aboutsummaryrefslogtreecommitdiffstats
path: root/formats/packp/pktline
diff options
context:
space:
mode:
authorAlberto Cortés <alcortesm@gmail.com>2016-10-26 17:56:26 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2016-10-26 15:56:26 +0000
commit73fa9ef25a8af9c8337a4cf34a67cfe208f1a7c5 (patch)
tree66886d9b47e373b748c1bceafe1885e6f47868dd /formats/packp/pktline
parentf3ab3a6c73015b5ae9b2a4756dc646e1211cedb9 (diff)
downloadgo-git-73fa9ef25a8af9c8337a4cf34a67cfe208f1a7c5.tar.gz
Use advrefs in gituploadpackinfo (#92)
* add advrefs encoder and parser * modify advrefs encoder to resemble json encoder * turn advrefs parser into a decoder * clean code * improve documentation * improve documentation * clean code * upgrade to new pktline.Add and add Flush const to easy integration * gometalinter * Use packp/advrefs for GitUploadPackInfo parsing - GitUploadPackInfo now uses packp/advrefs instead of parsing the message by itself. - Capabilities has been moved from clients/common to packp to avoid a circular import. - Cleaning of advrefs_test code. - Add support for prefix encoding and decoding in advrefs. * clean advrefs test code * clean advrefs test code * clean advrefs test code * gometalinter * add pktline encoder * change pktline.EncodeFlush to pktline.Flush * make scanner tests use the encoder instead of Pktlines * check errors on flush and clean constants * ubstitute the PktLines type with a pktline.Encoder * use pktline.Encoder in all go-git * add example of pktline.Encodef() * add package overview * documentation * support symbolic links other than HEAD * simplify decoding of shallows * packp: fix mcuadros comments - all abbreviates removed (by visual inspection, some may remain) - all empty maps are initialized using make - simplify readRef with a switch - make decodeShallow malformed error more verbose - add pktline.Encoder.encodeLine - remove infamous panic in checkPayloadLength by refactoring out the whole function
Diffstat (limited to 'formats/packp/pktline')
-rw-r--r--formats/packp/pktline/encoder.go123
-rw-r--r--formats/packp/pktline/encoder_test.go249
-rw-r--r--formats/packp/pktline/pktlines.go140
-rw-r--r--formats/packp/pktline/pktlines_test.go231
-rw-r--r--formats/packp/pktline/scanner_test.go46
5 files changed, 402 insertions, 387 deletions
diff --git a/formats/packp/pktline/encoder.go b/formats/packp/pktline/encoder.go
new file mode 100644
index 0000000..0a88a9b
--- /dev/null
+++ b/formats/packp/pktline/encoder.go
@@ -0,0 +1,123 @@
+// Package pktline implements reading payloads form pkt-lines and encoding pkt-lines from payloads.
+package pktline
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+)
+
+// An Encoder writes pkt-lines to an output stream.
+type Encoder struct {
+ w io.Writer
+}
+
+const (
+ // MaxPayloadSize is the maximum payload size of a pkt-line in bytes.
+ MaxPayloadSize = 65516
+)
+
+var (
+ // FlushPkt are the contents of a flush-pkt pkt-line.
+ FlushPkt = []byte{'0', '0', '0', '0'}
+ // Flush is the payload to use with the Encode method to encode a flush-pkt.
+ Flush = []byte{}
+ // FlushString is the payload to use with the EncodeString method to encode a flush-pkt.
+ FlushString = ""
+ // ErrPayloadTooLong is returned by the Encode methods when any of the
+ // provided payloads is bigger than MaxPayloadSize.
+ ErrPayloadTooLong = errors.New("payload is too long")
+)
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ w: w,
+ }
+}
+
+// Flush encodes a flush-pkt to the output stream.
+func (e *Encoder) Flush() error {
+ _, err := e.w.Write(FlushPkt)
+ return err
+}
+
+// Encode encodes a pkt-line with the payload specified and write it to
+// the output stream. If several payloads are specified, each of them
+// will get streamed in their own pkt-lines.
+func (e *Encoder) Encode(payloads ...[]byte) error {
+ for _, p := range payloads {
+ if err := e.encodeLine(p); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (e *Encoder) encodeLine(p []byte) error {
+ if len(p) > MaxPayloadSize {
+ return ErrPayloadTooLong
+ }
+
+ if bytes.Equal(p, Flush) {
+ if err := e.Flush(); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ n := len(p) + 4
+ if _, err := e.w.Write(asciiHex16(n)); err != nil {
+ return err
+ }
+ if _, err := e.w.Write(p); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Returns the hexadecimal ascii representation of the 16 less
+// significant bits of n. The length of the returned slice will always
+// be 4. Example: if n is 1234 (0x4d2), the return value will be
+// []byte{'0', '4', 'd', '2'}.
+func asciiHex16(n int) []byte {
+ var ret [4]byte
+ ret[0] = byteToASCIIHex(byte(n & 0xf000 >> 12))
+ ret[1] = byteToASCIIHex(byte(n & 0x0f00 >> 8))
+ ret[2] = byteToASCIIHex(byte(n & 0x00f0 >> 4))
+ ret[3] = byteToASCIIHex(byte(n & 0x000f))
+
+ return ret[:]
+}
+
+// turns a byte into its hexadecimal ascii representation. Example:
+// from 11 (0xb) to 'b'.
+func byteToASCIIHex(n byte) byte {
+ if n < 10 {
+ return '0' + n
+ }
+
+ return 'a' - 10 + n
+}
+
+// EncodeString works similarly as Encode but payloads are specified as strings.
+func (e *Encoder) EncodeString(payloads ...string) error {
+ for _, p := range payloads {
+ if err := e.Encode([]byte(p)); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// Encodef encodes a single pkt-line with the payload formatted as
+// the format specifier and the rest of the arguments suggest.
+func (e *Encoder) Encodef(format string, a ...interface{}) error {
+ return e.EncodeString(
+ fmt.Sprintf(format, a...),
+ )
+}
diff --git a/formats/packp/pktline/encoder_test.go b/formats/packp/pktline/encoder_test.go
new file mode 100644
index 0000000..5990ea5
--- /dev/null
+++ b/formats/packp/pktline/encoder_test.go
@@ -0,0 +1,249 @@
+package pktline_test
+
+import (
+ "bytes"
+ "os"
+ "strings"
+ "testing"
+
+ "gopkg.in/src-d/go-git.v4/formats/packp/pktline"
+
+ . "gopkg.in/check.v1"
+)
+
+func Test(t *testing.T) { TestingT(t) }
+
+type SuiteEncoder struct{}
+
+var _ = Suite(&SuiteEncoder{})
+
+func (s *SuiteEncoder) TestFlush(c *C) {
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+
+ err := e.Flush()
+ c.Assert(err, IsNil)
+
+ obtained := buf.Bytes()
+ c.Assert(obtained, DeepEquals, pktline.FlushPkt)
+}
+
+func (s *SuiteEncoder) TestEncode(c *C) {
+ for i, test := range [...]struct {
+ input [][]byte
+ expected []byte
+ }{
+ {
+ input: [][]byte{
+ []byte("hello\n"),
+ },
+ expected: []byte("000ahello\n"),
+ }, {
+ input: [][]byte{
+ []byte("hello\n"),
+ pktline.Flush,
+ },
+ expected: []byte("000ahello\n0000"),
+ }, {
+ input: [][]byte{
+ []byte("hello\n"),
+ []byte("world!\n"),
+ []byte("foo"),
+ },
+ expected: []byte("000ahello\n000bworld!\n0007foo"),
+ }, {
+ input: [][]byte{
+ []byte("hello\n"),
+ pktline.Flush,
+ []byte("world!\n"),
+ []byte("foo"),
+ pktline.Flush,
+ },
+ expected: []byte("000ahello\n0000000bworld!\n0007foo0000"),
+ }, {
+ input: [][]byte{
+ []byte(strings.Repeat("a", pktline.MaxPayloadSize)),
+ },
+ expected: []byte(
+ "fff0" + strings.Repeat("a", pktline.MaxPayloadSize)),
+ }, {
+ input: [][]byte{
+ []byte(strings.Repeat("a", pktline.MaxPayloadSize)),
+ []byte(strings.Repeat("b", pktline.MaxPayloadSize)),
+ },
+ expected: []byte(
+ "fff0" + strings.Repeat("a", pktline.MaxPayloadSize) +
+ "fff0" + strings.Repeat("b", pktline.MaxPayloadSize)),
+ },
+ } {
+ comment := Commentf("input %d = %v\n", i, test.input)
+
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+
+ err := e.Encode(test.input...)
+ c.Assert(err, IsNil, comment)
+
+ c.Assert(buf.Bytes(), DeepEquals, test.expected, comment)
+ }
+}
+
+func (s *SuiteEncoder) TestEncodeErrPayloadTooLong(c *C) {
+ for i, input := range [...][][]byte{
+ [][]byte{
+ []byte(strings.Repeat("a", pktline.MaxPayloadSize+1)),
+ },
+ [][]byte{
+ []byte("hello world!"),
+ []byte(strings.Repeat("a", pktline.MaxPayloadSize+1)),
+ },
+ [][]byte{
+ []byte("hello world!"),
+ []byte(strings.Repeat("a", pktline.MaxPayloadSize+1)),
+ []byte("foo"),
+ },
+ } {
+ comment := Commentf("input %d = %v\n", i, input)
+
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+
+ err := e.Encode(input...)
+ c.Assert(err, Equals, pktline.ErrPayloadTooLong, comment)
+ }
+}
+
+func (s *SuiteEncoder) TestEncodeStrings(c *C) {
+ for i, test := range [...]struct {
+ input []string
+ expected []byte
+ }{
+ {
+ input: []string{
+ "hello\n",
+ },
+ expected: []byte("000ahello\n"),
+ }, {
+ input: []string{
+ "hello\n",
+ pktline.FlushString,
+ },
+ expected: []byte("000ahello\n0000"),
+ }, {
+ input: []string{
+ "hello\n",
+ "world!\n",
+ "foo",
+ },
+ expected: []byte("000ahello\n000bworld!\n0007foo"),
+ }, {
+ input: []string{
+ "hello\n",
+ pktline.FlushString,
+ "world!\n",
+ "foo",
+ pktline.FlushString,
+ },
+ expected: []byte("000ahello\n0000000bworld!\n0007foo0000"),
+ }, {
+ input: []string{
+ strings.Repeat("a", pktline.MaxPayloadSize),
+ },
+ expected: []byte(
+ "fff0" + strings.Repeat("a", pktline.MaxPayloadSize)),
+ }, {
+ input: []string{
+ strings.Repeat("a", pktline.MaxPayloadSize),
+ strings.Repeat("b", pktline.MaxPayloadSize),
+ },
+ expected: []byte(
+ "fff0" + strings.Repeat("a", pktline.MaxPayloadSize) +
+ "fff0" + strings.Repeat("b", pktline.MaxPayloadSize)),
+ },
+ } {
+ comment := Commentf("input %d = %v\n", i, test.input)
+
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+
+ err := e.EncodeString(test.input...)
+ c.Assert(err, IsNil, comment)
+ c.Assert(buf.Bytes(), DeepEquals, test.expected, comment)
+ }
+}
+
+func (s *SuiteEncoder) TestEncodeStringErrPayloadTooLong(c *C) {
+ for i, input := range [...][]string{
+ []string{
+ strings.Repeat("a", pktline.MaxPayloadSize+1),
+ },
+ []string{
+ "hello world!",
+ strings.Repeat("a", pktline.MaxPayloadSize+1),
+ },
+ []string{
+ "hello world!",
+ strings.Repeat("a", pktline.MaxPayloadSize+1),
+ "foo",
+ },
+ } {
+ comment := Commentf("input %d = %v\n", i, input)
+
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+
+ err := e.EncodeString(input...)
+ c.Assert(err, Equals, pktline.ErrPayloadTooLong, comment)
+ }
+}
+
+func (s *SuiteEncoder) TestEncodef(c *C) {
+ format := " %s %d\n"
+ str := "foo"
+ d := 42
+
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+
+ err := e.Encodef(format, str, d)
+ c.Assert(err, IsNil)
+
+ expected := []byte("000c foo 42\n")
+ c.Assert(buf.Bytes(), DeepEquals, expected)
+}
+
+func ExampleEncoder() {
+ // Create an encoder that writes pktlines to stdout.
+ e := pktline.NewEncoder(os.Stdout)
+
+ // Encode some data as a new pkt-line.
+ _ = e.Encode([]byte("data\n")) // error checks removed for brevity
+
+ // Encode a flush-pkt.
+ _ = e.Flush()
+
+ // Encode a couple of byte slices and a flush in one go. Each of
+ // them will end up as payloads of their own pktlines.
+ _ = e.Encode(
+ []byte("hello\n"),
+ []byte("world!\n"),
+ pktline.Flush,
+ )
+
+ // You can also encode strings:
+ _ = e.EncodeString(
+ "foo\n",
+ "bar\n",
+ pktline.FlushString,
+ )
+
+ // You can also format and encode a payload:
+ _ = e.Encodef(" %s %d\n", "foo", 42)
+ // Output:
+ // 0009data
+ // 0000000ahello
+ // 000bworld!
+ // 00000008foo
+ // 0008bar
+ // 0000000c foo 42
+}
diff --git a/formats/packp/pktline/pktlines.go b/formats/packp/pktline/pktlines.go
deleted file mode 100644
index c19aa2e..0000000
--- a/formats/packp/pktline/pktlines.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Package pktline implements reading payloads form pkt-lines and creating pkt-lines from payloads.
-package pktline
-
-import (
- "bytes"
- "errors"
- "io"
- "strings"
-)
-
-const (
- // MaxPayloadSize is the maximum payload size of a pkt-line in bytes.
- MaxPayloadSize = 65516
-)
-
-var (
- flush = []byte{'0', '0', '0', '0'}
-)
-
-// PktLines values represent a succession of pkt-lines. Values from
-// this type are not zero-value safe, use the New function instead.
-type PktLines struct {
- r io.Reader
-}
-
-var (
- // ErrPayloadTooLong is returned by the Add methods when any of the
- // provided payloads is bigger than MaxPayloadSize.
- ErrPayloadTooLong = errors.New("payload is too long")
- // ErrEmptyPayload is returned by the Add methods when an empty
- // payload is provided.
- ErrEmptyPayload = errors.New("cannot add empty payloads")
-)
-
-// New returns an empty PktLines (with no payloads) ready to be used.
-func New() *PktLines {
- return &PktLines{
- r: bytes.NewReader(nil),
- }
-}
-
-// AddFlush adds a flush-pkt to p.
-func (p *PktLines) AddFlush() {
- p.r = io.MultiReader(p.r, bytes.NewReader(flush))
-}
-
-// Add adds the slices in pp as the payloads of a
-// corresponding number of pktlines.
-func (p *PktLines) Add(pp ...[]byte) error {
- tmp := []io.Reader{p.r}
- for _, p := range pp {
- if err := add(&tmp, p); err != nil {
- return err
- }
- }
- p.r = io.MultiReader(tmp...)
-
- return nil
-}
-
-func add(dst *[]io.Reader, e []byte) error {
- if err := checkPayloadLength(len(e)); err != nil {
- return err
- }
-
- n := len(e) + 4
- *dst = append(*dst, bytes.NewReader(asciiHex16(n)))
- *dst = append(*dst, bytes.NewReader(e))
-
- return nil
-}
-
-func checkPayloadLength(n int) error {
- switch {
- case n < 0:
- panic("unexpected negative payload length")
- case n == 0:
- return ErrEmptyPayload
- case n > MaxPayloadSize:
- return ErrPayloadTooLong
- default:
- return nil
- }
-}
-
-// Returns the hexadecimal ascii representation of the 16 less
-// significant bits of n. The length of the returned slice will always
-// be 4. Example: if n is 1234 (0x4d2), the return value will be
-// []byte{'0', '4', 'd', '2'}.
-func asciiHex16(n int) []byte {
- var ret [4]byte
- ret[0] = byteToASCIIHex(byte(n & 0xf000 >> 12))
- ret[1] = byteToASCIIHex(byte(n & 0x0f00 >> 8))
- ret[2] = byteToASCIIHex(byte(n & 0x00f0 >> 4))
- ret[3] = byteToASCIIHex(byte(n & 0x000f))
-
- return ret[:]
-}
-
-// turns a byte into its hexadecimal ascii representation. Example:
-// from 11 (0xb) to 'b'.
-func byteToASCIIHex(n byte) byte {
- if n < 10 {
- return '0' + n
- }
-
- return 'a' - 10 + n
-}
-
-// AddString adds the strings in pp as payloads of a
-// corresponding number of pktlines.
-func (p *PktLines) AddString(pp ...string) error {
- tmp := []io.Reader{p.r}
- for _, p := range pp {
- if err := addString(&tmp, p); err != nil {
- return err
- }
- }
-
- p.r = io.MultiReader(tmp...)
-
- return nil
-}
-
-func addString(dst *[]io.Reader, s string) error {
- if err := checkPayloadLength(len(s)); err != nil {
- return err
- }
-
- n := len(s) + 4
- *dst = append(*dst, bytes.NewReader(asciiHex16(n)))
- *dst = append(*dst, strings.NewReader(s))
-
- return nil
-}
-
-// Read reads the pktlines for the payloads added so far.
-func (p *PktLines) Read(b []byte) (n int, err error) {
- return p.r.Read(b)
-}
diff --git a/formats/packp/pktline/pktlines_test.go b/formats/packp/pktline/pktlines_test.go
deleted file mode 100644
index e0ba16b..0000000
--- a/formats/packp/pktline/pktlines_test.go
+++ /dev/null
@@ -1,231 +0,0 @@
-package pktline_test
-
-import (
- "io"
- "io/ioutil"
- "os"
- "strings"
- "testing"
-
- "gopkg.in/src-d/go-git.v4/formats/packp/pktline"
-
- . "gopkg.in/check.v1"
-)
-
-func Test(t *testing.T) { TestingT(t) }
-
-type SuitePktLine struct {
-}
-
-var _ = Suite(&SuitePktLine{})
-
-func (s *SuitePktLine) TestNewIsEmpty(c *C) {
- p := pktline.New()
-
- b, err := ioutil.ReadAll(p)
- c.Assert(err, IsNil)
- c.Assert(b, DeepEquals, []byte{})
-}
-
-func (s *SuitePktLine) TestAddFlush(c *C) {
- p := pktline.New()
- p.AddFlush()
-
- b, err := ioutil.ReadAll(p)
- c.Assert(err, IsNil)
- c.Assert(string(b), DeepEquals, "0000")
-}
-
-func (s *SuitePktLine) TestAdd(c *C) {
- for i, test := range [...]struct {
- input [][]byte
- expected []byte
- }{
- {
- input: [][]byte{
- []byte("hello\n"),
- },
- expected: []byte("000ahello\n"),
- }, {
- input: [][]byte{
- []byte("hello\n"),
- []byte("world!\n"),
- []byte("foo"),
- },
- expected: []byte("000ahello\n000bworld!\n0007foo"),
- }, {
- input: [][]byte{
- []byte(strings.Repeat("a", pktline.MaxPayloadSize)),
- },
- expected: []byte(
- "fff0" + strings.Repeat("a", pktline.MaxPayloadSize)),
- }, {
- input: [][]byte{
- []byte(strings.Repeat("a", pktline.MaxPayloadSize)),
- []byte(strings.Repeat("b", pktline.MaxPayloadSize)),
- },
- expected: []byte(
- "fff0" + strings.Repeat("a", pktline.MaxPayloadSize) +
- "fff0" + strings.Repeat("b", pktline.MaxPayloadSize)),
- },
- } {
- p := pktline.New()
- err := p.Add(test.input...)
- c.Assert(err, IsNil, Commentf("input %d = %v", i, test.input))
-
- obtained, err := ioutil.ReadAll(p)
- c.Assert(err, IsNil, Commentf("input %d = %v", i, test.input))
-
- c.Assert(obtained, DeepEquals, test.expected,
- Commentf("input %d = %v", i, test.input))
- }
-}
-
-func (s *SuitePktLine) TestAddErrEmptyPayload(c *C) {
- for _, input := range [...][][]byte{
- [][]byte{
- []byte{},
- },
- [][]byte{
- []byte(nil),
- },
- [][]byte{
- []byte("hello world!"),
- []byte{},
- },
- [][]byte{
- []byte{},
- []byte("hello world!"),
- },
- } {
- p := pktline.New()
- err := p.Add(input...)
- c.Assert(err, Equals, pktline.ErrEmptyPayload)
- }
-}
-
-func (s *SuitePktLine) TestAddErrPayloadTooLong(c *C) {
- for _, input := range [...][][]byte{
- [][]byte{
- []byte(strings.Repeat("a", pktline.MaxPayloadSize+1)),
- },
- [][]byte{
- []byte("hello world!"),
- []byte(strings.Repeat("a", pktline.MaxPayloadSize+1)),
- },
- [][]byte{
- []byte("hello world!"),
- []byte(strings.Repeat("a", pktline.MaxPayloadSize+1)),
- []byte("foo"),
- },
- } {
- p := pktline.New()
- err := p.Add(input...)
- c.Assert(err, Equals, pktline.ErrPayloadTooLong,
- Commentf("%v\n", input))
- }
-}
-
-func (s *SuitePktLine) TestAddString(c *C) {
- for i, test := range [...]struct {
- input []string
- expected []byte
- }{
- {
- input: []string{
- "hello\n",
- },
- expected: []byte("000ahello\n"),
- }, {
- input: []string{
- "hello\n",
- "world!\n",
- "foo",
- },
- expected: []byte("000ahello\n000bworld!\n0007foo"),
- }, {
- input: []string{
- strings.Repeat("a", pktline.MaxPayloadSize),
- },
- expected: []byte(
- "fff0" + strings.Repeat("a", pktline.MaxPayloadSize)),
- }, {
- input: []string{
- strings.Repeat("a", pktline.MaxPayloadSize),
- strings.Repeat("b", pktline.MaxPayloadSize),
- },
- expected: []byte(
- "fff0" + strings.Repeat("a", pktline.MaxPayloadSize) +
- "fff0" + strings.Repeat("b", pktline.MaxPayloadSize)),
- },
- } {
- p := pktline.New()
- err := p.AddString(test.input...)
- c.Assert(err, IsNil, Commentf("input %d = %v", i, test.input))
-
- obtained, err := ioutil.ReadAll(p)
- c.Assert(err, IsNil, Commentf("input %d = %v", i, test.input))
-
- c.Assert(obtained, DeepEquals, test.expected,
- Commentf("input %d = %v", i, test.input))
- }
-}
-
-func (s *SuitePktLine) TestAddStringErrEmptyPayload(c *C) {
- for _, input := range [...][]string{
- []string{""},
- []string{"hello world!", ""},
- []string{"", "hello world!"},
- } {
- p := pktline.New()
- err := p.AddString(input...)
- c.Assert(err, Equals, pktline.ErrEmptyPayload)
- }
-}
-
-func (s *SuitePktLine) TestAddStringErrPayloadTooLong(c *C) {
- for _, input := range [...][]string{
- []string{
- strings.Repeat("a", pktline.MaxPayloadSize+1),
- },
- []string{
- "hello world!",
- strings.Repeat("a", pktline.MaxPayloadSize+1),
- },
- []string{
- "hello world!",
- strings.Repeat("a", pktline.MaxPayloadSize+1),
- "foo",
- },
- } {
- p := pktline.New()
- err := p.AddString(input...)
- c.Assert(err, Equals, pktline.ErrPayloadTooLong,
- Commentf("%v\n", input))
- }
-}
-
-func ExamplePktLines() {
- // Create an empty collection of pktlines.
- p := pktline.New()
-
- // Add two strings as payloads ("foo\n" and "bar\n"), they will
- // end up as two consecutive pktlines.
- p.AddString("foo\n", "bar\n") // error checks removed for brevity
-
- // You can also add byte slices as payloads...
- p.Add([]byte("hello\n"), []byte("world!\n"))
-
- // Add a flush-pkt.
- p.AddFlush()
-
- // PktLines are Readers, so you can directly read the full sequence.
- io.Copy(os.Stdout, p)
-
- // Output:
- // 0008foo
- // 0008bar
- // 000ahello
- // 000bworld!
- // 0000
-}
diff --git a/formats/packp/pktline/scanner_test.go b/formats/packp/pktline/scanner_test.go
index de0f8df..b5a3c7d 100644
--- a/formats/packp/pktline/scanner_test.go
+++ b/formats/packp/pktline/scanner_test.go
@@ -1,6 +1,7 @@
package pktline_test
import (
+ "bytes"
"fmt"
"io"
"strings"
@@ -41,11 +42,14 @@ func (s *SuiteScanner) TestEmptyReader(c *C) {
}
func (s *SuiteScanner) TestFlush(c *C) {
- p := pktline.New()
- p.AddFlush()
- sc := pktline.NewScanner(p)
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+ err := e.Flush()
+ c.Assert(err, IsNil)
+ sc := pktline.NewScanner(&buf)
c.Assert(sc.Scan(), Equals, true)
+
payload := sc.Bytes()
c.Assert(len(payload), Equals, 0)
}
@@ -70,14 +74,16 @@ func (s *SuiteScanner) TestScanAndPayload(c *C) {
strings.Repeat("a", pktline.MaxPayloadSize),
strings.Repeat("a", pktline.MaxPayloadSize-1) + "\n",
} {
- p := pktline.New()
- err := p.AddString(test)
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+ err := e.EncodeString(test)
c.Assert(err, IsNil,
Commentf("input len=%x, contents=%.10q\n", len(test), test))
- sc := pktline.NewScanner(p)
+ sc := pktline.NewScanner(&buf)
c.Assert(sc.Scan(), Equals, true,
Commentf("test = %.20q...", test))
+
obtained := sc.Bytes()
c.Assert(obtained, DeepEquals, []byte(test),
Commentf("in = %.20q out = %.20q", test, string(obtained)))
@@ -107,16 +113,19 @@ func (s *SuiteScanner) TestSkip(c *C) {
expected: []byte("third"),
},
} {
- p := pktline.New()
- err := p.AddString(test.input...)
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+ err := e.EncodeString(test.input...)
c.Assert(err, IsNil)
- sc := pktline.NewScanner(p)
+
+ sc := pktline.NewScanner(&buf)
for i := 0; i < test.n; i++ {
c.Assert(sc.Scan(), Equals, true,
Commentf("scan error = %s", sc.Err()))
}
c.Assert(sc.Scan(), Equals, true,
Commentf("scan error = %s", sc.Err()))
+
obtained := sc.Bytes()
c.Assert(obtained, DeepEquals, test.expected,
Commentf("\nin = %.20q\nout = %.20q\nexp = %.20q",
@@ -125,10 +134,12 @@ func (s *SuiteScanner) TestSkip(c *C) {
}
func (s *SuiteScanner) TestEOF(c *C) {
- p := pktline.New()
- err := p.AddString("first", "second")
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+ err := e.EncodeString("first", "second")
c.Assert(err, IsNil)
- sc := pktline.NewScanner(p)
+
+ sc := pktline.NewScanner(&buf)
for sc.Scan() {
}
c.Assert(sc.Err(), IsNil)
@@ -164,19 +175,22 @@ func (s *SuiteScanner) TestReadSomeSections(c *C) {
// 0000
// and so on
func sectionsExample(c *C, nSections, nLines int) io.Reader {
- p := pktline.New()
+ var buf bytes.Buffer
+ e := pktline.NewEncoder(&buf)
+
for section := 0; section < nSections; section++ {
ss := []string{}
for line := 0; line < nLines; line++ {
line := fmt.Sprintf(" %d.%d\n", section, line)
ss = append(ss, line)
}
- err := p.AddString(ss...)
+ err := e.EncodeString(ss...)
+ c.Assert(err, IsNil)
+ err = e.Flush()
c.Assert(err, IsNil)
- p.AddFlush()
}
- return p
+ return &buf
}
func ExampleScanner() {