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

Sync feature/stream-mode branch with v2.7.0 #640

Open
wants to merge 320 commits into
base: feature/stream-mode
Choose a base branch
from

Conversation

fxamacker
Copy link
Owner

Closes #638

This PR merges v2.7.0 into feature/stream-mode which was based on v2.4.0.

Merged changes include:

  • Two Encoder fields are removed to be consistent with v2.7.0: e *encoderBuffer and stream bool
  • New StreamEncoder field buf *bytes.Buffer (removed from Encoder) is added to store encoded data before flushing
  • New StreamEncoder.Encode() is added to simplify Encoder.Encode(), so Encoder.Encode() doesn't need to handle stream mode (consistent with v2.7.0).

For info about other changes from v2.4.0 to v2.7.0, see fxamacker/cbor/releases.

Conflict Resolution

git log -1 -p -w --remerge-diff 62b894b173ee5531f6b7e3ee5ba0e7f8c639f521

commit 62b894b173ee5531f6b7e3ee5ba0e7f8c639f521
Merge: c0c9f77 02b69db
Author: Faye Amacker <33205765+fxamacker@users.noreply.github.com>
Date:   Wed Mar 19 10:17:47 2025 -0500

    Merge tag 'v2.7.0' into fxamacker/update-stream-mode-with-master

diff --git a/decode.go b/decode.go
remerge CONFLICT (content): Merge conflict in decode.go
index 75ecbc8..3a35b14 100644
--- a/decode.go
+++ b/decode.go
@@ -776,12 +776,8 @@ type DecOptions struct {
 	TimeTag DecTagMode
 
 	// MaxNestedLevels specifies the max nested levels allowed for any combination of CBOR array, maps, and tags.
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-	// Default is 32 levels and it can be set to [4, 32767].
-=======
 	// Default is 32 levels and it can be set to [4, 65535]. Note that higher maximum levels of nesting can
 	// require larger amounts of stack to deserialize. Don't increase this higher than you require.
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 	MaxNestedLevels int
 
 	// MaxArrayElements specifies the max number of elements for CBOR arrays.
@@ -968,19 +964,11 @@ const (
 
 	defaultMaxMapPairs = 131072
 	minMaxMapPairs     = 16
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-	maxMaxMapPairs     = maxInt
-
-	defaultMaxNestedLevels = 32
-	minMaxNestedLevels     = 4
-	maxMaxNestedLevels     = 32767
-=======
 	maxMaxMapPairs     = 2147483647
 
 	defaultMaxNestedLevels = 32
 	minMaxNestedLevels     = 4
 	maxMaxNestedLevels     = 65535
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 )
 
 var defaultSimpleValues = func() *SimpleValueRegistry {
@@ -1012,17 +1000,9 @@ func (opts DecOptions) decMode() (*decMode, error) { //nolint:gocritic // ignore
 	if !opts.IntDec.valid() {
 		return nil, errors.New("cbor: invalid IntDec " + strconv.Itoa(int(opts.IntDec)))
 	}
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-	if opts.MaxNestedLevels == 0 {
-		opts.MaxNestedLevels = defaultMaxNestedLevels
-	} else if opts.MaxNestedLevels < minMaxNestedLevels || opts.MaxNestedLevels > maxMaxNestedLevels {
-		return nil, errors.New("cbor: invalid MaxNestedLevels " + strconv.Itoa(opts.MaxNestedLevels) +
-			" (range is [" + strconv.Itoa(minMaxNestedLevels) + ", " + strconv.Itoa(maxMaxNestedLevels) + "])")
-=======
 
 	if !opts.MapKeyByteString.valid() {
 		return nil, errors.New("cbor: invalid MapKeyByteString " + strconv.Itoa(int(opts.MapKeyByteString)))
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 	}
 
 	if opts.MaxNestedLevels == 0 {
@@ -1190,15 +1170,12 @@ type DecMode interface {
 	// NewDecoder returns a new decoder that reads from r using dm DecMode.
 	NewDecoder(r io.Reader) *Decoder
 
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
 	// NewStreamDecoder returns a new StreamDecoder that reads from r using dm DecMode.
 	NewStreamDecoder(r io.Reader) *StreamDecoder
 
 	// NewByteStreamDecoder returns a new StreamDecoder that reads from data using dm DecMode.
 	NewByteStreamDecoder(data []byte) *StreamDecoder
 
-=======
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 	// DecOptions returns user specified options used to create this DecMode.
 	DecOptions() DecOptions
 }
diff --git a/decode_test.go b/decode_test.go
remerge CONFLICT (content): Merge conflict in decode_test.go
index 01da754..54da813 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -2987,18 +2987,15 @@ var invalidCBORUnmarshalTests = []struct {
 	{"Major type 0 with additional information 31", hexDecode("1f"), "cbor: invalid additional information 31 for type positive integer", true},
 	{"Major type 1 with additional information 31", hexDecode("3f"), "cbor: invalid additional information 31 for type negative integer", true},
 	{"Major type 6 with additional information 31", hexDecode("df"), "cbor: invalid additional information 31 for type tag", true},
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
 	// more
 	{"End of input in a head", hexDecode("59"), "unexpected EOF", false},
 	{"End of input in a head", hexDecode("5b"), "unexpected EOF", false},
 	{"End of input in a head", hexDecode("d8"), "unexpected EOF", false},
 	{"End of input in a head", hexDecode("d9"), "unexpected EOF", false},
-=======
 	// Extraneous data
 	{"two ints", hexDecode("0001"), "cbor: 1 bytes of extraneous data starting at index 1", false},
 	{"two arrays", hexDecode("830102038104"), "cbor: 2 bytes of extraneous data starting at index 4", false},
 	{"int and partial array", hexDecode("00830102"), "cbor: 3 bytes of extraneous data starting at index 1", false},
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 }
 
 func TestInvalidCBORUnmarshal(t *testing.T) {
@@ -3449,12 +3446,8 @@ func TestStructFieldNil(t *testing.T) {
 func TestLengthOverflowsInt(t *testing.T) {
 	// Data is generating by go-fuzz.
 	// string/slice/map length in uint64 cast to int causes integer overflow.
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-	cborData := [][]byte{
-		hexDecode("9bcf30303030303030cfd697829782"),
-=======
 	data := [][]byte{
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
+		hexDecode("9bcf30303030303030cfd697829782"),
 		hexDecode("bbcf30303030303030cfd697829782"),
 		hexDecode("5bcf30303030303030cfd697829782"),
 	}
@@ -5062,21 +5055,12 @@ func TestDecModeInvalidMaxNestedLevel(t *testing.T) {
 		{
 			name:         "< min allowed nested levels",
 			opts:         DecOptions{MaxNestedLevels: 1},
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-			wantErrorMsg: "cbor: invalid MaxNestedLevels 1 (range is [4, 32767])",
-		},
-		{
-			name:         "> max allowed nested levels",
-			opts:         DecOptions{MaxNestedLevels: 32768},
-			wantErrorMsg: "cbor: invalid MaxNestedLevels 32768 (range is [4, 32767])",
-=======
 			wantErrorMsg: "cbor: invalid MaxNestedLevels 1 (range is [4, 65535])",
 		},
 		{
 			name:         "MaxNestedLevels > 65535",
 			opts:         DecOptions{MaxNestedLevels: 65536},
 			wantErrorMsg: "cbor: invalid MaxNestedLevels 65536 (range is [4, 65535])",
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 		},
 	}
 	for _, tc := range testCases {
@@ -5112,7 +5096,7 @@ func TestDecModeInvalidMaxMapPairs(t *testing.T) {
 		{
 			name:         "< min allowed max map pairs",
 			opts:         DecOptions{MaxMapPairs: 1},
-			wantErrorMsg: "cbor: invalid MaxMapPairs 1 (range is [16, 9223372036854775807])",
+			wantErrorMsg: "cbor: invalid MaxMapPairs 1 (range is [16, 2147483647])",
 		},
 	}
 	if bits.UintSize == 32 {
diff --git a/encode.go b/encode.go
remerge CONFLICT (content): Merge conflict in encode.go
index a4cdfca..165f978 100644
--- a/encode.go
+++ b/encode.go
@@ -956,31 +956,19 @@ func (em *encMode) NewEncoder(w io.Writer) *Encoder {
 	return &Encoder{w: w, em: em}
 }
 
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
 // NewStreamEncoder returns a new stream encoder that writes sequentially to w using em EncMode.
 func (em *encMode) NewStreamEncoder(w io.Writer) *StreamEncoder {
 	return &StreamEncoder{
-		Encoder: &Encoder{w: w, em: em, e: getEncoderBuffer(), stream: true},
+		Encoder: em.NewEncoder(w),
+		buf:     getEncodeBuffer(),
 	}
 }
 
-type encoderBuffer struct {
-	bytes.Buffer
-	scratch [16]byte
-}
-
-// encoderBufferPool caches unused encoderBuffer objects for later reuse.
-var encoderBufferPool = sync.Pool{
-	New: func() interface{} {
-		e := new(encoderBuffer)
-		e.Grow(64) // TODO: make this configurable
-=======
 // encodeBufferPool caches unused bytes.Buffer objects for later reuse.
 var encodeBufferPool = sync.Pool{
 	New: func() interface{} {
 		e := new(bytes.Buffer)
-		e.Grow(32) // TODO: make this configurable
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
+		e.Grow(64) // TODO: make this configurable
 		return e
 	},
 }
@@ -1754,12 +1742,6 @@ func encodeHead(e *bytes.Buffer, t byte, n uint64) int {
 	}
 
 	if n <= math.MaxUint8 {
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-		e.scratch[0] = t | 24
-		e.scratch[1] = byte(n)
-		e.Write(e.scratch[:2])
-		return
-=======
 		const headSize = 2
 		scratch := [headSize]byte{
 			t | byte(additionalInformationWith1ByteArgument),
@@ -1767,36 +1749,18 @@ func encodeHead(e *bytes.Buffer, t byte, n uint64) int {
 		}
 		e.Write(scratch[:])
 		return headSize
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 	}
 
 	if n <= math.MaxUint16 {
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-		e.scratch[0] = t | 25
-		binary.BigEndian.PutUint16(e.scratch[1:], uint16(n))
-		e.Write(e.scratch[:3])
-		return
-=======
 		const headSize = 3
 		var scratch [headSize]byte
 		scratch[0] = t | byte(additionalInformationWith2ByteArgument)
 		binary.BigEndian.PutUint16(scratch[1:], uint16(n))
 		e.Write(scratch[:])
 		return headSize
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 	}
 
 	if n <= math.MaxUint32 {
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-		e.scratch[0] = t | 26
-		binary.BigEndian.PutUint32(e.scratch[1:], uint32(n))
-		e.Write(e.scratch[:5])
-		return
-	}
-	e.scratch[0] = t | 27
-	binary.BigEndian.PutUint64(e.scratch[1:], n)
-	e.Write(e.scratch[:9])
-=======
 		const headSize = 5
 		var scratch [headSize]byte
 		scratch[0] = t | byte(additionalInformationWith4ByteArgument)
@@ -1811,7 +1775,6 @@ func encodeHead(e *bytes.Buffer, t byte, n uint64) int {
 	binary.BigEndian.PutUint64(scratch[1:], n)
 	e.Write(scratch[:])
 	return headSize
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 }
 
 var (
diff --git a/stream.go b/stream.go
remerge CONFLICT (content): Merge conflict in stream.go
index 5f97900..693b7d0 100644
--- a/stream.go
+++ b/stream.go
@@ -168,7 +168,6 @@ type Encoder struct {
 	w          io.Writer
 	em         *encMode
 	indefTypes []cborType
-	stream     bool
 }
 
 // NewEncoder returns a new encoder that writes to w using the default encoding options.
@@ -176,31 +175,40 @@ func NewEncoder(w io.Writer) *Encoder {
 	return defaultEncMode.NewEncoder(w)
 }
 
-// Encode writes the CBOR encoding of v.
-func (enc *Encoder) Encode(v interface{}) error {
-	if len(enc.indefTypes) > 0 && v != nil {
+func (enc *Encoder) checkIndefiniteLengthDataItemTypeIfNeeded(v interface{}) error {
+	if len(enc.indefTypes) == 0 || v == nil {
+		return nil
+	}
+
 	indefType := enc.indefTypes[len(enc.indefTypes)-1]
-		if indefType == cborTypeTextString {
+	return checkIndefiniteLengthDataItemType(indefType, v)
+}
+
+func checkIndefiniteLengthDataItemType(indefType cborType, v interface{}) error {
+	switch indefType {
+	case cborTypeTextString:
 		k := reflect.TypeOf(v).Kind()
 		if k != reflect.String {
 			return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length text string")
 		}
-		} else if indefType == cborTypeByteString {
+
+	case cborTypeByteString:
 		t := reflect.TypeOf(v)
 		k := t.Kind()
 		if (k != reflect.Array && k != reflect.Slice) || t.Elem().Kind() != reflect.Uint8 {
 			return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length byte string")
 		}
 	}
+
+	return nil
 }
 
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-	err := encode(enc.e, enc.em, reflect.ValueOf(v))
-	if err == nil && !enc.stream {
-		_, err = enc.e.WriteTo(enc.w)
-		enc.e.Reset()
+// Encode writes the CBOR encoding of v.
+func (enc *Encoder) Encode(v interface{}) error {
+	if err := enc.checkIndefiniteLengthDataItemTypeIfNeeded(v); err != nil {
+		return err
 	}
-=======
+
 	buf := getEncodeBuffer()
 
 	err := encode(buf, enc.em, reflect.ValueOf(v))
@@ -209,7 +217,6 @@ func (enc *Encoder) Encode(v interface{}) error {
 	}
 
 	putEncodeBuffer(buf)
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 	return err
 }
 
diff --git a/stream_decode.go b/stream_decode.go
index 107f3a7..2129003 100644
--- a/stream_decode.go
+++ b/stream_decode.go
@@ -600,7 +600,7 @@ func (sd *StreamDecoder) _readAndValidateNext() (int, error) {
 		sd.dec.d.reset(sd.dec.buf[sd.dec.off:])
 
 		start := sd.dec.d.off
-		err := sd.dec.d.valid()
+		err := sd.dec.d.wellformed(true, false)
 		end := sd.dec.d.off
 
 		// Restore decoder offset after validation
diff --git a/stream_encode.go b/stream_encode.go
index c15a0df..18e8c87 100644
--- a/stream_encode.go
+++ b/stream_encode.go
@@ -4,9 +4,11 @@
 package cbor
 
 import (
+	"bytes"
 	"errors"
 	"io"
 	"math/big"
+	"reflect"
 )
 
 // ErrStreamClosed is the error indicating operations on a closed stream.
@@ -22,19 +24,13 @@ var ErrStreamClosed = errors.New("cbor: operation on closed stream")
 // complete and well-formed.
 type StreamEncoder struct {
 	*Encoder
+	buf    *bytes.Buffer
 	closed bool
 }
 
 // NewStreamEncoder returns a new StreamEncoder for sequential encoding.
 func NewStreamEncoder(w io.Writer) *StreamEncoder {
-	return &StreamEncoder{
-		Encoder: &Encoder{
-			w:      w,
-			em:     defaultEncMode,
-			e:      getEncoderBuffer(),
-			stream: true,
-		},
-	}
+	return defaultEncMode.NewStreamEncoder(w)
 }
 
 // Close closes StreamEncoder and subsequence operations (except for Close)
@@ -43,7 +39,7 @@ func (se *StreamEncoder) Close() {
 	if se.closed {
 		return
 	}
-	putEncoderBuffer(se.Encoder.e)
+	putEncodeBuffer(se.buf)
 	se.Encoder = nil
 	se.closed = true
 }
@@ -53,16 +49,25 @@ func (se *StreamEncoder) Flush() error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	_, err := se.Encoder.e.WriteTo(se.Encoder.w)
+	_, err := se.buf.WriteTo(se.Encoder.w)
+	return err
+}
+
+// Encode writes the CBOR encoding of v.
+func (se *StreamEncoder) Encode(v interface{}) error {
+	if err := se.checkIndefiniteLengthDataItemTypeIfNeeded(v); err != nil {
 		return err
 	}
 
+	return encode(se.buf, se.em, reflect.ValueOf(v))
+}
+
 // EncodeMapHead encodes CBOR map head of specified size.
 func (se *StreamEncoder) EncodeMapHead(size uint64) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.Encoder.e, byte(cborTypeMap), size)
+	encodeHead(se.buf, byte(cborTypeMap), size)
 	return nil
 }
 
@@ -71,7 +76,7 @@ func (se *StreamEncoder) EncodeArrayHead(size uint64) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.Encoder.e, byte(cborTypeArray), size)
+	encodeHead(se.buf, byte(cborTypeArray), size)
 	return nil
 }
 
@@ -80,7 +85,7 @@ func (se *StreamEncoder) EncodeTagHead(num uint64) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.Encoder.e, byte(cborTypeTag), num)
+	encodeHead(se.buf, byte(cborTypeTag), num)
 	return nil
 }
 
@@ -93,7 +98,7 @@ func (se *StreamEncoder) EncodeRawBytes(b []byte) error {
 	if len(b) == 0 {
 		return nil
 	}
-	se.e.Write(b)
+	se.buf.Write(b)
 	return nil
 }
 
@@ -102,7 +107,7 @@ func (se *StreamEncoder) EncodeNil() error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	se.e.Write(cborNil)
+	se.buf.Write(cborNil)
 	return nil
 }
 
@@ -115,7 +120,7 @@ func (se *StreamEncoder) EncodeBool(b bool) error {
 	if !b {
 		bytes = cborFalse
 	}
-	se.e.Write(bytes)
+	se.buf.Write(bytes)
 	return nil
 }
 
@@ -124,7 +129,7 @@ func (se *StreamEncoder) EncodeUint(i uint) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.e, byte(cborTypePositiveInt), uint64(i))
+	encodeHead(se.buf, byte(cborTypePositiveInt), uint64(i))
 	return nil
 }
 
@@ -133,7 +138,7 @@ func (se *StreamEncoder) EncodeUint8(i uint8) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.e, byte(cborTypePositiveInt), uint64(i))
+	encodeHead(se.buf, byte(cborTypePositiveInt), uint64(i))
 	return nil
 }
 
@@ -142,7 +147,7 @@ func (se *StreamEncoder) EncodeUint16(i uint16) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.e, byte(cborTypePositiveInt), uint64(i))
+	encodeHead(se.buf, byte(cborTypePositiveInt), uint64(i))
 	return nil
 }
 
@@ -151,7 +156,7 @@ func (se *StreamEncoder) EncodeUint32(i uint32) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.e, byte(cborTypePositiveInt), uint64(i))
+	encodeHead(se.buf, byte(cborTypePositiveInt), uint64(i))
 	return nil
 }
 
@@ -160,7 +165,7 @@ func (se *StreamEncoder) EncodeUint64(i uint64) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.e, byte(cborTypePositiveInt), i)
+	encodeHead(se.buf, byte(cborTypePositiveInt), i)
 	return nil
 }
 
@@ -194,7 +199,7 @@ func (se *StreamEncoder) EncodeInt64(i int64) error {
 		t = cborTypeNegativeInt
 		i = i*(-1) - 1
 	}
-	encodeHead(se.e, byte(t), uint64(i))
+	encodeHead(se.buf, byte(t), uint64(i))
 	return nil
 }
 
@@ -204,12 +209,12 @@ func (se *StreamEncoder) EncodeBytes(b []byte) error {
 		return ErrStreamClosed
 	}
 	if b == nil {
-		se.e.Write(cborNil)
+		se.buf.Write(cborNil)
 		return nil
 	}
 
-	encodeHead(se.e, byte(cborTypeByteString), uint64(len(b)))
-	se.e.Write(b)
+	encodeHead(se.buf, byte(cborTypeByteString), uint64(len(b)))
+	se.buf.Write(b)
 	return nil
 }
 
@@ -218,8 +223,8 @@ func (se *StreamEncoder) EncodeString(s string) error {
 	if se.closed {
 		return ErrStreamClosed
 	}
-	encodeHead(se.e, byte(cborTypeTextString), uint64(len(s)))
-	se.e.WriteString(s)
+	encodeHead(se.buf, byte(cborTypeTextString), uint64(len(s)))
+	se.buf.WriteString(s)
 	return nil
 }
 
@@ -232,7 +237,7 @@ func (se *StreamEncoder) EncodeBigInt(v *big.Int) error {
 	}
 	if se.em.bigIntConvert == BigIntConvertShortest {
 		if v.IsUint64() {
-			encodeHead(se.e, byte(cborTypePositiveInt), v.Uint64())
+			encodeHead(se.buf, byte(cborTypePositiveInt), v.Uint64())
 			return nil
 		}
 		if v.IsInt64() {
@@ -253,9 +258,9 @@ func (se *StreamEncoder) EncodeBigInt(v *big.Int) error {
 	b := v.Bytes()
 
 	// Write tag number
-	encodeHead(se.e, byte(cborTypeTag), uint64(tagNum))
+	encodeHead(se.buf, byte(cborTypeTag), uint64(tagNum))
 	// Write bignum byte string
-	encodeHead(se.e, byte(cborTypeByteString), uint64(len(b)))
-	se.e.Write(b)
+	encodeHead(se.buf, byte(cborTypeByteString), uint64(len(b)))
+	se.buf.Write(b)
 	return nil
 }
diff --git a/valid_test.go b/valid_test.go
remerge CONFLICT (content): Merge conflict in valid_test.go
index 5221a8a..f4637b8 100644
--- a/valid_test.go
+++ b/valid_test.go
@@ -155,11 +155,7 @@ func TestDepthError(t *testing.T) {
 		},
 		{
 			name:         "33-level map",
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-			cborData:     hexDecode("a101a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a101"),
-=======
 			data:         hexDecode("a101818181818181818181818181818181818181818181818181818181818181818101"),
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 			opts:         DecOptions{},
 			wantErrorMsg: "cbor: exceeded max nested level 32",
 		},
@@ -179,15 +175,9 @@ func TestDepthError(t *testing.T) {
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			dm, _ := tc.opts.decMode()
-<<<<<<< c0c9f77 (Merge pull request #392 from fxamacker/fxamacker/add-streamencoder-close)
-			d := decoder{data: tc.cborData, dm: dm}
-			if err := d.valid(); err == nil {
-				t.Errorf("valid(0x%x) didn't return an error", tc.cborData)
-=======
 			d := decoder{data: tc.data, dm: dm}
 			if _, err := d.wellformedInternal(0, false); err == nil {
 				t.Errorf("wellformed(0x%x) didn't return an error", tc.data)
->>>>>>> 02b69db (Merge pull request #560 from fxamacker/fxamacker/update-readme-for-v2.7.0)
 			} else if _, ok := err.(*MaxNestedLevelError); !ok {
 				t.Errorf("wellformed(0x%x) returned wrong error type %T, want (*MaxNestedLevelError)", tc.data, err)
 			} else if err.Error() != tc.wantErrorMsg {

fxamacker and others added 30 commits May 6, 2023 17:09
UnmarshalFirst parses the first CBOR data item using the decoding mode.
Any remaining bytes are returned in rest.
…o-DecMode-interface

Add UnmarshalFirst to DecMode interface
…ons/setup-go-4

Bump actions/setup-go from 3 to 4
Co-authored-by: Faye Amacker <33205765+fxamacker@users.noreply.github.com>
Signed-off-by: Yan Qing <txr1883@gmail.com>
Signed-off-by: Yan Qing <txr1883@gmail.com>
Reduced min coverage to 96% (was 98%) since the Diagnose()
and DiagnoseFirst() functions reduced code coverage because
of error path .

These two functions return diagnostic notation for debugging,
so CBOR encoding/decoding funcs are unaffected (still >= 98% coverage).

Added triggers:
- pull_request
- workflow_dispatch

Co-authored-by: Faye Amacker <33205765+fxamacker@users.noreply.github.com>
Add more tests for Diagnose and DiagnoseFirst
Update README to separately mention support for:
- CBOR (IETF RFC 8949, STD 94)
- CBOR Sequences (IETF RFC 8742)
…c8742

Update README for CBOR Sequences RFC 8742
Document new CBOR codec functions:
- UnmarshalFirst()
- Diagnose()
- DiagnoseFirst()

UnmarshalFirst() makes it easier to use CBOR Sequences (RFC 8742).

Diagnose() and DiagnoseFirst() produces human-readable Extended Diagnostic Notation (RFC 8610 Appendix G).
….5.0-beta3

Update README.md for v2.5.0-beta3
Bump golangci-lint to 1.52.2.
Bump Go to 1.20.
Remove deprecated linters.

Temporarily disable revive to reduce noise in
golangci-lint 1.52.2.
Specify DDR4 in benchmark system because faster RAM
(DDR5 or overclocked DDR4) makes a difference in this
specific comparison.
Bump safer-golangci-lint to 1.52.2
Update README to mention DDR4 in benchmark comparison.
…ata-error

Fix Diagnose to return io.EOF error on empty data.

This was detected while updating CBOR fuzz tests for v2.5.0-beta3.
Add Whats New section to mention:
- Features already present in v2.4 are release quality.
- Newly added functions require more fuzzing & docs.
….5.0-beta4

Update README.md for cbor v2.5.0-beta4
Temp CI change to regenerate code coverage badge for old releases that passed with 98% coverage.

Master branch passes with 96% coverage because adding Diagnose() functions dropped coverage a bit.  Name of badge URL includes coverage percent, so this doesn't affect master.
Revert temp changes that were used for regenerating coverage badge (>98%) for older releases.

Master branch and newer releases use >96% coverage badge due to Diagnose() functions reducing coverage a bit.
Buffered returns an io.Reader for data remaining in Decoder's buffer.
The returned reader is valid until the next call to Decode or Skip.

This basically matches the Decoder.Buffered() in Go's encoding/json.
fxamacker and others added 25 commits June 6, 2024 21:04
Disable conflicting encode options when marshaling cbor.Tag.
…ub/codeql-action-3.25.7

Bump github/codeql-action from 3.25.6 to 3.25.7
Add go1.21 to ci.yml.  It was omitted because local tests use it and test matrix on GitHub is too large.

Very old versions like go1.17 can be removed from ci.yml after fxamacker/cbor v1.27.0 is released.
While at it, also improve docs.
Currently *errors.errorString is returned when unmarshalling
built-in tags (tag 0-3 and 21-23) with inadmissible content type.

This commit adds InadmissibleTagContentTypeError and returns this
error with the same error message as before when unmarshalling
build-in tags with inadmissible content type.
…rmat-dec-mode

Improve byte string format decoding options
…ontentTypeError

Replace `*errors.errorString` with `InadmissibleTagContentTypeError`
This commit adds features related to allowing user to specify
a buffer rather than using built-in buffer pool:

- cbor.MarshalToBuffer() uses codec's default options to encode
  to user provided buffer instead of using built-in buffer pool.

- UserBufferEncMode interface extends EncMode interface with
  MarshalToBuffer() so user can provide buffer for encoding
  instead of using built-in buffer pool.

- EncOptions.UserBufferEncMode() returns UserBufferEncMode

- EncOptions.UserBufferEncModeWithTags() returns UserBufferEncMode

- EncOptions.UserBufferEncModeWithSharedTags() returns UserBufferEncMode
Also renamed related options to be consistent.
…e-interface

Allow user to specify buffer by adding `cbor.MarshalToBuffer()`, `UserBufferEncMode` interface, etc.
Rename ByteSliceMode to ByteSliceLaterFormatMode, etc
Signed-off-by: Ben Luddy <bluddy@redhat.com>
Fix panic using SortFastShuffle (unreleased new feaure) to encode a struct with no fields.
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@a5ac7e5...692973e)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.7 to 3.25.10.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@f079b84...23acc5c)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
…ub/codeql-action-3.25.10

Bump github/codeql-action from 3.25.7 to 3.25.10
…ons/checkout-4.1.7

Bump actions/checkout from 4.1.6 to 4.1.7
Add Kubernetes to list of users, update Quick Start, etc.
….7.0

Update README.md for v2.7.0 release
@fxamacker fxamacker added the enhancement New feature or request label Mar 19, 2025
@fxamacker fxamacker self-assigned this Mar 19, 2025
@fxamacker
Copy link
Owner Author

@turbolent PTAL (not urgent yet since we can continue testing atree using this before merge).

For context, a project using atree had external dependency using cbor v2.7.0 and ran into build error because atree uses this feature branch based on cbor v2.4.

Eventually, I intend to add streaming feature to main branch of cbor along with some improvements.

This is needed for backward compatibility with
a project that sets this limit to math.MaxInt64.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants