Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Decoder.Buffered to return buffered data #412

Merged
merged 1 commit into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package cbor

import (
"bytes"
"errors"
"io"
"reflect"
Expand Down Expand Up @@ -65,6 +66,12 @@ func (dec *Decoder) NumBytesRead() int {
return dec.bytesRead
}

// Buffered returns a reader for data remaining in Decoder's buffer.
// Returned reader is valid until the next call to Decode or Skip.
func (dec *Decoder) Buffered() io.Reader {
return bytes.NewReader(dec.buf[dec.off:])
}
fxamacker marked this conversation as resolved.
Show resolved Hide resolved

// readNext() reads next CBOR data item from Reader to buffer.
// It returns the size of next CBOR data item.
// It also returns validation error or read error if any.
Expand Down
86 changes: 86 additions & 0 deletions stream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,92 @@ func TestDecoderStructTag(t *testing.T) {
}
}

func TestDecoderBuffered(t *testing.T) {
testCases := []struct {
name string
cborData []byte
buffered []byte
decodeErr error
}{
{
name: "empty",
cborData: []byte{},
buffered: []byte{},
decodeErr: io.EOF,
},
{
name: "malformed CBOR data item",
cborData: []byte{0xc0},
buffered: []byte{0xc0},
decodeErr: io.ErrUnexpectedEOF,
},
{
name: "1 CBOR data item",
cborData: []byte{0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
buffered: []byte{},
},
{
name: "2 CBOR data items",
cborData: []byte{
// First CBOR data item
0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Second CBOR data item
0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
buffered: []byte{
// Second CBOR data item
0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
{
name: "1 CBOR data item followed by non-CBOR data",
cborData: []byte{
// CBOR data item
0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Extraneous non-CBOR data ("abc")
0x61, 0x62, 0x63,
},
buffered: []byte{
// non-CBOR data ("abc")
0x61, 0x62, 0x63,
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
r := bytes.NewReader(tc.cborData)

decoder := NewDecoder(r)

// Decoder's buffer has no data yet.
br := decoder.Buffered()
buffered, err := io.ReadAll(br)
if err != nil {
t.Errorf("failed to read from reader returned by Buffered(): %v", err)
}
if len(buffered) > 0 {
t.Errorf("Buffered() = 0x%x (%d bytes), want 0 bytes", buffered, len(buffered))
}

var v interface{}
err = decoder.Decode(&v)
if err != tc.decodeErr {
t.Errorf("Decode() returned error %v, want %v", err, tc.decodeErr)
}

br = decoder.Buffered()
buffered, err = io.ReadAll(br)
if err != nil {
t.Errorf("failed to read from reader returned by Buffered(): %v", err)
}
if !bytes.Equal(tc.buffered, buffered) {
t.Errorf("Buffered() = 0x%x (%d bytes), want 0x%x (%d bytes)", buffered, len(buffered), tc.buffered, len(tc.buffered))
}
})
}
}

func TestEncoder(t *testing.T) {
var want bytes.Buffer
var w bytes.Buffer
Expand Down