Skip to content

Commit

Permalink
Merge pull request mailru#77 from erikdubbelboer/readcloser
Browse files Browse the repository at this point in the history
Add ReadCloser method to jwriter and buffer
  • Loading branch information
gobwas authored Feb 17, 2017
2 parents 9762c86 + ce0e787 commit 7a67b2a
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
54 changes: 54 additions & 0 deletions buffer/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,57 @@ func (b *Buffer) BuildBytes(reuse ...[]byte) []byte {

return ret
}

type readCloser struct {
offset int
bufs [][]byte
}

func (r *readCloser) Read(p []byte) (n int, err error) {
for _, buf := range r.bufs {
// Copy as much as we can.
x := copy(p[n:], buf[r.offset:])
n += x // Increment how much we filled.

// Did we empty the whole buffer?
if r.offset+x == len(buf) {
// On to the next buffer.
r.offset = 0
r.bufs = r.bufs[1:]

// We can release this buffer.
putBuf(buf)
} else {
r.offset += x
}

if n == len(p) {
break
}
}
// No buffers left or nothing read?
if len(r.bufs) == 0 {
err = io.EOF
}
return
}

func (r *readCloser) Close() error {
// Release all remainig buffers.
for _, buf := range r.bufs {
putBuf(buf)
}

return nil
}

// ReadCloser creates an io.ReadCloser with all the contents of the buffer.
func (b *Buffer) ReadCloser() io.ReadCloser {
ret := &readCloser{0, append(b.bufs, b.Buf)}

b.bufs = nil
b.toPool = nil
b.Buf = nil

return ret
}
28 changes: 28 additions & 0 deletions buffer/pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,31 @@ func TestDumpTo(t *testing.T) {
t.Errorf("DumpTo() = %v; want %v", n, len(want))
}
}

func TestReadCloser(t *testing.T) {
var b Buffer
var want []byte

s := "test"
for i := 0; i < 1000; i++ {
b.AppendBytes([]byte(s))
want = append(want, s...)
}

out := &bytes.Buffer{}
rc := b.ReadCloser()
n, err := out.ReadFrom(rc)
if err != nil {
t.Errorf("ReadCloser() error: %v", err)
}
rc.Close() // Will always return nil

got := out.Bytes()
if !bytes.Equal(got, want) {
t.Errorf("DumpTo(): got %v; want %v", got, want)
}

if n != int64(len(want)) {
t.Errorf("DumpTo() = %v; want %v", n, len(want))
}
}
10 changes: 10 additions & 0 deletions jwriter/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ func (w *Writer) BuildBytes(reuse ...[]byte) ([]byte, error) {
return w.Buffer.BuildBytes(reuse...), nil
}

// ReadCloser returns an io.ReadCloser that can be used to read the data.
// ReadCloser also resets the buffer.
func (w *Writer) ReadCloser() (io.ReadCloser, error) {
if w.Error != nil {
return nil, w.Error
}

return w.Buffer.ReadCloser(), nil
}

// RawByte appends raw binary data to the buffer.
func (w *Writer) RawByte(c byte) {
w.Buffer.AppendByte(c)
Expand Down

0 comments on commit 7a67b2a

Please sign in to comment.