diff --git a/bson/bson_test.go b/bson/bson_test.go index cb926838f0..db51caface 100644 --- a/bson/bson_test.go +++ b/bson/bson_test.go @@ -30,28 +30,6 @@ func noerr(t *testing.T, err error) { } } -func TestCompareTimestamp(t *testing.T) { - testcases := []struct { - name string - tp Timestamp - tp2 Timestamp - expected int - }{ - {"equal", Timestamp{T: 12345, I: 67890}, Timestamp{T: 12345, I: 67890}, 0}, - {"T greater than", Timestamp{T: 12345, I: 67890}, Timestamp{T: 2345, I: 67890}, 1}, - {"I greater than", Timestamp{T: 12345, I: 67890}, Timestamp{T: 12345, I: 7890}, 1}, - {"T less than", Timestamp{T: 12345, I: 67890}, Timestamp{T: 112345, I: 67890}, -1}, - {"I less than", Timestamp{T: 12345, I: 67890}, Timestamp{T: 12345, I: 167890}, -1}, - } - - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - result := CompareTimestamp(tc.tp, tc.tp2) - require.Equal(t, tc.expected, result) - }) - } -} - func TestTimestamp(t *testing.T) { t.Parallel() diff --git a/bson/cond_addr_codec.go b/bson/cond_addr_codec.go index 012b2d825c..fed4d1f8df 100644 --- a/bson/cond_addr_codec.go +++ b/bson/cond_addr_codec.go @@ -32,7 +32,7 @@ func (cae *condAddrEncoder) EncodeValue(ec EncodeContext, vw ValueWriter, val re if cae.elseEnc != nil { return cae.elseEnc.EncodeValue(ec, vw, val) } - return ErrNoEncoder{Type: val.Type()} + return errNoEncoder{Type: val.Type()} } // condAddrDecoder is the decoder used when a pointer to the value has a decoder. @@ -57,5 +57,5 @@ func (cad *condAddrDecoder) DecodeValue(dc DecodeContext, vr ValueReader, val re if cad.elseDec != nil { return cad.elseDec.DecodeValue(dc, vr, val) } - return ErrNoDecoder{Type: val.Type()} + return errNoDecoder{Type: val.Type()} } diff --git a/bson/cond_addr_codec_test.go b/bson/cond_addr_codec_test.go index c22c29fe72..3125214f30 100644 --- a/bson/cond_addr_codec_test.go +++ b/bson/cond_addr_codec_test.go @@ -52,7 +52,7 @@ func TestCondAddrCodec(t *testing.T) { t.Run("error", func(t *testing.T) { errEncoder := newCondAddrEncoder(encode1, nil) err := errEncoder.EncodeValue(EncodeContext{}, rw, unaddressable) - want := ErrNoEncoder{Type: unaddressable.Type()} + want := errNoEncoder{Type: unaddressable.Type()} assert.Equal(t, err, want, "expected error %v, got %v", want, err) }) }) @@ -88,7 +88,7 @@ func TestCondAddrCodec(t *testing.T) { t.Run("error", func(t *testing.T) { errDecoder := newCondAddrDecoder(decode1, nil) err := errDecoder.DecodeValue(DecodeContext{}, rw, unaddressable) - want := ErrNoDecoder{Type: unaddressable.Type()} + want := errNoDecoder{Type: unaddressable.Type()} assert.Equal(t, err, want, "expected error %v, got %v", want, err) }) }) diff --git a/bson/copier.go b/bson/copier.go index 07ebc744b5..d4b3697407 100644 --- a/bson/copier.go +++ b/bson/copier.go @@ -15,9 +15,6 @@ import ( ) // copyDocument handles copying one document from the src to the dst. -// -// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be -// supported in Go Driver 2.0. func copyDocument(dst ValueWriter, src ValueReader) error { dr, err := src.ReadDocument() if err != nil { @@ -34,9 +31,6 @@ func copyDocument(dst ValueWriter, src ValueReader) error { // copyArrayFromBytes copies the values from a BSON array represented as a // []byte to a ValueWriter. -// -// Deprecated: Copying BSON arrays using the ValueWriter and ValueReader interfaces will not be -// supported in Go Driver 2.0. func copyArrayFromBytes(dst ValueWriter, src []byte) error { aw, err := dst.WriteArray() if err != nil { @@ -53,9 +47,6 @@ func copyArrayFromBytes(dst ValueWriter, src []byte) error { // copyDocumentFromBytes copies the values from a BSON document represented as a // []byte to a ValueWriter. -// -// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be -// supported in Go Driver 2.0. func copyDocumentFromBytes(dst ValueWriter, src []byte) error { dw, err := dst.WriteDocument() if err != nil { @@ -74,9 +65,6 @@ type writeElementFn func(key string) (ValueWriter, error) // copyBytesToArrayWriter copies the values from a BSON Array represented as a []byte to an // ArrayWriter. -// -// Deprecated: Copying BSON arrays using the ArrayWriter interface will not be supported in Go -// Driver 2.0. func copyBytesToArrayWriter(dst ArrayWriter, src []byte) error { wef := func(_ string) (ValueWriter, error) { return dst.WriteArrayElement() @@ -87,9 +75,6 @@ func copyBytesToArrayWriter(dst ArrayWriter, src []byte) error { // copyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a // DocumentWriter. -// -// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be -// supported in Go Driver 2.0. func copyBytesToDocumentWriter(dst DocumentWriter, src []byte) error { wef := func(key string) (ValueWriter, error) { return dst.WriteDocumentElement(key) @@ -149,18 +134,12 @@ func copyBytesToValueWriter(src []byte, wef writeElementFn) error { // copyDocumentToBytes copies an entire document from the ValueReader and // returns it as bytes. -// -// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be -// supported in Go Driver 2.0. func copyDocumentToBytes(src ValueReader) ([]byte, error) { return appendDocumentBytes(nil, src) } // appendDocumentBytes functions the same as CopyDocumentToBytes, but will // append the result to dst. -// -// Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be -// supported in Go Driver 2.0. func appendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) { if br, ok := src.(bytesReader); ok { _, dst, err := br.readValueBytes(dst) @@ -178,9 +157,6 @@ func appendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) { } // appendArrayBytes copies an array from the ValueReader to dst. -// -// Deprecated: Copying BSON arrays using the ValueWriter and ValueReader interfaces will not be -// supported in Go Driver 2.0. func appendArrayBytes(dst []byte, src ValueReader) ([]byte, error) { if br, ok := src.(bytesReader); ok { _, dst, err := br.readValueBytes(dst) @@ -198,8 +174,6 @@ func appendArrayBytes(dst []byte, src ValueReader) ([]byte, error) { } // copyValueFromBytes will write the value represtend by t and src to dst. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.UnmarshalValue] instead. func copyValueFromBytes(dst ValueWriter, t Type, src []byte) error { if wvb, ok := dst.(bytesWriter); ok { return wvb.writeValueBytes(t, src) @@ -214,44 +188,28 @@ func copyValueFromBytes(dst ValueWriter, t Type, src []byte) error { return copyValue(dst, vr) } -// CopyValueToBytes copies a value from src and returns it as a Type and a +// copyValueToBytes copies a value from src and returns it as a Type and a // []byte. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.MarshalValue] instead. -func CopyValueToBytes(src ValueReader) (Type, []byte, error) { - return appendValueBytes(nil, src) -} - -// appendValueBytes functions the same as CopyValueToBytes, but will append the -// result to dst. -// -// Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go -// Driver 2.0. -func appendValueBytes(dst []byte, src ValueReader) (Type, []byte, error) { +func copyValueToBytes(src ValueReader) (Type, []byte, error) { if br, ok := src.(bytesReader); ok { - return br.readValueBytes(dst) + return br.readValueBytes(nil) } vw := vwPool.Get().(*valueWriter) defer putValueWriter(vw) - start := len(dst) - - vw.reset(dst) + vw.reset(nil) vw.push(mElement) err := copyValue(vw, src) if err != nil { - return 0, dst, err + return 0, nil, err } - return Type(vw.buf[start]), vw.buf[start+2:], nil + return Type(vw.buf[0]), vw.buf[2:], nil } // copyValue will copy a single value from src to dst. -// -// Deprecated: Copying BSON values using the ValueWriter and ValueReader interfaces will not be -// supported in Go Driver 2.0. func copyValue(dst ValueWriter, src ValueReader) error { var err error switch src.Type() { @@ -461,3 +419,15 @@ func copyDocumentCore(dw DocumentWriter, dr DocumentReader) error { return dw.WriteDocumentEnd() } + +// bytesReader is the interface used to read BSON bytes from a valueReader. +// +// The bytes of the value will be appended to dst. +type bytesReader interface { + readValueBytes(dst []byte) (Type, []byte, error) +} + +// bytesWriter is the interface used to write BSON bytes to a valueWriter. +type bytesWriter interface { + writeValueBytes(t Type, b []byte) error +} diff --git a/bson/copier_test.go b/bson/copier_test.go index 23c13447a4..f0939aa20a 100644 --- a/bson/copier_test.go +++ b/bson/copier_test.go @@ -455,7 +455,7 @@ func TestCopier(t *testing.T) { noerr(t, err) _, _, err = vr.ReadElement() noerr(t, err) - btype, got, err := CopyValueToBytes(vr) + btype, got, err := copyValueToBytes(vr) noerr(t, err) want := bsoncore.AppendString(nil, "world") if btype != TypeString { @@ -467,7 +467,7 @@ func TestCopier(t *testing.T) { }) t.Run("Non BytesReader", func(t *testing.T) { llvrw := &TestValueReaderWriter{t: t, bsontype: TypeString, readval: "Hello, world!"} - btype, got, err := CopyValueToBytes(llvrw) + btype, got, err := copyValueToBytes(llvrw) noerr(t, err) want := bsoncore.AppendString(nil, "Hello, world!") if btype != TypeString { @@ -477,49 +477,10 @@ func TestCopier(t *testing.T) { t.Errorf("Bytes do not match. got %v; want %v", got, want) } }) - }) - t.Run("AppendValueBytes", func(t *testing.T) { - t.Run("BytesReader", func(t *testing.T) { - var idx int32 - b, err := bsoncore.AppendDocumentEnd( - bsoncore.AppendStringElement( - bsoncore.AppendDocumentStartInline(nil, &idx), - "hello", "world", - ), - idx, - ) - noerr(t, err) - vr := newValueReader(b) - _, err = vr.ReadDocument() - noerr(t, err) - _, _, err = vr.ReadElement() - noerr(t, err) - btype, got, err := appendValueBytes(nil, vr) - noerr(t, err) - want := bsoncore.AppendString(nil, "world") - if btype != TypeString { - t.Errorf("Incorrect type returned. got %v; want %v", btype, TypeString) - } - if !bytes.Equal(got, want) { - t.Errorf("Bytes do not match. got %v; want %v", got, want) - } - }) - t.Run("Non BytesReader", func(t *testing.T) { - llvrw := &TestValueReaderWriter{t: t, bsontype: TypeString, readval: "Hello, world!"} - btype, got, err := appendValueBytes(nil, llvrw) - noerr(t, err) - want := bsoncore.AppendString(nil, "Hello, world!") - if btype != TypeString { - t.Errorf("Incorrect type returned. got %v; want %v", btype, TypeString) - } - if !bytes.Equal(got, want) { - t.Errorf("Bytes do not match. got %v; want %v", got, want) - } - }) - t.Run("CopyValue error", func(t *testing.T) { + t.Run("Error", func(t *testing.T) { want := errors.New("CopyValue error") llvrw := &TestValueReaderWriter{t: t, bsontype: TypeString, err: want, errAfter: llvrwReadString} - _, _, got := appendValueBytes(make([]byte, 0), llvrw) + _, _, got := copyValueToBytes(llvrw) if !assert.CompareErrors(got, want) { t.Errorf("Errors do not match. got %v; want %v", got, want) } diff --git a/bson/decoder_test.go b/bson/decoder_test.go index cfb51d6433..58291908c6 100644 --- a/bson/decoder_test.go +++ b/bson/decoder_test.go @@ -224,7 +224,7 @@ func TestDecoderv2(t *testing.T) { cdeih := func(string, string) string { return "certainlydoesntexistelsewhereihope" } dec := NewDecoder(NewValueReader([]byte{})) - want := ErrNoDecoder{Type: reflect.TypeOf(cdeih)} + want := errNoDecoder{Type: reflect.TypeOf(cdeih)} got := dec.Decode(&cdeih) assert.Equal(t, want, got, "Received unexpected error.") }) diff --git a/bson/default_value_decoders.go b/bson/default_value_decoders.go index 8f95ea2485..83bd42fedb 100644 --- a/bson/default_value_decoders.go +++ b/bson/default_value_decoders.go @@ -1180,7 +1180,7 @@ func valueUnmarshalerDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Va val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. } - t, src, err := CopyValueToBytes(vr) + t, src, err := copyValueToBytes(vr) if err != nil { return err } @@ -1206,7 +1206,7 @@ func unmarshalerDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) val.Set(reflect.New(val.Type().Elem())) } - _, src, err := CopyValueToBytes(vr) + _, src, err := copyValueToBytes(vr) if err != nil { return err } diff --git a/bson/default_value_decoders_test.go b/bson/default_value_decoders_test.go index b7fd95ad28..e88e9b820a 100644 --- a/bson/default_value_decoders_test.go +++ b/bson/default_value_decoders_test.go @@ -818,7 +818,7 @@ func TestDefaultValueDecoders(t *testing.T) { &DecodeContext{Registry: newTestRegistry()}, &valueReaderWriter{}, readDocument, - ErrNoDecoder{Type: reflect.TypeOf("")}, + errNoDecoder{Type: reflect.TypeOf("")}, }, { "ReadElement Error", @@ -904,7 +904,7 @@ func TestDefaultValueDecoders(t *testing.T) { &DecodeContext{Registry: newTestRegistry()}, &valueReaderWriter{BSONType: TypeArray}, readArray, - ErrNoDecoder{Type: reflect.TypeOf("")}, + errNoDecoder{Type: reflect.TypeOf("")}, }, { "ReadValue Error", @@ -998,7 +998,7 @@ func TestDefaultValueDecoders(t *testing.T) { &DecodeContext{Registry: newTestRegistry()}, &valueReaderWriter{BSONType: TypeArray}, readArray, - ErrNoDecoder{Type: reflect.TypeOf("")}, + errNoDecoder{Type: reflect.TypeOf("")}, }, { "ReadValue Error", @@ -1558,7 +1558,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "No Decoder", &wrong, &DecodeContext{Registry: buildDefaultRegistry()}, nil, nothing, - ErrNoDecoder{Type: reflect.TypeOf(wrong)}, + errNoDecoder{Type: reflect.TypeOf(wrong)}, }, { "decode null", @@ -3307,7 +3307,7 @@ func TestDefaultValueDecoders(t *testing.T) { } val := reflect.New(tEmpty).Elem() dc := DecodeContext{Registry: newTestRegistry()} - want := ErrNoTypeMapEntry{Type: tc.bsontype} + want := errNoTypeMapEntry{Type: tc.bsontype} got := (&emptyInterfaceCodec{}).DecodeValue(dc, llvr, val) if !assert.CompareErrors(got, want) { t.Errorf("Errors are not equal. got %v; want %v", got, want) @@ -3324,7 +3324,7 @@ func TestDefaultValueDecoders(t *testing.T) { dc := DecodeContext{ Registry: reg, } - want := ErrNoDecoder{Type: reflect.TypeOf(tc.val)} + want := errNoDecoder{Type: reflect.TypeOf(tc.val)} got := (&emptyInterfaceCodec{}).DecodeValue(dc, llvr, val) if !assert.CompareErrors(got, want) { t.Errorf("Errors are not equal. got %v; want %v", got, want) @@ -3389,7 +3389,7 @@ func TestDefaultValueDecoders(t *testing.T) { t.Run("no type registered", func(t *testing.T) { llvr := &valueReaderWriter{BSONType: TypeDouble} - want := ErrNoTypeMapEntry{Type: TypeDouble} + want := errNoTypeMapEntry{Type: TypeDouble} val := reflect.New(tEmpty).Elem() got := (&emptyInterfaceCodec{}).DecodeValue(DecodeContext{Registry: newTestRegistry()}, llvr, val) if !assert.CompareErrors(got, want) { @@ -3538,7 +3538,7 @@ func TestDefaultValueDecoders(t *testing.T) { } stringStructErr := &DecodeError{ keys: []string{"foo"}, - wrapped: ErrNoDecoder{reflect.TypeOf("")}, + wrapped: errNoDecoder{reflect.TypeOf("")}, } // Test a deeply nested struct mixed with maps and slices. diff --git a/bson/default_value_encoders.go b/bson/default_value_encoders.go index c87855551f..0b8ec92769 100644 --- a/bson/default_value_encoders.go +++ b/bson/default_value_encoders.go @@ -17,13 +17,17 @@ import ( "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) -var bvwPool = NewValueWriterPool() +var bvwPool = sync.Pool{ + New: func() interface{} { + return new(valueWriter) + }, +} var errInvalidValue = errors.New("cannot encode invalid element") var sliceWriterPool = sync.Pool{ New: func() interface{} { - sw := make(SliceWriter, 0) + sw := make(sliceWriter, 0) return &sw }, } @@ -462,11 +466,13 @@ func codeWithScopeEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Valu return err } - sw := sliceWriterPool.Get().(*SliceWriter) + sw := sliceWriterPool.Get().(*sliceWriter) defer sliceWriterPool.Put(sw) *sw = (*sw)[:0] - scopeVW := bvwPool.Get(sw) + scopeVW := bvwPool.Get().(*valueWriter) + scopeVW.reset(scopeVW.buf[:0]) + scopeVW.w = sw defer bvwPool.Put(scopeVW) encoder, err := ec.LookupEncoder(reflect.TypeOf(cws.Scope)) diff --git a/bson/default_value_encoders_test.go b/bson/default_value_encoders_test.go index 3977d0b141..485d414e03 100644 --- a/bson/default_value_encoders_test.go +++ b/bson/default_value_encoders_test.go @@ -735,7 +735,7 @@ func TestDefaultValueEncoders(t *testing.T) { &EncodeContext{Registry: buildDefaultRegistry()}, nil, nothing, - ErrNoEncoder{Type: reflect.TypeOf(wrong)}, + errNoEncoder{Type: reflect.TypeOf(wrong)}, }, }, }, @@ -1653,7 +1653,7 @@ func TestDefaultValueEncoders(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - b := make(SliceWriter, 0, 512) + b := make(sliceWriter, 0, 512) vw := NewValueWriter(&b) reg := buildDefaultRegistry() enc, err := reg.LookupEncoder(reflect.TypeOf(tc.value)) @@ -1703,7 +1703,7 @@ func TestDefaultValueEncoders(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - b := make(SliceWriter, 0, 512) + b := make(sliceWriter, 0, 512) vw := NewValueWriter(&b) reg := buildDefaultRegistry() enc, err := reg.LookupEncoder(reflect.TypeOf(tc.value)) @@ -1731,7 +1731,7 @@ func TestDefaultValueEncoders(t *testing.T) { val.Set(reflect.ValueOf(int64(1234567890))) llvrw := new(valueReaderWriter) got := (&emptyInterfaceCodec{}).EncodeValue(EncodeContext{Registry: newTestRegistry()}, llvrw, val) - want := ErrNoEncoder{Type: tInt64} + want := errNoEncoder{Type: tInt64} if !assert.CompareErrors(got, want) { t.Errorf("Did not receive expected error. got %v; want %v", got, want) } diff --git a/bson/encoder_test.go b/bson/encoder_test.go index 999b9962ef..03958273bd 100644 --- a/bson/encoder_test.go +++ b/bson/encoder_test.go @@ -20,7 +20,7 @@ import ( func TestBasicEncode(t *testing.T) { for _, tc := range marshalingTestCases { t.Run(tc.name, func(t *testing.T) { - got := make(SliceWriter, 0, 1024) + got := make(sliceWriter, 0, 1024) vw := NewValueWriter(&got) reg := DefaultRegistry encoder, err := reg.LookupEncoder(reflect.TypeOf(tc.val)) @@ -39,7 +39,7 @@ func TestBasicEncode(t *testing.T) { func TestEncoderEncode(t *testing.T) { for _, tc := range marshalingTestCases { t.Run(tc.name, func(t *testing.T) { - got := make(SliceWriter, 0, 1024) + got := make(sliceWriter, 0, 1024) vw := NewValueWriter(&got) enc := NewEncoder(vw) err := enc.Encode(tc.val) @@ -88,7 +88,7 @@ func TestEncoderEncode(t *testing.T) { marshaler := testMarshaler{buf: tc.buf, err: tc.err} var vw ValueWriter - b := make(SliceWriter, 0, 100) + b := make(sliceWriter, 0, 100) compareVW := false if tc.vw != nil { vw = tc.vw diff --git a/bson/extjson_reader.go b/bson/extjson_reader.go index 7395cc5d0c..4ba28dd0a2 100644 --- a/bson/extjson_reader.go +++ b/bson/extjson_reader.go @@ -10,52 +10,8 @@ import ( "errors" "fmt" "io" - "sync" ) -// ExtJSONValueReaderPool is a pool for ValueReaders that read ExtJSON. -// -// Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0. -type ExtJSONValueReaderPool struct { - pool sync.Pool -} - -// NewExtJSONValueReaderPool instantiates a new ExtJSONValueReaderPool. -// -// Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0. -func NewExtJSONValueReaderPool() *ExtJSONValueReaderPool { - return &ExtJSONValueReaderPool{ - pool: sync.Pool{ - New: func() interface{} { - return new(extJSONValueReader) - }, - }, - } -} - -// Get retrieves a ValueReader from the pool and uses src as the underlying ExtJSON. -// -// Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0. -func (bvrp *ExtJSONValueReaderPool) Get(r io.Reader, canonical bool) (ValueReader, error) { - vr := bvrp.pool.Get().(*extJSONValueReader) - return vr.reset(r, canonical) -} - -// Put inserts a ValueReader into the pool. If the ValueReader is not a ExtJSON ValueReader nothing -// is inserted into the pool and ok will be false. -// -// Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0. -func (bvrp *ExtJSONValueReaderPool) Put(vr ValueReader) (ok bool) { - bvr, ok := vr.(*extJSONValueReader) - if !ok { - return false - } - - bvr, _ = bvr.reset(nil, false) - bvrp.pool.Put(bvr) - return true -} - type ejvrState struct { mode mode vType Type diff --git a/bson/extjson_writer.go b/bson/extjson_writer.go index a060aeed75..797e24883f 100644 --- a/bson/extjson_writer.go +++ b/bson/extjson_writer.go @@ -15,65 +15,10 @@ import ( "sort" "strconv" "strings" - "sync" "time" "unicode/utf8" ) -// ExtJSONValueWriterPool is a pool for ExtJSON ValueWriters. -// -// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. -type ExtJSONValueWriterPool struct { - pool sync.Pool -} - -// NewExtJSONValueWriterPool creates a new pool for ValueWriter instances that write to ExtJSON. -// -// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. -func NewExtJSONValueWriterPool() *ExtJSONValueWriterPool { - return &ExtJSONValueWriterPool{ - pool: sync.Pool{ - New: func() interface{} { - return new(extJSONValueWriter) - }, - }, - } -} - -// Get retrieves a ExtJSON ValueWriter from the pool and resets it to use w as the destination. -// -// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. -func (bvwp *ExtJSONValueWriterPool) Get(w io.Writer, canonical, escapeHTML bool) ValueWriter { - vw := bvwp.pool.Get().(*extJSONValueWriter) - if writer, ok := w.(*SliceWriter); ok { - vw.reset(*writer, canonical, escapeHTML) - vw.w = writer - return vw - } - vw.buf = vw.buf[:0] - vw.w = w - return vw -} - -// Put inserts a ValueWriter into the pool. If the ValueWriter is not a ExtJSON ValueWriter, nothing -// happens and ok will be false. -// -// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. -func (bvwp *ExtJSONValueWriterPool) Put(vw ValueWriter) (ok bool) { - bvw, ok := vw.(*extJSONValueWriter) - if !ok { - return false - } - - if _, ok := bvw.w.(*SliceWriter); ok { - bvw.buf = nil - } - bvw.w = nil - - bvwp.pool.Put(bvw) - return true -} - type ejvwState struct { mode mode } diff --git a/bson/marshal.go b/bson/marshal.go index d6e687ddae..f36f73942e 100644 --- a/bson/marshal.go +++ b/bson/marshal.go @@ -14,7 +14,11 @@ import ( const defaultDstCap = 256 -var extjPool = NewExtJSONValueWriterPool() +var extjPool = sync.Pool{ + New: func() interface{} { + return new(extJSONValueWriter) + }, +} // Marshaler is the interface implemented by types that can marshal themselves // into a valid BSON document. @@ -88,22 +92,36 @@ func Marshal(val interface{}) ([]byte, error) { // MarshalValue will use bson.DefaultRegistry to transform val into a BSON value. If val is a struct, this function will // inspect struct tags and alter the marshalling process accordingly. func MarshalValue(val interface{}) (Type, []byte, error) { - return MarshalValueWithRegistry(DefaultRegistry, val) -} - -// MarshalValueWithRegistry returns the BSON encoding of val using Registry r. -// -// Deprecated: Using a custom registry to marshal individual BSON values will not be supported in Go -// Driver 2.0. -func MarshalValueWithRegistry(r *Registry, val interface{}) (Type, []byte, error) { - sw := SliceWriter(make([]byte, 0)) - vwFlusher := bvwPool.GetAtModeElement(&sw) + sw := bufPool.Get().(*bytes.Buffer) + defer func() { + // Proper usage of a sync.Pool requires each entry to have approximately + // the same memory cost. To obtain this property when the stored type + // contains a variably-sized buffer, we add a hard limit on the maximum + // buffer to place back in the pool. We limit the size to 16MiB because + // that's the maximum wire message size supported by any current MongoDB + // server. + // + // Comment based on + // https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/fmt/print.go;l=147 + // + // Recycle byte slices that are smaller than 16MiB and at least half + // occupied. + if sw.Cap() < 16*1024*1024 && sw.Cap()/2 < sw.Len() { + bufPool.Put(sw) + } + }() + sw.Reset() + vwFlusher := NewValueWriter(sw).(*valueWriter) + vw, err := vwFlusher.WriteDocumentElement("") + if err != nil { + return 0, nil, err + } // get an Encoder and encode the value enc := encPool.Get().(*Encoder) defer encPool.Put(enc) - enc.Reset(vwFlusher) - enc.ec = EncodeContext{Registry: r} + enc.Reset(vw) + enc.SetRegistry(DefaultRegistry) if err := enc.Encode(val); err != nil { return 0, nil, err } @@ -114,14 +132,21 @@ func MarshalValueWithRegistry(r *Registry, val interface{}) (Type, []byte, error if err := vwFlusher.Flush(); err != nil { return 0, nil, err } - return Type(sw[0]), sw[2:], nil + typ := sw.Next(2) + return Type(typ[0]), sw.Bytes(), nil } // MarshalExtJSON returns the extended JSON encoding of val. func MarshalExtJSON(val interface{}, canonical, escapeHTML bool) ([]byte, error) { - sw := SliceWriter(make([]byte, 0, defaultDstCap)) - ejvw := extjPool.Get(&sw, canonical, escapeHTML) - defer extjPool.Put(ejvw) + sw := sliceWriter(make([]byte, 0, defaultDstCap)) + ejvw := extjPool.Get().(*extJSONValueWriter) + ejvw.reset(sw, canonical, escapeHTML) + ejvw.w = &sw + defer func() { + ejvw.buf = nil + ejvw.w = nil + extjPool.Put(ejvw) + }() enc := encPool.Get().(*Encoder) defer encPool.Put(enc) diff --git a/bson/mgocompat/bson_test.go b/bson/mgocompat/bson_test.go index abdf8d5cfc..e49bb99a8b 100644 --- a/bson/mgocompat/bson_test.go +++ b/bson/mgocompat/bson_test.go @@ -52,9 +52,17 @@ func makeZeroDoc(value interface{}) (zero interface{}) { return zero } +func unmarshalWithRegistry(t *testing.T, r *bson.Registry, data []byte, val interface{}) error { + t.Helper() + + dec := bson.NewDecoder(bson.NewValueReader(data)) + dec.SetRegistry(r) + return dec.Decode(val) +} + func testUnmarshal(t *testing.T, data string, obj interface{}) { zero := makeZeroDoc(obj) - err := bson.UnmarshalWithRegistry(Registry, []byte(data), zero) + err := unmarshalWithRegistry(t, Registry, []byte(data), zero) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(zero, obj), "expected: %v, got: %v", obj, zero) } @@ -100,7 +108,7 @@ func TestUnmarshalSampleItems(t *testing.T) { for i, item := range sampleItems { t.Run(strconv.Itoa(i), func(t *testing.T) { value := bson.M{} - err := bson.UnmarshalWithRegistry(Registry, []byte(item.data), &value) + err := unmarshalWithRegistry(t, Registry, []byte(item.data), &value) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(value, item.obj), "expected: %v, got: %v", item.obj, value) }) @@ -185,7 +193,7 @@ func TestUnmarshalAllItems(t *testing.T) { for i, item := range allItems { t.Run(strconv.Itoa(i), func(t *testing.T) { value := bson.M{} - err := bson.UnmarshalWithRegistry(Registry, []byte(wrapInDoc(item.data)), &value) + err := unmarshalWithRegistry(t, Registry, []byte(wrapInDoc(item.data)), &value) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(value, item.obj), "expected: %v, got: %v", item.obj, value) }) @@ -226,7 +234,7 @@ func TestUnmarshalZeroesStruct(t *testing.T) { assert.Nil(t, err, "expected nil error, got: %v", err) type T struct{ A, B int } v := T{A: 1} - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &v) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), &v) assert.Nil(t, err, "expected nil error, got: %v", err) assert.Equal(t, 0, v.A, "expected: 0, got: %v", v.A) assert.Equal(t, 2, v.B, "expected: 2, got: %v", v.B) @@ -240,7 +248,7 @@ func TestUnmarshalZeroesMap(t *testing.T) { err := enc.Encode(bson.M{"b": 2}) assert.Nil(t, err, "expected nil error, got: %v", err) m := bson.M{"a": 1} - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &m) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), &m) assert.Nil(t, err, "expected nil error, got: %v", err) want := bson.M{"b": 2} @@ -256,7 +264,7 @@ func TestUnmarshalNonNilInterface(t *testing.T) { assert.Nil(t, err, "expected nil error, got: %v", err) m := bson.M{"a": 1} var i interface{} = m - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &i) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), &i) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(bson.M{"b": 2}, i), "expected: %v, got: %v", bson.M{"b": 2}, i) assert.True(t, reflect.DeepEqual(bson.M{"a": 1}, m), "expected: %v, got: %v", bson.M{"a": 1}, m) @@ -298,7 +306,7 @@ func TestPtrInline(t *testing.T) { err := enc.Encode(cs.In) assert.Nil(t, err, "expected nil error, got: %v", err) var dataBSON bson.M - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &dataBSON) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), &dataBSON) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(cs.Out, dataBSON), "expected: %v, got: %v", cs.Out, dataBSON) @@ -449,7 +457,7 @@ func Test64bitInt(t *testing.T) { assert.Equal(t, want, buf.String(), "expected: %v, got: %v", want, buf.String()) var result struct{ I int } - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &result) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), &result) assert.Nil(t, err, "expected nil error, got: %v", err) assert.Equal(t, i, int64(result.I), "expected: %v, got: %v", i, int64(result.I)) } @@ -607,7 +615,7 @@ func TestUnmarshalRawStructItems(t *testing.T) { t.Run(strconv.Itoa(i), func(t *testing.T) { raw := bson.Raw(wrapInDoc(item.data)) zero := makeZeroDoc(item.obj) - err := bson.UnmarshalWithRegistry(Registry, raw, zero) + err := unmarshalWithRegistry(t, Registry, raw, zero) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(item.obj, zero), "expected: %v, got: %v", item.obj, zero) }) @@ -723,7 +731,7 @@ func TestUnmarshalNilInStruct(t *testing.T) { // Nil is the default value, so we need to ensure it's indeed being set. b := byte(1) v := &struct{ Ptr *byte }{&b} - err := bson.UnmarshalWithRegistry(Registry, []byte(wrapInDoc("\x0Aptr\x00")), v) + err := unmarshalWithRegistry(t, Registry, []byte(wrapInDoc("\x0Aptr\x00")), v) assert.Nil(t, err, "expected nil error, got: %v", err) want := &struct{ Ptr *byte }{nil} @@ -830,7 +838,7 @@ func TestUnmarshalErrorItems(t *testing.T) { default: value = item.obj } - err := bson.UnmarshalWithRegistry(Registry, data, value) + err := unmarshalWithRegistry(t, Registry, data, value) assert.NotNil(t, err, "expected error") }) } @@ -902,10 +910,10 @@ var corruptedData = []string{ func TestUnmarshalMapDocumentTooShort(t *testing.T) { for i, data := range corruptedData { t.Run(strconv.Itoa(i), func(t *testing.T) { - err := bson.UnmarshalWithRegistry(Registry, []byte(data), bson.M{}) + err := unmarshalWithRegistry(t, Registry, []byte(data), bson.M{}) assert.NotNil(t, err, "expected error, got nil") - err = bson.UnmarshalWithRegistry(Registry, []byte(data), &struct{}{}) + err = unmarshalWithRegistry(t, Registry, []byte(data), &struct{}{}) assert.NotNil(t, err, "expected error, got nil") }) } @@ -961,12 +969,12 @@ func TestUnmarshalAllItemsWithPtrSetter(t *testing.T) { var field *setterType if i == 0 { obj := &ptrSetterDoc{} - err := bson.UnmarshalWithRegistry(Registry, []byte(wrapInDoc(item.data)), obj) + err := unmarshalWithRegistry(t, Registry, []byte(wrapInDoc(item.data)), obj) assert.Nil(t, err, "expected nil error, got: %v", err) field = obj.Field } else { obj := &valSetterDoc{} - err := bson.UnmarshalWithRegistry(Registry, []byte(wrapInDoc(item.data)), obj) + err := unmarshalWithRegistry(t, Registry, []byte(wrapInDoc(item.data)), obj) assert.Nil(t, err, "expected nil error, got: %v", err) field = &obj.Field } @@ -990,7 +998,7 @@ func TestUnmarshalAllItemsWithPtrSetter(t *testing.T) { func TestUnmarshalWholeDocumentWithSetter(t *testing.T) { obj := &setterType{} - err := bson.UnmarshalWithRegistry(Registry, []byte(sampleItems[0].data), obj) + err := unmarshalWithRegistry(t, Registry, []byte(sampleItems[0].data), obj) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(bson.M{"hello": "world"}, obj.Received), "expected obj.received to be: %v, got: %v", bson.M{"hello": "world"}, obj.Received) } @@ -1004,13 +1012,13 @@ func TestUnmarshalSetterErrors(t *testing.T) { data := wrapInDoc("\x02abc\x00\x02\x00\x00\x001\x00" + "\x02def\x00\x02\x00\x00\x002\x00" + "\x02ghi\x00\x02\x00\x00\x003\x00") - err := bson.UnmarshalWithRegistry(Registry, []byte(data), m) - assert.NotNil(t, err, "expected UnmarshalWithRegistry error %v, got nil", boom) + err := unmarshalWithRegistry(t, Registry, []byte(data), m) + assert.NotNil(t, err, "expected unmarshal error %v, got nil", boom) // It's not possible to generate the actual expected error here because it's an *UnmarshalError, which is defined // in bsoncodec and only contains unexported fields. expectedErr := errors.New("error decoding key def: BOOM") - assert.Equal(t, expectedErr.Error(), err.Error(), "expected UnmarshalWithRegistry error %v, got %v", expectedErr, err) + assert.Equal(t, expectedErr.Error(), err.Error(), "expected unmarshal error %v, got %v", expectedErr, err) assert.NotNil(t, m["abc"], "expected value not to be nil") assert.Nil(t, m["def"], "expected value to be nil, got: %v", m["def"]) @@ -1031,7 +1039,7 @@ func TestUnmarshalSetterErrSetZero(t *testing.T) { assert.Nil(t, err, "expected nil error, got: %v", err) m := map[string]*setterType{} - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), m) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), m) assert.Nil(t, err, "expected nil error, got: %v", err) value, ok := m["field"] @@ -1134,7 +1142,7 @@ func TestMarshalShortWithGetter(t *testing.T) { err := enc.Encode(obj) assert.Nil(t, err, "expected nil error, got: %v", err) m := bson.M{} - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &m) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), &m) assert.Nil(t, err, "expected nil error, got: %v", err) assert.Equal(t, 42, m["v"], "expected m[\"v\"] to be: %v, got: %v", 42, m["v"]) } @@ -1148,7 +1156,7 @@ func TestMarshalWithGetterNil(t *testing.T) { err := enc.Encode(obj) assert.Nil(t, err, "expected nil error, got: %v", err) m := bson.M{} - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &m) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), &m) assert.Nil(t, err, "expected nil error, got: %v", err) want := bson.M{"_": ""} assert.Equal(t, want, m, "expected m[\"v\"] to be: %v, got: %v", want, m) @@ -1601,7 +1609,7 @@ func testCrossPair(t *testing.T, dump interface{}, load interface{}) { enc.SetRegistry(Registry) err := enc.Encode(dump) assert.Nil(t, err, "expected nil error, got: %v", err) - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), zero) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), zero) assert.Nil(t, err, "expected nil error, got: %v", err) assert.True(t, reflect.DeepEqual(load, zero), "expected: %v, got: %v", load, zero) @@ -1718,7 +1726,7 @@ func TestMarshalNotRespectNil(t *testing.T) { testStruct2 := T{} - _ = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &testStruct2) + _ = unmarshalWithRegistry(t, Registry, buf.Bytes(), &testStruct2) assert.NotNil(t, testStruct2.Slice, "expected non-nil slice") assert.NotNil(t, testStruct2.BSlice, "expected non-nil byte slice") @@ -1751,7 +1759,7 @@ func TestMarshalRespectNil(t *testing.T) { testStruct2 := T{} - _ = bson.UnmarshalWithRegistry(RespectNilValuesRegistry, buf.Bytes(), &testStruct2) + _ = unmarshalWithRegistry(t, RespectNilValuesRegistry, buf.Bytes(), &testStruct2) assert.Len(t, testStruct2.Slice, 0, "expected empty slice, got: %v", testStruct2.Slice) assert.Nil(t, testStruct2.SlicePtr, "expected nil slice ptr, got: %v", testStruct2.SlicePtr) @@ -1780,7 +1788,7 @@ func TestMarshalRespectNil(t *testing.T) { testStruct2 = T{} - _ = bson.UnmarshalWithRegistry(RespectNilValuesRegistry, buf.Bytes(), &testStruct2) + _ = unmarshalWithRegistry(t, RespectNilValuesRegistry, buf.Bytes(), &testStruct2) assert.NotNil(t, testStruct2.Slice, "expected non-nil slice") assert.NotNil(t, testStruct2.SlicePtr, "expected non-nil slice ptr") @@ -1815,7 +1823,7 @@ func TestInlineWithPointerToSelf(t *testing.T) { assert.Nil(t, err, "expected nil error, got: %v", err) var x2 InlineLoop - err = bson.UnmarshalWithRegistry(Registry, buf.Bytes(), &x2) + err = unmarshalWithRegistry(t, Registry, buf.Bytes(), &x2) assert.Nil(t, err, "expected nil error, got: %v", err) assert.Equal(t, x1, x2, "Expected %v, got %v", x1, x2) } diff --git a/bson/mgoregistry.go b/bson/mgoregistry.go index 15c67c43dc..2f208a8c63 100644 --- a/bson/mgoregistry.go +++ b/bson/mgoregistry.go @@ -129,7 +129,7 @@ func setterDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. } - t, src, err := CopyValueToBytes(vr) + t, src, err := copyValueToBytes(vr) if err != nil { return err } diff --git a/bson/objectid.go b/bson/objectid.go index ccb0b78338..024281eb7f 100644 --- a/bson/objectid.go +++ b/bson/objectid.go @@ -91,14 +91,6 @@ func ObjectIDFromHex(s string) (ObjectID, error) { return oid, nil } -// IsValidObjectID returns true if the provided hex string represents a valid ObjectID and false if not. -// -// Deprecated: Use ObjectIDFromHex and check the error instead. -func IsValidObjectID(s string) bool { - _, err := ObjectIDFromHex(s) - return err == nil -} - // MarshalText returns the ObjectID as UTF-8-encoded text. Implementing this allows us to use ObjectID // as a map key when marshalling JSON. See https://pkg.go.dev/encoding#TextMarshaler func (id ObjectID) MarshalText() ([]byte, error) { diff --git a/bson/objectid_test.go b/bson/objectid_test.go index 12d4214241..f7291c5a2c 100644 --- a/bson/objectid_test.go +++ b/bson/objectid_test.go @@ -108,27 +108,6 @@ func TestFromHex_WrongLength(t *testing.T) { require.Equal(t, ErrInvalidHex, err) } -func TestIsValidObjectID(t *testing.T) { - testCases := []struct { - givenID string - expected bool - }{ - { - givenID: "5ef7fdd91c19e3222b41b839", - expected: true, - }, - { - givenID: "5ef7fdd91c19e3222b41b83", - expected: false, - }, - } - - for _, testcase := range testCases { - got := IsValidObjectID(testcase.givenID) - assert.Equal(t, testcase.expected, got, "expected hex string to be valid ObjectID: %v, got %v", testcase.expected, got) - } -} - func TestTimeStamp(t *testing.T) { testCases := []struct { Hex string diff --git a/bson/pointer_codec.go b/bson/pointer_codec.go index 2839efed83..ff2e940ce7 100644 --- a/bson/pointer_codec.go +++ b/bson/pointer_codec.go @@ -38,7 +38,7 @@ func (pc *pointerCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflec typ := val.Type() if v, ok := pc.ecache.Load(typ); ok { if v == nil { - return ErrNoEncoder{Type: typ} + return errNoEncoder{Type: typ} } return v.EncodeValue(ec, vw, val.Elem()) } @@ -74,7 +74,7 @@ func (pc *pointerCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflec if v, ok := pc.dcache.Load(typ); ok { if v == nil { - return ErrNoDecoder{Type: typ} + return errNoDecoder{Type: typ} } return v.DecodeValue(dc, vr, val.Elem()) } diff --git a/bson/primitive.go b/bson/primitive.go index aac77fc3ab..80cf085b02 100644 --- a/bson/primitive.go +++ b/bson/primitive.go @@ -183,14 +183,6 @@ func (tp Timestamp) Compare(tp2 Timestamp) int { } } -// CompareTimestamp compares the time instant tp with tp2. If tp is before tp2, it returns -1; if tp is after -// tp2, it returns +1; if they're the same, it returns 0. -// -// Deprecated: Use Timestamp.Compare instead. -func CompareTimestamp(tp, tp2 Timestamp) int { - return tp.Compare(tp2) -} - // MinKey represents the BSON minkey value. type MinKey struct{} diff --git a/bson/primitive_codecs.go b/bson/primitive_codecs.go index 334549465e..5ac5f0009c 100644 --- a/bson/primitive_codecs.go +++ b/bson/primitive_codecs.go @@ -51,7 +51,7 @@ func rawValueDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) err return ValueDecoderError{Name: "RawValueDecodeValue", Types: []reflect.Type{tRawValue}, Received: val} } - t, value, err := CopyValueToBytes(vr) + t, value, err := copyValueToBytes(vr) if err != nil { return err } diff --git a/bson/primitive_codecs_test.go b/bson/primitive_codecs_test.go index e9a7403551..103a4774bf 100644 --- a/bson/primitive_codecs_test.go +++ b/bson/primitive_codecs_test.go @@ -458,7 +458,7 @@ func TestPrimitiveValueEncoders(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - b := make(SliceWriter, 0, 512) + b := make(sliceWriter, 0, 512) vw := NewValueWriter(&b) enc := NewEncoder(vw) err := enc.Encode(tc.value) diff --git a/bson/raw_value_test.go b/bson/raw_value_test.go index 67444faa61..e6b5c24b96 100644 --- a/bson/raw_value_test.go +++ b/bson/raw_value_test.go @@ -28,7 +28,7 @@ func TestRawValue(t *testing.T) { reg := newTestRegistry() val := RawValue{Type: TypeString, Value: bsoncore.AppendString(nil, "foobar"), r: reg} var s string - want := ErrNoDecoder{Type: reflect.TypeOf(s)} + want := errNoDecoder{Type: reflect.TypeOf(s)} got := val.Unmarshal(&s) if !assert.CompareErrors(got, want) { t.Errorf("Expected errors to match. got %v; want %v", got, want) @@ -66,7 +66,7 @@ func TestRawValue(t *testing.T) { reg := newTestRegistry() var val RawValue var s string - want := ErrNoDecoder{Type: reflect.TypeOf(s)} + want := errNoDecoder{Type: reflect.TypeOf(s)} got := val.UnmarshalWithRegistry(reg, &s) if !assert.CompareErrors(got, want) { t.Errorf("Expected errors to match. got %v; want %v", got, want) @@ -117,7 +117,7 @@ func TestRawValue(t *testing.T) { dc := DecodeContext{Registry: newTestRegistry()} var val RawValue var s string - want := ErrNoDecoder{Type: reflect.TypeOf(s)} + want := errNoDecoder{Type: reflect.TypeOf(s)} got := val.UnmarshalWithContext(&dc, &s) if !assert.CompareErrors(got, want) { t.Errorf("Expected errors to match. got %v; want %v", got, want) diff --git a/bson/reader.go b/bson/reader.go index 587982b338..955d2e9fdb 100644 --- a/bson/reader.go +++ b/bson/reader.go @@ -47,12 +47,3 @@ type ValueReader interface { ReadTimestamp() (t, i uint32, err error) ReadUndefined() error } - -// bytesReader is a generic interface used to read BSON bytes from a -// ValueReader. This interface is meant to be a superset of ValueReader, so that -// types that implement ValueReader may also implement this interface. -// -// The bytes of the value will be appended to dst. -type bytesReader interface { - readValueBytes(dst []byte) (Type, []byte, error) -} diff --git a/bson/registry.go b/bson/registry.go index bcd3133445..5102a40032 100644 --- a/bson/registry.go +++ b/bson/registry.go @@ -17,49 +17,33 @@ import ( // primitive codecs. var DefaultRegistry = NewRegistry() -// ErrNilType is returned when nil is passed to either LookupEncoder or LookupDecoder. -// -// Deprecated: ErrNilType will not be supported in Go Driver 2.0. -var ErrNilType = errors.New("cannot perform a decoder lookup on ") - -// ErrNotPointer is returned when a non-pointer type is provided to LookupDecoder. -// -// Deprecated: ErrNotPointer will not be supported in Go Driver 2.0. -var ErrNotPointer = errors.New("non-pointer provided to LookupDecoder") - -// ErrNoEncoder is returned when there wasn't an encoder available for a type. -// -// Deprecated: ErrNoEncoder will not be supported in Go Driver 2.0. -type ErrNoEncoder struct { +// errNoEncoder is returned when there wasn't an encoder available for a type. +type errNoEncoder struct { Type reflect.Type } -func (ene ErrNoEncoder) Error() string { +func (ene errNoEncoder) Error() string { if ene.Type == nil { return "no encoder found for " } return "no encoder found for " + ene.Type.String() } -// ErrNoDecoder is returned when there wasn't a decoder available for a type. -// -// Deprecated: ErrNoDecoder will not be supported in Go Driver 2.0. -type ErrNoDecoder struct { +// errNoDecoder is returned when there wasn't a decoder available for a type. +type errNoDecoder struct { Type reflect.Type } -func (end ErrNoDecoder) Error() string { +func (end errNoDecoder) Error() string { return "no decoder found for " + end.Type.String() } -// ErrNoTypeMapEntry is returned when there wasn't a type available for the provided BSON type. -// -// Deprecated: ErrNoTypeMapEntry will not be supported in Go Driver 2.0. -type ErrNoTypeMapEntry struct { +// errNoTypeMapEntry is returned when there wasn't a type available for the provided BSON type. +type errNoTypeMapEntry struct { Type Type } -func (entme ErrNoTypeMapEntry) Error() string { +func (entme errNoTypeMapEntry) Error() string { return "no type map entry found for " + entme.Type.String() } @@ -258,12 +242,12 @@ func (r *Registry) RegisterTypeMapEntry(bt Type, rt reflect.Type) { // concurrent use by multiple goroutines after all codecs and encoders are registered. func (r *Registry) LookupEncoder(valueType reflect.Type) (ValueEncoder, error) { if valueType == nil { - return nil, ErrNoEncoder{Type: valueType} + return nil, errNoEncoder{Type: valueType} } enc, found := r.lookupTypeEncoder(valueType) if found { if enc == nil { - return nil, ErrNoEncoder{Type: valueType} + return nil, errNoEncoder{Type: valueType} } return enc, nil } @@ -276,7 +260,7 @@ func (r *Registry) LookupEncoder(valueType reflect.Type) (ValueEncoder, error) { if v, ok := r.kindEncoders.Load(valueType.Kind()); ok { return r.storeTypeEncoder(valueType, v), nil } - return nil, ErrNoEncoder{Type: valueType} + return nil, errNoEncoder{Type: valueType} } func (r *Registry) storeTypeEncoder(rt reflect.Type, enc ValueEncoder) ValueEncoder { @@ -327,12 +311,12 @@ func (r *Registry) lookupInterfaceEncoder(valueType reflect.Type, allowAddr bool // concurrent use by multiple goroutines after all codecs and decoders are registered. func (r *Registry) LookupDecoder(valueType reflect.Type) (ValueDecoder, error) { if valueType == nil { - return nil, ErrNilType + return nil, errors.New("cannot perform a decoder lookup on ") } dec, found := r.lookupTypeDecoder(valueType) if found { if dec == nil { - return nil, ErrNoDecoder{Type: valueType} + return nil, errNoDecoder{Type: valueType} } return dec, nil } @@ -345,7 +329,7 @@ func (r *Registry) LookupDecoder(valueType reflect.Type) (ValueDecoder, error) { if v, ok := r.kindDecoders.Load(valueType.Kind()); ok { return r.storeTypeDecoder(valueType, v), nil } - return nil, ErrNoDecoder{Type: valueType} + return nil, errNoDecoder{Type: valueType} } func (r *Registry) lookupTypeDecoder(valueType reflect.Type) (ValueDecoder, bool) { @@ -381,7 +365,7 @@ func (r *Registry) lookupInterfaceDecoder(valueType reflect.Type, allowAddr bool func (r *Registry) LookupTypeMapEntry(bt Type) (reflect.Type, error) { v, ok := r.typeMap.Load(bt) if v == nil || !ok { - return nil, ErrNoTypeMapEntry{Type: bt} + return nil, errNoTypeMapEntry{Type: bt} } return v.(reflect.Type), nil } diff --git a/bson/registry_examples_test.go b/bson/registry_examples_test.go index 39214f1b65..a2c5bac2b0 100644 --- a/bson/registry_examples_test.go +++ b/bson/registry_examples_test.go @@ -148,7 +148,9 @@ func ExampleRegistry_customDecoder() { IsOK lenientBool `bson:"isOK"` } var doc MyDocument - err = bson.UnmarshalWithRegistry(reg, b, &doc) + dec := bson.NewDecoder(bson.NewValueReader(b)) + dec.SetRegistry(reg) + err = dec.Decode(&doc) if err != nil { panic(err) } @@ -290,7 +292,9 @@ func ExampleRegistry_RegisterKindDecoder() { Int64 int64 } var doc myDocument - err = bson.UnmarshalWithRegistry(reg, b, &doc) + dec := bson.NewDecoder(bson.NewValueReader(b)) + dec.SetRegistry(reg) + err = dec.Decode(&doc) if err != nil { panic(err) } diff --git a/bson/registry_test.go b/bson/registry_test.go index 184501933a..40d65c8741 100644 --- a/bson/registry_test.go +++ b/bson/registry_test.go @@ -328,7 +328,7 @@ func TestRegistryBuilder(t *testing.T) { "No Codec Registered", ft3, nil, - ErrNoEncoder{Type: ft3}, + errNoEncoder{Type: ft3}, false, }, } @@ -348,8 +348,8 @@ func TestRegistryBuilder(t *testing.T) { }) t.Run("Decoder", func(t *testing.T) { wanterr := tc.wanterr - if ene, ok := tc.wanterr.(ErrNoEncoder); ok { - wanterr = ErrNoDecoder(ene) + if ene, ok := tc.wanterr.(errNoEncoder); ok { + wanterr = errNoDecoder(ene) } gotcodec, goterr := reg.LookupDecoder(tc.t) @@ -416,7 +416,7 @@ func TestRegistryBuilder(t *testing.T) { } want = nil - wanterr := ErrNoTypeMapEntry{Type: TypeObjectID} + wanterr := errNoTypeMapEntry{Type: TypeObjectID} got, err = reg.LookupTypeMapEntry(TypeObjectID) if !errors.Is(err, wanterr) { t.Errorf("did not get expected error: got %#v, want %#v", err, wanterr) @@ -743,7 +743,7 @@ func TestRegistry(t *testing.T) { "No Codec Registered", ft3, nil, - ErrNoEncoder{Type: ft3}, + errNoEncoder{Type: ft3}, false, }, } @@ -771,8 +771,8 @@ func TestRegistry(t *testing.T) { t.Parallel() wanterr := tc.wanterr - if ene, ok := tc.wanterr.(ErrNoEncoder); ok { - wanterr = ErrNoDecoder(ene) + if ene, ok := tc.wanterr.(errNoEncoder); ok { + wanterr = errNoDecoder(ene) } gotcodec, goterr := reg.LookupDecoder(tc.t) @@ -791,7 +791,7 @@ func TestRegistry(t *testing.T) { t.Run("Encoder", func(t *testing.T) { t.Parallel() - wanterr := ErrNoEncoder{Type: reflect.TypeOf(nil)} + wanterr := errNoEncoder{Type: reflect.TypeOf(nil)} gotcodec, goterr := reg.LookupEncoder(nil) if !cmp.Equal(goterr, wanterr, cmp.Comparer(assert.CompareErrors)) { @@ -804,12 +804,10 @@ func TestRegistry(t *testing.T) { t.Run("Decoder", func(t *testing.T) { t.Parallel() - wanterr := ErrNilType + wanterr := "cannot perform a decoder lookup on " gotcodec, goterr := reg.LookupDecoder(nil) - if !cmp.Equal(goterr, wanterr, cmp.Comparer(assert.CompareErrors)) { - t.Errorf("errors did not match: got %#v, want %#v", goterr, wanterr) - } + assert.EqualError(t, goterr, wanterr, "errors did not match") if !cmp.Equal(gotcodec, nil, allowunexported, cmp.Comparer(comparepc)) { t.Errorf("codecs did not match: got %v: want nil", gotcodec) } @@ -875,7 +873,7 @@ func TestRegistry(t *testing.T) { } want = nil - wanterr := ErrNoTypeMapEntry{Type: TypeObjectID} + wanterr := errNoTypeMapEntry{Type: TypeObjectID} got, err = reg.LookupTypeMapEntry(TypeObjectID) if !errors.Is(err, wanterr) { t.Errorf("unexpected error: got %#v, want %#v", err, wanterr) diff --git a/bson/struct_codec.go b/bson/struct_codec.go index 18cd40140f..8ae1fb2939 100644 --- a/bson/struct_codec.go +++ b/bson/struct_codec.go @@ -57,23 +57,23 @@ type structCodec struct { cache sync.Map // map[reflect.Type]*structDescription inlineMapEncoder mapElementsEncoder - // DecodeZeroStruct causes DecodeValue to delete any existing values from Go structs in the + // decodeZeroStruct causes DecodeValue to delete any existing values from Go structs in the // destination value passed to Decode before unmarshaling BSON documents into them. decodeZeroStruct bool - // DecodeDeepZeroInline causes DecodeValue to delete any existing values from Go structs in the + // decodeDeepZeroInline causes DecodeValue to delete any existing values from Go structs in the // destination value passed to Decode before unmarshaling BSON documents into them. decodeDeepZeroInline bool - // EncodeOmitDefaultStruct causes the Encoder to consider the zero value for a struct (e.g. + // encodeOmitDefaultStruct causes the Encoder to consider the zero value for a struct (e.g. // MyStruct{}) as empty and omit it from the marshaled BSON when the "omitempty" struct tag // option is set. encodeOmitDefaultStruct bool - // AllowUnexportedFields allows encoding and decoding values from un-exported struct fields. + // allowUnexportedFields allows encoding and decoding values from un-exported struct fields. allowUnexportedFields bool - // OverwriteDuplicatedInlinedFields, if false, causes EncodeValue to return an error if there is + // overwriteDuplicatedInlinedFields, if false, causes EncodeValue to return an error if there is // a duplicate field in the marshaled BSON when the "inline" struct tag option is set. The // default value is true. overwriteDuplicatedInlinedFields bool @@ -140,7 +140,7 @@ func (sc *structCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect } if desc.encoder == nil { - return ErrNoEncoder{Type: rv.Type()} + return errNoEncoder{Type: rv.Type()} } encoder := desc.encoder @@ -348,7 +348,7 @@ func (sc *structCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect } if fd.decoder == nil { - return newDecodeError(fd.name, ErrNoDecoder{Type: field.Elem().Type()}) + return newDecodeError(fd.name, errNoDecoder{Type: field.Elem().Type()}) } err = fd.decoder.DecodeValue(dctx, vr, field.Elem()) diff --git a/bson/struct_tag_parser.go b/bson/struct_tag_parser.go index 26773a39e9..47955639b4 100644 --- a/bson/struct_tag_parser.go +++ b/bson/struct_tag_parser.go @@ -35,8 +35,6 @@ import ( // // Skip This struct field should be skipped. This is usually denoted by parsing a "-" // for the name. -// -// Deprecated: Defining custom BSON struct tag parsers will not be supported in Go Driver 2.0. type structTags struct { Name string OmitEmpty bool diff --git a/bson/truncation_test.go b/bson/truncation_test.go index 865917cfe4..958a9b1915 100644 --- a/bson/truncation_test.go +++ b/bson/truncation_test.go @@ -23,6 +23,13 @@ type outputArgs struct { Val *int64 } +func unmarshalWithContext(t *testing.T, dc DecodeContext, data []byte, val interface{}) error { + t.Helper() + + vr := NewValueReader(data) + return unmarshalFromReader(dc, vr, val) +} + func TestTruncation(t *testing.T) { t.Run("truncation", func(t *testing.T) { inputName := "truncation" @@ -44,7 +51,7 @@ func TestTruncation(t *testing.T) { Truncate: true, } - err = UnmarshalWithContext(dc, buf.Bytes(), &output) + err = unmarshalWithContext(t, dc, buf.Bytes(), &output) assert.Nil(t, err) assert.Equal(t, inputName, output.Name) @@ -71,7 +78,7 @@ func TestTruncation(t *testing.T) { } // case throws an error when truncation is disabled - err = UnmarshalWithContext(dc, buf.Bytes(), &output) + err = unmarshalWithContext(t, dc, buf.Bytes(), &output) assert.NotNil(t, err) }) } diff --git a/bson/unmarshal.go b/bson/unmarshal.go index 49ed348ea4..0e5ac573a3 100644 --- a/bson/unmarshal.go +++ b/bson/unmarshal.go @@ -38,122 +38,28 @@ type ValueUnmarshaler interface { // pointed to by val. If val is nil or not a pointer, Unmarshal returns // InvalidUnmarshalError. func Unmarshal(data []byte, val interface{}) error { - return UnmarshalWithRegistry(DefaultRegistry, data, val) -} - -// UnmarshalWithRegistry parses the BSON-encoded data using Registry r and -// stores the result in the value pointed to by val. If val is nil or not -// a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. -// -// Deprecated: Use [NewDecoder] and specify the Registry by calling [Decoder.SetRegistry] instead: -// -// dec, err := bson.NewDecoder(NewBSONDocumentReader(data)) -// if err != nil { -// panic(err) -// } -// dec.SetRegistry(reg) -// -// See [Decoder] for more examples. -func UnmarshalWithRegistry(r *Registry, data []byte, val interface{}) error { - vr := NewValueReader(data) - return unmarshalFromReader(DecodeContext{Registry: r}, vr, val) -} - -// UnmarshalWithContext parses the BSON-encoded data using DecodeContext dc and -// stores the result in the value pointed to by val. If val is nil or not -// a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. -// -// Deprecated: Use [NewDecoder] and use the Decoder configuration methods to set the desired unmarshal -// behavior instead: -// -// dec, err := bson.NewDecoder(NewBSONDocumentReader(data)) -// if err != nil { -// panic(err) -// } -// dec.DefaultDocumentM() -// -// See [Decoder] for more examples. -func UnmarshalWithContext(dc DecodeContext, data []byte, val interface{}) error { vr := NewValueReader(data) - return unmarshalFromReader(dc, vr, val) + return unmarshalFromReader(DecodeContext{Registry: DefaultRegistry}, vr, val) } // UnmarshalValue parses the BSON value of type t with bson.DefaultRegistry and // stores the result in the value pointed to by val. If val is nil or not a pointer, // UnmarshalValue returns an error. func UnmarshalValue(t Type, data []byte, val interface{}) error { - return UnmarshalValueWithRegistry(DefaultRegistry, t, data, val) -} - -// UnmarshalValueWithRegistry parses the BSON value of type t with registry r and -// stores the result in the value pointed to by val. If val is nil or not a pointer, -// UnmarshalValue returns an error. -// -// Deprecated: Using a custom registry to unmarshal individual BSON values will not be supported in -// Go Driver 2.0. -func UnmarshalValueWithRegistry(r *Registry, t Type, data []byte, val interface{}) error { vr := NewBSONValueReader(t, data) - return unmarshalFromReader(DecodeContext{Registry: r}, vr, val) + return unmarshalFromReader(DecodeContext{Registry: DefaultRegistry}, vr, val) } // UnmarshalExtJSON parses the extended JSON-encoded data and stores the result // in the value pointed to by val. If val is nil or not a pointer, Unmarshal // returns InvalidUnmarshalError. func UnmarshalExtJSON(data []byte, canonical bool, val interface{}) error { - return UnmarshalExtJSONWithRegistry(DefaultRegistry, data, canonical, val) -} - -// UnmarshalExtJSONWithRegistry parses the extended JSON-encoded data using -// Registry r and stores the result in the value pointed to by val. If val is -// nil or not a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. -// -// Deprecated: Use [NewDecoder] and specify the Registry by calling [Decoder.SetRegistry] instead: -// -// vr, err := NewExtJSONValueReader(bytes.NewReader(data), true) -// if err != nil { -// panic(err) -// } -// dec, err := bson.NewDecoder(vr) -// if err != nil { -// panic(err) -// } -// dec.SetRegistry(reg) -// -// See [Decoder] for more examples. -func UnmarshalExtJSONWithRegistry(r *Registry, data []byte, canonical bool, val interface{}) error { - ejvr, err := NewExtJSONValueReader(bytes.NewReader(data), canonical) - if err != nil { - return err - } - - return unmarshalFromReader(DecodeContext{Registry: r}, ejvr, val) -} - -// UnmarshalExtJSONWithContext parses the extended JSON-encoded data using -// DecodeContext dc and stores the result in the value pointed to by val. If val is -// nil or not a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. -// -// Deprecated: Use [NewDecoder] and use the Decoder configuration methods to set the desired unmarshal -// behavior instead: -// -// vr, err := NewExtJSONValueReader(bytes.NewReader(data), true) -// if err != nil { -// panic(err) -// } -// dec, err := bson.NewDecoder(vr) -// if err != nil { -// panic(err) -// } -// dec.DefaultDocumentM() -// -// See [Decoder] for more examples. -func UnmarshalExtJSONWithContext(dc DecodeContext, data []byte, canonical bool, val interface{}) error { ejvr, err := NewExtJSONValueReader(bytes.NewReader(data), canonical) if err != nil { return err } - return unmarshalFromReader(dc, ejvr, val) + return unmarshalFromReader(DecodeContext{Registry: DefaultRegistry}, ejvr, val) } func unmarshalFromReader(dc DecodeContext, vr ValueReader, val interface{}) error { diff --git a/bson/unmarshal_test.go b/bson/unmarshal_test.go index d83edd3940..ea1b04dd36 100644 --- a/bson/unmarshal_test.go +++ b/bson/unmarshal_test.go @@ -7,7 +7,6 @@ package bson import ( - "errors" "math/rand" "reflect" "sync" @@ -40,175 +39,48 @@ func TestUnmarshal(t *testing.T) { } func TestUnmarshalWithRegistry(t *testing.T) { - for _, tc := range unmarshalingTestCases() { - t.Run(tc.name, func(t *testing.T) { - // Make a copy of the test data so we can modify it later. - data := make([]byte, len(tc.data)) - copy(data, tc.data) - - // Assert that unmarshaling the input data results in the expected value. - got := reflect.New(tc.sType).Interface() - err := UnmarshalWithRegistry(DefaultRegistry, data, got) - noerr(t, err) - assert.Equal(t, tc.want, got, "Did not unmarshal as expected.") - - // Fill the input data slice with random bytes and then assert that the result still - // matches the expected value. - _, err = rand.Read(data) - noerr(t, err) - assert.Equal(t, tc.want, got, "unmarshaled value does not match expected after modifying the input bytes") - }) - } -} - -func TestUnmarshalWithContext(t *testing.T) { - for _, tc := range unmarshalingTestCases() { - t.Run(tc.name, func(t *testing.T) { - // Make a copy of the test data so we can modify it later. - data := make([]byte, len(tc.data)) - copy(data, tc.data) - - // Assert that unmarshaling the input data results in the expected value. - dc := DecodeContext{Registry: DefaultRegistry} - got := reflect.New(tc.sType).Interface() - err := UnmarshalWithContext(dc, data, got) - noerr(t, err) - assert.Equal(t, tc.want, got, "Did not unmarshal as expected.") - - // Fill the input data slice with random bytes and then assert that the result still - // matches the expected value. - _, err = rand.Read(data) - noerr(t, err) - assert.Equal(t, tc.want, got, "unmarshaled value does not match expected after modifying the input bytes") - }) - } -} - -func TestUnmarshalExtJSONWithRegistry(t *testing.T) { - t.Run("UnmarshalExtJSONWithContext", func(t *testing.T) { - type teststruct struct{ Foo int } - var got teststruct - data := []byte("{\"foo\":1}") - err := UnmarshalExtJSONWithRegistry(DefaultRegistry, data, true, &got) - noerr(t, err) - want := teststruct{1} - assert.Equal(t, want, got, "Did not unmarshal as expected.") - }) - - t.Run("UnmarshalExtJSONInvalidInput", func(t *testing.T) { - data := []byte("invalid") - err := UnmarshalExtJSONWithRegistry(DefaultRegistry, data, true, &M{}) - if !errors.Is(err, ErrInvalidJSON) { - t.Fatalf("wanted ErrInvalidJSON, got %v", err) - } - }) -} - -func TestUnmarshalExtJSONWithContext(t *testing.T) { - type fooInt struct { - Foo int - } - - type fooString struct { - Foo string - } - - type fooBytes struct { - Foo []byte - } + t.Parallel() - var cases = []struct { - name string - sType reflect.Type - want interface{} - data []byte + testCases := []struct { + name string + val interface{} + bsontype Type + bytes []byte }{ { - name: "Small struct", - sType: reflect.TypeOf(fooInt{}), - data: []byte(`{"foo":1}`), - want: &fooInt{Foo: 1}, - }, - { - name: "Valid surrogate pair", - sType: reflect.TypeOf(fooString{}), - data: []byte(`{"foo":"\uD834\uDd1e"}`), - want: &fooString{Foo: "𝄞"}, - }, - { - name: "Valid surrogate pair with other values", - sType: reflect.TypeOf(fooString{}), - data: []byte(`{"foo":"abc \uD834\uDd1e 123"}`), - want: &fooString{Foo: "abc 𝄞 123"}, - }, - { - name: "High surrogate value with no following low surrogate value", - sType: reflect.TypeOf(fooString{}), - data: []byte(`{"foo":"abc \uD834 123"}`), - want: &fooString{Foo: "abc � 123"}, - }, - { - name: "High surrogate value at end of string", - sType: reflect.TypeOf(fooString{}), - data: []byte(`{"foo":"\uD834"}`), - want: &fooString{Foo: "�"}, - }, - { - name: "Low surrogate value with no preceding high surrogate value", - sType: reflect.TypeOf(fooString{}), - data: []byte(`{"foo":"abc \uDd1e 123"}`), - want: &fooString{Foo: "abc � 123"}, + name: "SliceCodec binary", + val: []byte("hello world"), + bsontype: TypeBinary, + bytes: bsoncore.AppendBinary(nil, TypeBinaryGeneric, []byte("hello world")), }, { - name: "Low surrogate value at end of string", - sType: reflect.TypeOf(fooString{}), - data: []byte(`{"foo":"\uDd1e"}`), - want: &fooString{Foo: "�"}, - }, - { - name: "High surrogate value with non-surrogate unicode value", - sType: reflect.TypeOf(fooString{}), - data: []byte(`{"foo":"\uD834\u00BF"}`), - want: &fooString{Foo: "�¿"}, - }, - // GODRIVER-2311 - // Test that ExtJSON-encoded binary unmarshals correctly to a bson.D and that the - // unmarshaled value does not reference the same underlying byte array as the input. - { - name: "bson.D with binary", - sType: reflect.TypeOf(D{}), - data: []byte(`{"foo": {"$binary": {"subType": "0", "base64": "AAECAwQF"}}}`), - want: &D{{"foo", Binary{Subtype: 0, Data: []byte{0, 1, 2, 3, 4, 5}}}}, - }, - // GODRIVER-2311 - // Test that ExtJSON-encoded binary unmarshals correctly to a struct and that the - // unmarshaled value does not reference thesame underlying byte array as the input. - { - name: "struct with binary", - sType: reflect.TypeOf(fooBytes{}), - data: []byte(`{"foo": {"$binary": {"subType": "0", "base64": "AAECAwQF"}}}`), - want: &fooBytes{Foo: []byte{0, 1, 2, 3, 4, 5}}, + name: "SliceCodec string", + val: []byte("hello world"), + bsontype: TypeString, + bytes: bsoncore.AppendString(nil, "hello world"), }, } + reg := NewRegistry() + reg.RegisterTypeDecoder(reflect.TypeOf([]byte{}), &sliceCodec{}) + for _, tc := range testCases { + tc := tc - for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - // Make a copy of the test data so we can modify it later. - data := make([]byte, len(tc.data)) - copy(data, tc.data) + t.Parallel() // Assert that unmarshaling the input data results in the expected value. - got := reflect.New(tc.sType).Interface() - dc := DecodeContext{Registry: DefaultRegistry} - err := UnmarshalExtJSONWithContext(dc, data, true, got) + gotValue := reflect.New(reflect.TypeOf(tc.val)) + dec := NewDecoder(NewBSONValueReader(tc.bsontype, tc.bytes)) + dec.SetRegistry(reg) + err := dec.Decode(gotValue.Interface()) noerr(t, err) - assert.Equal(t, tc.want, got, "Did not unmarshal as expected.") + assert.Equal(t, tc.val, gotValue.Elem().Interface(), "value mismatch; expected %s, got %s", tc.val, gotValue.Elem()) // Fill the input data slice with random bytes and then assert that the result still // matches the expected value. - _, err = rand.Read(data) + _, err = rand.Read(tc.bytes) noerr(t, err) - assert.Equal(t, tc.want, got, "unmarshaled value does not match expected after modifying the input bytes") + assert.Equal(t, tc.val, gotValue.Elem().Interface(), "unmarshaled value does not match expected after modifying the input bytes") }) } } @@ -249,7 +121,9 @@ func TestCachingDecodersNotSharedAcrossRegistries(t *testing.T) { assert.Equal(t, int32(1), first.X, "expected X value to be 1, got %v", first.X) var second Struct - err = UnmarshalWithRegistry(customReg, docBytes, &second) + dec := NewDecoder(NewValueReader(docBytes)) + dec.SetRegistry(customReg) + err = dec.Decode(&second) assert.Nil(t, err, "Unmarshal error: %v", err) assert.Equal(t, int32(-1), second.X, "expected X value to be -1, got %v", second.X) }) @@ -264,7 +138,9 @@ func TestCachingDecodersNotSharedAcrossRegistries(t *testing.T) { assert.Equal(t, int32(1), *first.X, "expected X value to be 1, got %v", *first.X) var second Struct - err = UnmarshalWithRegistry(customReg, docBytes, &second) + dec := NewDecoder(NewValueReader(docBytes)) + dec.SetRegistry(customReg) + err = dec.Decode(&second) assert.Nil(t, err, "Unmarshal error: %v", err) assert.Equal(t, int32(-1), *second.X, "expected X value to be -1, got %v", *second.X) }) diff --git a/bson/unmarshal_value_test.go b/bson/unmarshal_value_test.go index fd379b5daa..716fc3aa6e 100644 --- a/bson/unmarshal_value_test.go +++ b/bson/unmarshal_value_test.go @@ -36,60 +36,6 @@ func TestUnmarshalValue(t *testing.T) { }) } }) - t.Run("UnmarshalValueWithRegistry with DefaultRegistry", func(t *testing.T) { - t.Parallel() - - for _, tc := range unmarshalValueTestCases { - tc := tc - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - gotValue := reflect.New(reflect.TypeOf(tc.val)) - err := UnmarshalValueWithRegistry(DefaultRegistry, tc.bsontype, tc.bytes, gotValue.Interface()) - assert.Nil(t, err, "UnmarshalValueWithRegistry error: %v", err) - assert.Equal(t, tc.val, gotValue.Elem().Interface(), "value mismatch; expected %s, got %s", tc.val, gotValue.Elem()) - }) - } - }) - // tests covering GODRIVER-2779 - t.Run("UnmarshalValueWithRegistry with custom registry", func(t *testing.T) { - t.Parallel() - - testCases := []struct { - name string - val interface{} - bsontype Type - bytes []byte - }{ - { - name: "SliceCodec binary", - val: []byte("hello world"), - bsontype: TypeBinary, - bytes: bsoncore.AppendBinary(nil, TypeBinaryGeneric, []byte("hello world")), - }, - { - name: "SliceCodec string", - val: []byte("hello world"), - bsontype: TypeString, - bytes: bsoncore.AppendString(nil, "hello world"), - }, - } - reg := NewRegistry() - reg.RegisterTypeDecoder(reflect.TypeOf([]byte{}), &sliceCodec{}) - for _, tc := range testCases { - tc := tc - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - gotValue := reflect.New(reflect.TypeOf(tc.val)) - err := UnmarshalValueWithRegistry(reg, tc.bsontype, tc.bytes, gotValue.Interface()) - assert.Nil(t, err, "UnmarshalValueWithRegistry error: %v", err) - assert.Equal(t, tc.val, gotValue.Elem().Interface(), "value mismatch; expected %s, got %s", tc.val, gotValue.Elem()) - }) - } - }) } // tests covering GODRIVER-2779 @@ -115,8 +61,11 @@ func BenchmarkSliceCodecUnmarshal(b *testing.B) { for _, bm := range benchmarks { b.Run(bm.name, func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { + dec := NewDecoder(nil) + dec.SetRegistry(reg) for pb.Next() { - err := UnmarshalValueWithRegistry(reg, bm.bsontype, bm.bytes, &[]byte{}) + dec.Reset(NewBSONValueReader(bm.bsontype, bm.bytes)) + err := dec.Decode(&[]byte{}) if err != nil { b.Fatal(err) } diff --git a/bson/value_reader.go b/bson/value_reader.go index 039cd1b2c7..2ce612a570 100644 --- a/bson/value_reader.go +++ b/bson/value_reader.go @@ -24,50 +24,6 @@ var vrPool = sync.Pool{ }, } -// ValueReaderPool is a pool for ValueReaders that read BSON. -// -// Deprecated: ValueReaderPool will not be supported in Go Driver 2.0. -type ValueReaderPool struct { - pool sync.Pool -} - -// NewValueReaderPool instantiates a new ValueReaderPool. -// -// Deprecated: ValueReaderPool will not be supported in Go Driver 2.0. -func NewValueReaderPool() *ValueReaderPool { - return &ValueReaderPool{ - pool: sync.Pool{ - New: func() interface{} { - return new(valueReader) - }, - }, - } -} - -// Get retrieves a ValueReader from the pool and uses src as the underlying BSON. -// -// Deprecated: ValueReaderPool will not be supported in Go Driver 2.0. -func (bvrp *ValueReaderPool) Get(src []byte) ValueReader { - vr := bvrp.pool.Get().(*valueReader) - vr.reset(src) - return vr -} - -// Put inserts a ValueReader into the pool. If the ValueReader is not a BSON ValueReader nothing -// is inserted into the pool and ok will be false. -// -// Deprecated: ValueReaderPool will not be supported in Go Driver 2.0. -func (bvrp *ValueReaderPool) Put(vr ValueReader) (ok bool) { - bvr, ok := vr.(*valueReader) - if !ok { - return false - } - - bvr.reset(nil) - bvrp.pool.Put(bvr) - return true -} - // ErrEOA is the error returned when the end of a BSON array has been reached. var ErrEOA = errors.New("end of array") diff --git a/bson/value_writer.go b/bson/value_writer.go index fa04f67af3..bbcdbc5764 100644 --- a/bson/value_writer.go +++ b/bson/value_writer.go @@ -33,62 +33,6 @@ func putValueWriter(vw *valueWriter) { } } -// ValueWriterPool is a pool for BSON ValueWriters. -// -// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0. -type ValueWriterPool struct { - pool sync.Pool -} - -// NewValueWriterPool creates a new pool for ValueWriter instances that write to BSON. -// -// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0. -func NewValueWriterPool() *ValueWriterPool { - return &ValueWriterPool{ - pool: sync.Pool{ - New: func() interface{} { - return new(valueWriter) - }, - }, - } -} - -// Get retrieves a BSON ValueWriter from the pool and resets it to use w as the destination. -// -// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0. -func (bvwp *ValueWriterPool) Get(w io.Writer) ValueWriter { - vw := bvwp.pool.Get().(*valueWriter) - - // TODO: Having to call reset here with the same buffer doesn't really make sense. - vw.reset(vw.buf) - vw.buf = vw.buf[:0] - vw.w = w - return vw -} - -// GetAtModeElement retrieves a ValueWriterFlusher from the pool and resets it to use w as the destination. -// -// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0. -func (bvwp *ValueWriterPool) GetAtModeElement(w io.Writer) ValueWriterFlusher { - vw := bvwp.Get(w).(*valueWriter) - vw.push(mElement) - return vw -} - -// Put inserts a ValueWriter into the pool. If the ValueWriter is not a BSON ValueWriter, nothing -// happens and ok will be false. -// -// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0. -func (bvwp *ValueWriterPool) Put(vw ValueWriter) (ok bool) { - bvw, ok := vw.(*valueWriter) - if !ok { - return false - } - - bvwp.pool.Put(bvw) - return true -} - // This is here so that during testing we can change it and not require // allocating a 4GB slice. var maxSize = math.MaxInt32 diff --git a/bson/writer.go b/bson/writer.go index 380a0c4cb3..84cad0dda4 100644 --- a/bson/writer.go +++ b/bson/writer.go @@ -50,30 +50,11 @@ type ValueWriter interface { WriteUndefined() error } -// ValueWriterFlusher is a superset of ValueWriter that exposes functionality to flush to the underlying buffer. -// -// Deprecated: ValueWriterFlusher will not be supported in Go Driver 2.0. -type ValueWriterFlusher interface { - ValueWriter - Flush() error -} - -// bytesWriter is the interface used to write BSON bytes to a ValueWriter. -// This interface is meant to be a superset of ValueWriter, so that types that -// implement ValueWriter may also implement this interface. -type bytesWriter interface { - writeValueBytes(t Type, b []byte) error -} - -// SliceWriter allows a pointer to a slice of bytes to be used as an io.Writer. -// -// Deprecated: SliceWriter will not be supported in Go Driver 2.0. -type SliceWriter []byte +// sliceWriter allows a pointer to a slice of bytes to be used as an io.Writer. +type sliceWriter []byte // Write writes the bytes to the underlying slice. -// -// Deprecated: SliceWriter will not be supported in Go Driver 2.0. -func (sw *SliceWriter) Write(p []byte) (int, error) { +func (sw *sliceWriter) Write(p []byte) (int, error) { written := len(p) *sw = append(*sw, p...) return written, nil diff --git a/internal/integration/crud_helpers_test.go b/internal/integration/crud_helpers_test.go index 108515b11b..523917a4b5 100644 --- a/internal/integration/crud_helpers_test.go +++ b/internal/integration/crud_helpers_test.go @@ -1041,7 +1041,9 @@ func executeWithTransaction(mt *mtest.T, sess *mongo.Session, args bson.Raw) err mt.Helper() var testArgs withTransactionArgs - err := bson.UnmarshalWithRegistry(specTestRegistry, args, &testArgs) + dec := bson.NewDecoder(bson.NewValueReader(args)) + dec.SetRegistry(specTestRegistry) + err := dec.Decode(&testArgs) assert.Nil(mt, err, "error creating withTransactionArgs: %v", err) opts := createTransactionOptions(mt, testArgs.Options) diff --git a/internal/integration/crud_spec_test.go b/internal/integration/crud_spec_test.go index e6583f8ade..a547904193 100644 --- a/internal/integration/crud_spec_test.go +++ b/internal/integration/crud_spec_test.go @@ -7,9 +7,9 @@ package integration import ( + "bytes" "context" "fmt" - "io/ioutil" "os" "path" "reflect" @@ -91,12 +91,16 @@ func verifyServerlessConstraint(mt *mtest.T, expected string) error { } func runCrudFile(t *testing.T, file string) { - content, err := ioutil.ReadFile(file) + content, err := os.ReadFile(file) assert.Nil(t, err, "ReadFile error for %v: %v", file, err) var testFile crudTestFile - err = bson.UnmarshalExtJSONWithRegistry(crudRegistry, content, false, &testFile) - assert.Nil(t, err, "UnmarshalExtJSONWithRegistry error: %v", err) + vr, err := bson.NewExtJSONValueReader(bytes.NewReader(content), false) + assert.Nil(t, err, "NewExtJSONValueReader error: %v", err) + dec := bson.NewDecoder(vr) + dec.SetRegistry(crudRegistry) + err = dec.Decode(&testFile) + assert.Nil(t, err, "decode error: %v", err) mt := mtest.New(t, mtest.NewOptions().MinServerVersion(testFile.MinServerVersion).MaxServerVersion(testFile.MaxServerVersion)) diff --git a/internal/integration/database_test.go b/internal/integration/database_test.go index 12c2e0cd53..56505a0525 100644 --- a/internal/integration/database_test.go +++ b/internal/integration/database_test.go @@ -599,7 +599,9 @@ func getCollectionOptions(mt *mtest.T, collectionName string) bson.M { assert.True(mt, cursor.Next(context.Background()), "expected Next to return true, got false") var actualOpts bson.M - err = bson.UnmarshalWithRegistry(interfaceAsMapRegistry, cursor.Current.Lookup("options").Document(), &actualOpts) + dec := bson.NewDecoder(bson.NewValueReader(cursor.Current.Lookup("options").Document())) + dec.SetRegistry(interfaceAsMapRegistry) + err = dec.Decode(&actualOpts) assert.Nil(mt, err, "UnmarshalWithRegistry error: %v", err) return actualOpts diff --git a/internal/integration/initial_dns_seedlist_discovery_test.go b/internal/integration/initial_dns_seedlist_discovery_test.go index d4d4e20799..4a0e8ba738 100644 --- a/internal/integration/initial_dns_seedlist_discovery_test.go +++ b/internal/integration/initial_dns_seedlist_discovery_test.go @@ -7,9 +7,9 @@ package integration import ( + "bytes" "context" "crypto/tls" - "io/ioutil" "os" "path" "runtime" @@ -92,12 +92,16 @@ func runSeedlistDiscoveryPingTest(mt *mtest.T, clientOpts *options.ClientOptions } func runSeedlistDiscoveryTest(mt *mtest.T, file string) { - content, err := ioutil.ReadFile(file) + content, err := os.ReadFile(file) assert.Nil(mt, err, "ReadFile error for %v: %v", file, err) var test seedlistTest - err = bson.UnmarshalExtJSONWithRegistry(specTestRegistry, content, false, &test) - assert.Nil(mt, err, "UnmarshalExtJSONWithRegistry error: %v", err) + vr, err := bson.NewExtJSONValueReader(bytes.NewReader(content), false) + assert.Nil(mt, err, "NewExtJSONValueReader error: %v", err) + dec := bson.NewDecoder(vr) + dec.SetRegistry(specTestRegistry) + err = dec.Decode(&test) + assert.Nil(mt, err, "decode error: %v", err) if runtime.GOOS == "windows" && strings.HasSuffix(file, "/two-txt-records.json") { mt.Skip("skipping to avoid windows multiple TXT record lookup bug") diff --git a/internal/integration/retryable_writes_spec_test.go b/internal/integration/retryable_writes_spec_test.go index 9f08b52d4c..66f968e33d 100644 --- a/internal/integration/retryable_writes_spec_test.go +++ b/internal/integration/retryable_writes_spec_test.go @@ -7,6 +7,7 @@ package integration import ( + "bytes" "io/ioutil" "path" "testing" @@ -46,8 +47,12 @@ func runRetryableWritesFile(t *testing.T, filePath string) { assert.Nil(t, err, "ReadFile error for %v: %v", filePath, err) var testFile retryableWritesTestFile - err = bson.UnmarshalExtJSONWithRegistry(specTestRegistry, content, false, &testFile) - assert.Nil(t, err, "UnmarshalExtJSONWithRegistry error: %v", err) + vr, err := bson.NewExtJSONValueReader(bytes.NewReader(content), false) + assert.Nil(t, err, "NewExtJSONValueReader error: %v", err) + dec := bson.NewDecoder(vr) + dec.SetRegistry(specTestRegistry) + err = dec.Decode(&testFile) + assert.Nil(t, err, "decode error: %v", err) mt := mtest.New(t, mtest.NewOptions().RunOn(testFile.RunOn...).CreateClient(false)) diff --git a/internal/integration/unified/client_entity.go b/internal/integration/unified/client_entity.go index 200b0130b4..228e12e57f 100644 --- a/internal/integration/unified/client_entity.go +++ b/internal/integration/unified/client_entity.go @@ -474,9 +474,9 @@ func (c *clientEntity) processPoolEvent(evt *event.PoolEvent) { // Update the connection counter. This happens even if we're not storing any events. switch evt.Type { case event.ConnectionCheckedOut: - c.numConnsCheckedOut++ + atomic.AddInt32(&c.numConnsCheckedOut, 1) case event.ConnectionCheckedIn: - c.numConnsCheckedOut-- + atomic.AddInt32(&c.numConnsCheckedOut, -1) } eventType := monitoringEventTypeFromPoolEvent(evt) diff --git a/internal/integration/unified_runner_thread_helpers_test.go b/internal/integration/unified_runner_thread_helpers_test.go index 061ffe5fcc..023a1b5b7b 100644 --- a/internal/integration/unified_runner_thread_helpers_test.go +++ b/internal/integration/unified_runner_thread_helpers_test.go @@ -87,7 +87,9 @@ func runOnThread(mt *mtest.T, testCase *testCase, op *operation) { var routineOperation operation operationDoc := op.Arguments.Lookup("operation") - err := bson.UnmarshalWithRegistry(specTestRegistry, operationDoc.Document(), &routineOperation) + dec := bson.NewDecoder(bson.NewValueReader(operationDoc.Document())) + dec.SetRegistry(specTestRegistry) + err := dec.Decode(&routineOperation) assert.Nil(mt, err, "error creating operation for runOnThread: %v", err) ok = routine.addOperation(&routineOperation) diff --git a/internal/integration/unified_spec_test.go b/internal/integration/unified_spec_test.go index bcfb5d72f8..46d0c077e0 100644 --- a/internal/integration/unified_spec_test.go +++ b/internal/integration/unified_spec_test.go @@ -7,6 +7,7 @@ package integration import ( + "bytes" "context" "errors" "fmt" @@ -208,7 +209,11 @@ func runSpecTestFile(t *testing.T, specDir, fileName string) { assert.Nil(t, err, "unable to read spec test file %v: %v", filePath, err) var testFile testFile - err = bson.UnmarshalExtJSONWithRegistry(specTestRegistry, content, false, &testFile) + vr, err := bson.NewExtJSONValueReader(bytes.NewReader(content), false) + assert.Nil(t, err, "NewExtJSONValueReader error: %v", err) + dec := bson.NewDecoder(vr) + dec.SetRegistry(specTestRegistry) + err = dec.Decode(&testFile) assert.Nil(t, err, "unable to unmarshal spec test file at %v: %v", filePath, err) // create mtest wrapper and skip if needed diff --git a/mongo/change_stream.go b/mongo/change_stream.go index f02010f53f..5b3a8ddf16 100644 --- a/mongo/change_stream.go +++ b/mongo/change_stream.go @@ -244,13 +244,12 @@ func newChangeStream(ctx context.Context, config changeStreamConfig, pipeline in // any errors from Marshaling. customOptions := make(map[string]bsoncore.Value) for optionName, optionValue := range cs.options.Custom { - bsonType, bsonData, err := bson.MarshalValueWithRegistry(cs.registry, optionValue) + optionValueBSON, err := marshalValue(optionValue, nil, cs.registry) if err != nil { cs.err = err closeImplicitSession(cs.sess) return nil, cs.Err() } - optionValueBSON := bsoncore.Value{Type: bsoncore.Type(bsonType), Data: bsonData} customOptions[optionName] = optionValueBSON } cs.aggregate.CustomOptions(customOptions) @@ -260,13 +259,12 @@ func newChangeStream(ctx context.Context, config changeStreamConfig, pipeline in // any errors from Marshaling. cs.pipelineOptions = make(map[string]bsoncore.Value) for optionName, optionValue := range cs.options.CustomPipeline { - bsonType, bsonData, err := bson.MarshalValueWithRegistry(cs.registry, optionValue) + optionValueBSON, err := marshalValue(optionValue, nil, cs.registry) if err != nil { cs.err = err closeImplicitSession(cs.sess) return nil, cs.Err() } - optionValueBSON := bsoncore.Value{Type: bsoncore.Type(bsonType), Data: bsonData} cs.pipelineOptions[optionName] = optionValueBSON } } diff --git a/mongo/collection.go b/mongo/collection.go index ea75a4a0cd..c285341521 100644 --- a/mongo/collection.go +++ b/mongo/collection.go @@ -1079,11 +1079,10 @@ func aggregate(a aggregateParams) (cur *Cursor, err error) { // any errors from Marshaling. customOptions := make(map[string]bsoncore.Value) for optionName, optionValue := range ao.Custom { - bsonType, bsonData, err := bson.MarshalValueWithRegistry(a.registry, optionValue) + optionValueBSON, err := marshalValue(optionValue, nil, a.registry) if err != nil { return nil, err } - optionValueBSON := bsoncore.Value{Type: bsoncore.Type(bsonType), Data: bsonData} customOptions[optionName] = optionValueBSON } op.CustomOptions(customOptions) diff --git a/mongo/gridfs_bucket.go b/mongo/gridfs_bucket.go index dd3661877b..cdfb848020 100644 --- a/mongo/gridfs_bucket.go +++ b/mongo/gridfs_bucket.go @@ -605,7 +605,9 @@ func (b *GridFSBucket) parseUploadOptions(opts ...*options.UploadOptions) (*uplo return nil, err } var doc bson.D - unMarErr := bson.UnmarshalWithRegistry(uo.Registry, buf.Bytes(), &doc) + dec := bson.NewDecoder(bson.NewValueReader(buf.Bytes())) + dec.SetRegistry(uo.Registry) + unMarErr := dec.Decode(&doc) if unMarErr != nil { return nil, unMarErr } diff --git a/mongo/mongo.go b/mongo/mongo.go index 7ba0dff24e..0da198c8de 100644 --- a/mongo/mongo.go +++ b/mongo/mongo.go @@ -52,9 +52,6 @@ func (me MarshalError) Error() string { // } type Pipeline []bson.D -// bvwPool is a pool of BSON value writers. BSON value writers -var bvwPool = bson.NewValueWriterPool() - // getEncoder takes a writer, BSON options, and a BSON registry and returns a properly configured // bson.Encoder that writes to the given writer. func getEncoder( @@ -62,7 +59,7 @@ func getEncoder( opts *options.BSONOptions, reg *bson.Registry, ) (*bson.Encoder, error) { - vw := bvwPool.Get(w) + vw := bson.NewValueWriter(w) enc := bson.NewEncoder(vw) if opts != nil { diff --git a/mongo/read_write_concern_spec_test.go b/mongo/read_write_concern_spec_test.go index ffa41039b1..0dbe04fbdc 100644 --- a/mongo/read_write_concern_spec_test.go +++ b/mongo/read_write_concern_spec_test.go @@ -87,8 +87,12 @@ func runConnectionStringTestFile(t *testing.T, filePath string) { assert.Nil(t, err, "ReadFile error for %v: %v", filePath, err) var testFile connectionStringTestFile - err = bson.UnmarshalExtJSONWithRegistry(specTestRegistry, content, false, &testFile) - assert.Nil(t, err, "UnmarshalExtJSONWithRegistry error: %v", err) + vr, err := bson.NewExtJSONValueReader(bytes.NewReader(content), false) + assert.Nil(t, err, "NewExtJSONValueReader error: %v", err) + dec := bson.NewDecoder(vr) + dec.SetRegistry(specTestRegistry) + err = dec.Decode(&testFile) + assert.Nil(t, err, "decode error: %v", err) for _, test := range testFile.Tests { t.Run(test.Description, func(t *testing.T) { @@ -138,8 +142,12 @@ func runDocumentTestFile(t *testing.T, filePath string) { assert.Nil(t, err, "ReadFile error: %v", err) var testFile documentTestFile - err = bson.UnmarshalExtJSONWithRegistry(specTestRegistry, content, false, &testFile) - assert.Nil(t, err, "UnmarshalExtJSONWithRegistry error: %v", err) + vr, err := bson.NewExtJSONValueReader(bytes.NewReader(content), false) + assert.Nil(t, err, "NewExtJSONValueReader error: %v", err) + dec := bson.NewDecoder(vr) + dec.SetRegistry(specTestRegistry) + err = dec.Decode(&testFile) + assert.Nil(t, err, "decode error: %v", err) for _, test := range testFile.Tests { t.Run(test.Description, func(t *testing.T) { diff --git a/mongo/util.go b/mongo/util.go deleted file mode 100644 index 270fa24a25..0000000000 --- a/mongo/util.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2017-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package mongo