diff options
Diffstat (limited to 'formats/pktline')
-rw-r--r-- | formats/pktline/decoder.go | 111 | ||||
-rw-r--r-- | formats/pktline/decoder_test.go | 85 | ||||
-rw-r--r-- | formats/pktline/doc.go | 59 | ||||
-rw-r--r-- | formats/pktline/encoder.go | 64 | ||||
-rw-r--r-- | formats/pktline/encoder_test.go | 50 |
5 files changed, 0 insertions, 369 deletions
diff --git a/formats/pktline/decoder.go b/formats/pktline/decoder.go deleted file mode 100644 index 789ba7d..0000000 --- a/formats/pktline/decoder.go +++ /dev/null @@ -1,111 +0,0 @@ -package pktline - -import ( - "errors" - "io" - "strconv" -) - -var ( - // ErrUnderflow is triggered when a line is shorter than the described length - ErrUnderflow = errors.New("unexpected string length (underflow)") - // ErrInvalidHeader invalid pktline header - ErrInvalidHeader = errors.New("invalid header") - // ErrInvalidLen ivanlid line length found, < 0 - ErrInvalidLen = errors.New("invalid length") -) - -// Decoder implements a pkt-line format decoder -type Decoder struct { - r io.Reader -} - -// NewDecoder returns a new Decoder -func NewDecoder(r io.Reader) *Decoder { - return &Decoder{r} -} - -// ReadLine reads and return one pkt-line line from the reader -func (d *Decoder) ReadLine() (string, error) { - return d.readLine() -} - -func (d *Decoder) readLine() (string, error) { - raw := make([]byte, HeaderLength) - if _, err := io.ReadFull(d.r, raw); err != nil { - return "", err - } - - header, err := strconv.ParseInt(string(raw), 16, 16) - if err != nil { - return "", ErrInvalidHeader - } - - if header == 0 { - return "", nil - } - - exp := int(header - HeaderLength) - if exp < 0 { - return "", ErrInvalidLen - } - - line := make([]byte, exp) - if read, err := io.ReadFull(d.r, line); err != nil { - if err == io.ErrUnexpectedEOF && read < exp { - return "", ErrUnderflow - } - - return "", err - } - - return string(line), nil -} - -// ReadBlock reads and return multiple pkt-line lines, it stops at the end -// of the reader or if a flush-pkt is reached -func (d *Decoder) ReadBlock() ([]string, error) { - var o []string - - for { - line, err := d.readLine() - if err == io.EOF { - return o, nil - } - - if err != nil { - return o, err - } - - if err == nil && line == "" { - return o, nil - } - - o = append(o, line) - } -} - -// ReadAll read and returns all the lines -func (d *Decoder) ReadAll() ([]string, error) { - result, err := d.ReadBlock() - if err != nil { - return result, err - } - - for { - lines, err := d.ReadBlock() - if err == io.EOF { - return result, nil - } - - if err != nil { - return result, err - } - - if err == nil && len(lines) == 0 { - return result, nil - } - - result = append(result, lines...) - } -} diff --git a/formats/pktline/decoder_test.go b/formats/pktline/decoder_test.go deleted file mode 100644 index e3cd2f4..0000000 --- a/formats/pktline/decoder_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package pktline - -import ( - "strings" - "testing" - - . "gopkg.in/check.v1" -) - -func Test(t *testing.T) { TestingT(t) } - -type DecoderSuite struct{} - -var _ = Suite(&DecoderSuite{}) - -func (s *DecoderSuite) TestReadLine(c *C) { - j := NewDecoder(strings.NewReader("0006a\n")) - - line, err := j.ReadLine() - c.Assert(err, IsNil) - c.Assert(line, Equals, "a\n") -} - -func (s *DecoderSuite) TestReadLineInvalidHeader(c *C) { - j := NewDecoder(strings.NewReader("foo\n")) - - _, err := j.ReadLine() - c.Assert(err, Equals, ErrInvalidHeader) -} - -func (s *DecoderSuite) TestReadLineBufferUnderflow(c *C) { - j := NewDecoder(strings.NewReader("00e7a\n")) - - line, err := j.ReadLine() - c.Assert(err, Equals, ErrUnderflow) - c.Assert(line, Equals, "") -} - -func (s *DecoderSuite) TestReadLineInvalidLen(c *C) { - j := NewDecoder(strings.NewReader("0001foo\n")) - - line, err := j.ReadLine() - c.Assert(err, Equals, ErrInvalidLen) - c.Assert(line, Equals, "") -} - -func (s *DecoderSuite) TestReadBlock(c *C) { - j := NewDecoder(strings.NewReader("0006a\n")) - - lines, err := j.ReadBlock() - c.Assert(err, IsNil) - c.Assert(lines, HasLen, 1) - c.Assert(lines[0], Equals, "a\n") -} - -func (s *DecoderSuite) TestReadBlockWithFlush(c *C) { - j := NewDecoder(strings.NewReader("0006a\n0006b\n00000006c\n")) - - lines, err := j.ReadBlock() - c.Assert(err, IsNil) - c.Assert(lines, HasLen, 2) - c.Assert(lines[0], Equals, "a\n") - c.Assert(lines[1], Equals, "b\n") -} - -func (s *DecoderSuite) TestReadBlockInvalidLen(c *C) { - j := NewDecoder(strings.NewReader("0001foo\n")) - - lines, err := j.ReadBlock() - c.Assert(err, Equals, ErrInvalidLen) - c.Assert(lines, HasLen, 0) -} - -func (s *DecoderSuite) TestReadAll(c *C) { - j := NewDecoder(strings.NewReader("0006a\n0006b\n00000006c\n0006d\n0006e\n")) - - lines, err := j.ReadAll() - c.Assert(err, IsNil) - c.Assert(lines, HasLen, 5) - c.Assert(lines[0], Equals, "a\n") - c.Assert(lines[1], Equals, "b\n") - c.Assert(lines[2], Equals, "c\n") - c.Assert(lines[3], Equals, "d\n") - c.Assert(lines[4], Equals, "e\n") -} diff --git a/formats/pktline/doc.go b/formats/pktline/doc.go deleted file mode 100644 index 1e14ec0..0000000 --- a/formats/pktline/doc.go +++ /dev/null @@ -1,59 +0,0 @@ -// Package pktline implements a encoder/decoder of pkt-line format -package pktline - -// pkt-line Format -// --------------- -// -// Much (but not all) of the payload is described around pkt-lines. -// -// A pkt-line is a variable length binary string. The first four bytes -// of the line, the pkt-len, indicates the total length of the line, -// in hexadecimal. The pkt-len includes the 4 bytes used to contain -// the length's hexadecimal representation. -// -// A pkt-line MAY contain binary data, so implementors MUST ensure -// pkt-line parsing/formatting routines are 8-bit clean. -// -// A non-binary line SHOULD BE terminated by an LF, which if present -// MUST be included in the total length. -// -// The maximum length of a pkt-line's data component is 65520 bytes. -// Implementations MUST NOT send pkt-line whose length exceeds 65524 -// (65520 bytes of payload + 4 bytes of length data). -// -// Implementations SHOULD NOT send an empty pkt-line ("0004"). -// -// A pkt-line with a length field of 0 ("0000"), called a flush-pkt, -// is a special case and MUST be handled differently than an empty -// pkt-line ("0004"). -// -// ---- -// pkt-line = data-pkt / flush-pkt -// -// data-pkt = pkt-len pkt-payload -// pkt-len = 4*(HEXDIG) -// pkt-payload = (pkt-len - 4)*(OCTET) -// -// flush-pkt = "0000" -// ---- -// -// Examples (as C-style strings): -// -// ---- -// pkt-line actual value -// --------------------------------- -// "0006a\n" "a\n" -// "0005a" "a" -// "000bfoobar\n" "foobar\n" -// "0004" "" -// ---- -// -// Extracted from: -// https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt - -const ( - // HeaderLength length of the pktline header - HeaderLength = 4 - // MaxLength max line length - MaxLength = 65524 -) diff --git a/formats/pktline/encoder.go b/formats/pktline/encoder.go deleted file mode 100644 index 18efa25..0000000 --- a/formats/pktline/encoder.go +++ /dev/null @@ -1,64 +0,0 @@ -package pktline - -import ( - "errors" - "fmt" - "strings" -) - -var ( - //ErrOverflow is triggered when the line length exceed the MaxLength - ErrOverflow = errors.New("unexpected string length (overflow)") -) - -// Encoder implements a pkt-line format encoder -type Encoder struct { - lines []string -} - -// NewEncoder returns a new Encoder -func NewEncoder() *Encoder { - return &Encoder{make([]string, 0)} -} - -// AddLine encode and adds a line to the encoder -func (e *Encoder) AddLine(line string) error { - le, err := EncodeFromString(line + "\n") - if err != nil { - return err - } - - e.lines = append(e.lines, le) - return nil -} - -// AddFlush adds a flush-pkt to the encoder -func (e *Encoder) AddFlush() { - e.lines = append(e.lines, "0000") -} - -// Reader returns a string.Reader over the encoder -func (e *Encoder) Reader() *strings.Reader { - data := strings.Join(e.lines, "") - - return strings.NewReader(data) -} - -// EncodeFromString encodes a string to pkt-line format -func EncodeFromString(line string) (string, error) { - return Encode([]byte(line)) -} - -// Encode encodes a byte slice to pkt-line format -func Encode(line []byte) (string, error) { - if line == nil { - return "0000", nil - } - - l := len(line) + HeaderLength - if l > MaxLength { - return "", ErrOverflow - } - - return fmt.Sprintf("%04x%s", l, line), nil -} diff --git a/formats/pktline/encoder_test.go b/formats/pktline/encoder_test.go deleted file mode 100644 index f718c33..0000000 --- a/formats/pktline/encoder_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package pktline - -import ( - "bytes" - "io/ioutil" - "strings" - - . "gopkg.in/check.v1" -) - -type EncoderSuite struct{} - -var _ = Suite(&EncoderSuite{}) - -func (s *EncoderSuite) TestEncode(c *C) { - line, err := Encode([]byte("a\n")) - c.Assert(err, IsNil) - c.Assert(string(line), Equals, "0006a\n") -} - -func (s *EncoderSuite) TestEncodeNil(c *C) { - line, err := Encode(nil) - c.Assert(err, IsNil) - c.Assert(string(line), Equals, "0000") -} - -func (s *EncoderSuite) TestEncodeOverflow(c *C) { - _, err := Encode(bytes.Repeat([]byte{'0'}, MaxLength+1)) - c.Assert(err, Equals, ErrOverflow) -} - -func (s *EncoderSuite) TestEncodeFromString(c *C) { - line, err := EncodeFromString("a\n") - c.Assert(err, IsNil) - c.Assert(string(line), Equals, "0006a\n") -} - -func (s *EncoderSuite) TestEncoder(c *C) { - e := NewEncoder() - c.Assert(e.AddLine("a"), IsNil) - e.AddFlush() - c.Assert(e.AddLine("b"), IsNil) - - over := strings.Repeat("0", MaxLength+1) - c.Assert(e.AddLine(over), Equals, ErrOverflow) - - r := e.Reader() - a, _ := ioutil.ReadAll(r) - c.Assert(string(a), Equals, "0006a\n00000006b\n") -} |