Fast implementation of Git in pure Go

Revert "pktline: Make Reader/Writer structs"

This reverts commit 7f0a20840fa3efc51c2a2fc80c1f82e030e91f44.

runxiyu.tngl.sh 0e05e5fb c7e4dc3b

verified
+33 -49
+26 -35
pktline/pktline.go
··· 27 StatusResponseEnd 28 ) 29 30 - // Reader reads pkt-line data from an io.Reader. 31 - type Reader struct { 32 - r io.Reader 33 - } 34 - 35 - // NewReader returns a Reader that reads from r. 36 - func NewReader(r io.Reader) *Reader { 37 - return &Reader{r: r} 38 - } 39 - 40 - // ReadLine reads a single pkt-line from the underlying reader into buf. 41 // It returns the payload slice, number of payload bytes, and a status. 42 - func (pr *Reader) ReadLine(buf []byte) ([]byte, int, Status, error) { 43 var header [4]byte 44 - if _, err := io.ReadFull(pr.r, header[:]); err != nil { 45 if errors.Is(err, io.EOF) { 46 return nil, 0, StatusEOF, io.EOF 47 } ··· 73 if n > len(buf) { 74 return nil, 0, StatusEOF, ErrBufferTooSmall 75 } 76 - if _, err := io.ReadFull(pr.r, buf[:n]); err != nil { 77 if errors.Is(err, io.ErrUnexpectedEOF) { 78 return nil, 0, StatusEOF, io.ErrUnexpectedEOF 79 } 80 return nil, 0, StatusEOF, err 81 } 82 return buf[:n], n, StatusData, nil 83 - } 84 - 85 - // Writer writes pkt-line data to an io.Writer. 86 - type Writer struct { 87 - w io.Writer 88 - } 89 - 90 - // NewWriter returns a Writer that writes to w. 91 - func NewWriter(w io.Writer) *Writer { 92 - return &Writer{w: w} 93 } 94 95 // WriteLine writes a single pkt-line with data as its payload. 96 - func (pw *Writer) WriteLine(data []byte) error { 97 if len(data) > maxPacketDataLen { 98 return ErrPacketTooLarge 99 } 100 var header [4]byte 101 setHeader(header[:], len(data)+4) 102 - if _, err := pw.w.Write(header[:]); err != nil { 103 return err 104 } 105 if len(data) == 0 { 106 return nil 107 } 108 - _, err := pw.w.Write(data) 109 return err 110 } 111 112 // Flush writes a flush-pkt ("0000"). 113 - func (pw *Writer) Flush() error { 114 - _, err := io.WriteString(pw.w, "0000") 115 - return err 116 } 117 118 // Delim writes a delim-pkt ("0001"). 119 - func (pw *Writer) Delim() error { 120 - _, err := io.WriteString(pw.w, "0001") 121 - return err 122 } 123 124 // ResponseEnd writes a response-end pkt ("0002"). 125 - func (pw *Writer) ResponseEnd() error { 126 - _, err := io.WriteString(pw.w, "0002") 127 return err 128 } 129
··· 27 StatusResponseEnd 28 ) 29 30 + // ReadLine reads a single pkt-line from r into buf. 31 // It returns the payload slice, number of payload bytes, and a status. 32 + func ReadLine(r io.Reader, buf []byte) ([]byte, int, Status, error) { 33 + if r == nil { 34 + return nil, 0, StatusEOF, ErrInvalidHeader 35 + } 36 var header [4]byte 37 + if _, err := io.ReadFull(r, header[:]); err != nil { 38 if errors.Is(err, io.EOF) { 39 return nil, 0, StatusEOF, io.EOF 40 } ··· 66 if n > len(buf) { 67 return nil, 0, StatusEOF, ErrBufferTooSmall 68 } 69 + if _, err := io.ReadFull(r, buf[:n]); err != nil { 70 if errors.Is(err, io.ErrUnexpectedEOF) { 71 return nil, 0, StatusEOF, io.ErrUnexpectedEOF 72 } 73 return nil, 0, StatusEOF, err 74 } 75 return buf[:n], n, StatusData, nil 76 } 77 78 // WriteLine writes a single pkt-line with data as its payload. 79 + func WriteLine(w io.Writer, data []byte) error { 80 + if w == nil { 81 + return ErrInvalidHeader 82 + } 83 if len(data) > maxPacketDataLen { 84 return ErrPacketTooLarge 85 } 86 var header [4]byte 87 setHeader(header[:], len(data)+4) 88 + if _, err := w.Write(header[:]); err != nil { 89 return err 90 } 91 if len(data) == 0 { 92 return nil 93 } 94 + _, err := w.Write(data) 95 return err 96 } 97 98 // Flush writes a flush-pkt ("0000"). 99 + func Flush(w io.Writer) error { 100 + return writeLiteral(w, "0000") 101 } 102 103 // Delim writes a delim-pkt ("0001"). 104 + func Delim(w io.Writer) error { 105 + return writeLiteral(w, "0001") 106 } 107 108 // ResponseEnd writes a response-end pkt ("0002"). 109 + func ResponseEnd(w io.Writer) error { 110 + return writeLiteral(w, "0002") 111 + } 112 + 113 + func writeLiteral(w io.Writer, s string) error { 114 + if w == nil { 115 + return ErrInvalidHeader 116 + } 117 + _, err := io.WriteString(w, s) 118 return err 119 } 120
+7 -14
pktline/pktline_test.go
··· 10 func TestWriteReadLineRoundtrip(t *testing.T) { 11 var buf bytes.Buffer 12 payload := []byte("hello\n") 13 - pw := NewWriter(&buf) 14 - if err := pw.WriteLine(payload); err != nil { 15 t.Fatalf("WriteLine: %v", err) 16 } 17 18 dst := make([]byte, 64) 19 - pr := NewReader(&buf) 20 - line, n, status, err := pr.ReadLine(dst) 21 if err != nil { 22 t.Fatalf("ReadLine: %v", err) 23 } ··· 45 for _, tt := range tests { 46 t.Run(tt.name, func(t *testing.T) { 47 r := bytes.NewBufferString(tt.input) 48 - pr := NewReader(r) 49 dst := make([]byte, 16) 50 - line, n, status, err := pr.ReadLine(dst) 51 if err != nil { 52 t.Fatalf("ReadLine: %v", err) 53 } ··· 63 64 func TestReadLineInvalidHeader(t *testing.T) { 65 r := bytes.NewBufferString("zzzz") 66 - pr := NewReader(r) 67 dst := make([]byte, 16) 68 - _, _, _, err := pr.ReadLine(dst) 69 if !errors.Is(err, ErrInvalidHeader) { 70 t.Fatalf("expected ErrInvalidHeader, got %v", err) 71 } ··· 74 func TestReadLineBufferTooSmall(t *testing.T) { 75 var buf bytes.Buffer 76 payload := []byte("abcd") 77 - pw := NewWriter(&buf) 78 - if err := pw.WriteLine(payload); err != nil { 79 t.Fatalf("WriteLine: %v", err) 80 } 81 dst := make([]byte, 2) 82 - pr := NewReader(&buf) 83 - _, _, _, err := pr.ReadLine(dst) 84 if !errors.Is(err, ErrBufferTooSmall) { 85 t.Fatalf("expected ErrBufferTooSmall, got %v", err) 86 } ··· 88 89 func TestWriteLineTooLarge(t *testing.T) { 90 payload := make([]byte, maxPacketDataLen+1) 91 - pw := NewWriter(io.Discard) 92 - if err := pw.WriteLine(payload); !errors.Is(err, ErrPacketTooLarge) { 93 t.Fatalf("expected ErrPacketTooLarge, got %v", err) 94 } 95 }
··· 10 func TestWriteReadLineRoundtrip(t *testing.T) { 11 var buf bytes.Buffer 12 payload := []byte("hello\n") 13 + if err := WriteLine(&buf, payload); err != nil { 14 t.Fatalf("WriteLine: %v", err) 15 } 16 17 dst := make([]byte, 64) 18 + line, n, status, err := ReadLine(&buf, dst) 19 if err != nil { 20 t.Fatalf("ReadLine: %v", err) 21 } ··· 43 for _, tt := range tests { 44 t.Run(tt.name, func(t *testing.T) { 45 r := bytes.NewBufferString(tt.input) 46 dst := make([]byte, 16) 47 + line, n, status, err := ReadLine(r, dst) 48 if err != nil { 49 t.Fatalf("ReadLine: %v", err) 50 } ··· 60 61 func TestReadLineInvalidHeader(t *testing.T) { 62 r := bytes.NewBufferString("zzzz") 63 dst := make([]byte, 16) 64 + _, _, _, err := ReadLine(r, dst) 65 if !errors.Is(err, ErrInvalidHeader) { 66 t.Fatalf("expected ErrInvalidHeader, got %v", err) 67 } ··· 70 func TestReadLineBufferTooSmall(t *testing.T) { 71 var buf bytes.Buffer 72 payload := []byte("abcd") 73 + if err := WriteLine(&buf, payload); err != nil { 74 t.Fatalf("WriteLine: %v", err) 75 } 76 dst := make([]byte, 2) 77 + _, _, _, err := ReadLine(&buf, dst) 78 if !errors.Is(err, ErrBufferTooSmall) { 79 t.Fatalf("expected ErrBufferTooSmall, got %v", err) 80 } ··· 82 83 func TestWriteLineTooLarge(t *testing.T) { 84 payload := make([]byte, maxPacketDataLen+1) 85 + if err := WriteLine(io.Discard, payload); !errors.Is(err, ErrPacketTooLarge) { 86 t.Fatalf("expected ErrPacketTooLarge, got %v", err) 87 } 88 }