diff --git a/bson/array_codec.go b/bson/array_codec.go index 5b07f4acd4..4a53d376bc 100644 --- a/bson/array_codec.go +++ b/bson/array_codec.go @@ -12,24 +12,11 @@ import ( "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) -// ArrayCodec is the Codec used for bsoncore.Array values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// ArrayCodec registered. -type ArrayCodec struct{} - -var defaultArrayCodec = NewArrayCodec() - -// NewArrayCodec returns an ArrayCodec. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// ArrayCodec registered. -func NewArrayCodec() *ArrayCodec { - return &ArrayCodec{} -} +// arrayCodec is the Codec used for bsoncore.Array values. +type arrayCodec struct{} // EncodeValue is the ValueEncoder for bsoncore.Array values. -func (ac *ArrayCodec) EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +func (ac *arrayCodec) EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tCoreArray { return ValueEncoderError{Name: "CoreArrayEncodeValue", Types: []reflect.Type{tCoreArray}, Received: val} } @@ -39,7 +26,7 @@ func (ac *ArrayCodec) EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.V } // DecodeValue is the ValueDecoder for bsoncore.Array values. -func (ac *ArrayCodec) DecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { +func (ac *arrayCodec) DecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tCoreArray { return ValueDecoderError{Name: "CoreArrayDecodeValue", Types: []reflect.Type{tCoreArray}, Received: val} } diff --git a/bson/bson_test.go b/bson/bson_test.go index dcfc1037d9..03188d21b8 100644 --- a/bson/bson_test.go +++ b/bson/bson_test.go @@ -17,7 +17,6 @@ import ( "time" "github.com/google/go-cmp/cmp" - "go.mongodb.org/mongo-driver/bson/bsonoptions" "go.mongodb.org/mongo-driver/internal/assert" "go.mongodb.org/mongo-driver/internal/require" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" @@ -349,19 +348,18 @@ func TestMapCodec(t *testing.T) { strstr := stringerString("foo") mapObj := map[stringerString]int{strstr: 1} testCases := []struct { - name string - opts *bsonoptions.MapCodecOptions - key string + name string + mapCodec *mapCodec + key string }{ - {"default", bsonoptions.MapCodec(), "foo"}, - {"true", bsonoptions.MapCodec().SetEncodeKeysWithStringer(true), "bar"}, - {"false", bsonoptions.MapCodec().SetEncodeKeysWithStringer(false), "foo"}, + {"default", &mapCodec{}, "foo"}, + {"true", &mapCodec{encodeKeysWithStringer: true}, "bar"}, + {"false", &mapCodec{encodeKeysWithStringer: false}, "foo"}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - mapCodec := NewMapCodec(tc.opts) mapRegistry := NewRegistry() - mapRegistry.RegisterKindEncoder(reflect.Map, mapCodec) + mapRegistry.RegisterKindEncoder(reflect.Map, tc.mapCodec) buf := new(bytes.Buffer) vw := NewValueWriter(buf) enc := NewEncoder(vw) diff --git a/bson/bsoncodec_test.go b/bson/bsoncodec_test.go index d1dc21a953..61c38933ee 100644 --- a/bson/bsoncodec_test.go +++ b/bson/bsoncodec_test.go @@ -13,7 +13,7 @@ import ( ) func ExampleValueEncoder() { - var _ ValueEncoderFunc = func(ec EncodeContext, vw ValueWriter, val reflect.Value) error { + var _ ValueEncoderFunc = func(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if val.Kind() != reflect.String { return ValueEncoderError{Name: "StringEncodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val} } diff --git a/bson/bsonoptions/byte_slice_codec_options.go b/bson/bsonoptions/byte_slice_codec_options.go deleted file mode 100644 index 996bd17127..0000000000 --- a/bson/bsonoptions/byte_slice_codec_options.go +++ /dev/null @@ -1,49 +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 bsonoptions - -// ByteSliceCodecOptions represents all possible options for byte slice encoding and decoding. -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -type ByteSliceCodecOptions struct { - EncodeNilAsEmpty *bool // Specifies if a nil byte slice should encode as an empty binary instead of null. Defaults to false. -} - -// ByteSliceCodec creates a new *ByteSliceCodecOptions -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -func ByteSliceCodec() *ByteSliceCodecOptions { - return &ByteSliceCodecOptions{} -} - -// SetEncodeNilAsEmpty specifies if a nil byte slice should encode as an empty binary instead of null. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilByteSliceAsEmpty] instead. -func (bs *ByteSliceCodecOptions) SetEncodeNilAsEmpty(b bool) *ByteSliceCodecOptions { - bs.EncodeNilAsEmpty = &b - return bs -} - -// MergeByteSliceCodecOptions combines the given *ByteSliceCodecOptions into a single *ByteSliceCodecOptions in a last one wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeByteSliceCodecOptions(opts ...*ByteSliceCodecOptions) *ByteSliceCodecOptions { - bs := ByteSliceCodec() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.EncodeNilAsEmpty != nil { - bs.EncodeNilAsEmpty = opt.EncodeNilAsEmpty - } - } - - return bs -} diff --git a/bson/bsonoptions/doc.go b/bson/bsonoptions/doc.go deleted file mode 100644 index c40973c8d4..0000000000 --- a/bson/bsonoptions/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2022-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 bsonoptions defines the optional configurations for the BSON codecs. -package bsonoptions diff --git a/bson/bsonoptions/empty_interface_codec_options.go b/bson/bsonoptions/empty_interface_codec_options.go deleted file mode 100644 index f522c7e03f..0000000000 --- a/bson/bsonoptions/empty_interface_codec_options.go +++ /dev/null @@ -1,49 +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 bsonoptions - -// EmptyInterfaceCodecOptions represents all possible options for interface{} encoding and decoding. -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -type EmptyInterfaceCodecOptions struct { - DecodeBinaryAsSlice *bool // Specifies if Old and Generic type binarys should default to []slice instead of primitive.Binary. Defaults to false. -} - -// EmptyInterfaceCodec creates a new *EmptyInterfaceCodecOptions -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -func EmptyInterfaceCodec() *EmptyInterfaceCodecOptions { - return &EmptyInterfaceCodecOptions{} -} - -// SetDecodeBinaryAsSlice specifies if Old and Generic type binarys should default to []slice instead of primitive.Binary. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.BinaryAsSlice] instead. -func (e *EmptyInterfaceCodecOptions) SetDecodeBinaryAsSlice(b bool) *EmptyInterfaceCodecOptions { - e.DecodeBinaryAsSlice = &b - return e -} - -// MergeEmptyInterfaceCodecOptions combines the given *EmptyInterfaceCodecOptions into a single *EmptyInterfaceCodecOptions in a last one wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeEmptyInterfaceCodecOptions(opts ...*EmptyInterfaceCodecOptions) *EmptyInterfaceCodecOptions { - e := EmptyInterfaceCodec() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.DecodeBinaryAsSlice != nil { - e.DecodeBinaryAsSlice = opt.DecodeBinaryAsSlice - } - } - - return e -} diff --git a/bson/bsonoptions/map_codec_options.go b/bson/bsonoptions/map_codec_options.go deleted file mode 100644 index a7a7c1d980..0000000000 --- a/bson/bsonoptions/map_codec_options.go +++ /dev/null @@ -1,82 +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 bsonoptions - -// MapCodecOptions represents all possible options for map encoding and decoding. -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -type MapCodecOptions struct { - DecodeZerosMap *bool // Specifies if the map should be zeroed before decoding into it. Defaults to false. - EncodeNilAsEmpty *bool // Specifies if a nil map should encode as an empty document instead of null. Defaults to false. - // Specifies how keys should be handled. If false, the behavior matches encoding/json, where the encoding key type must - // either be a string, an integer type, or implement bsoncodec.KeyMarshaler and the decoding key type must either be a - // string, an integer type, or implement bsoncodec.KeyUnmarshaler. If true, keys are encoded with fmt.Sprint() and the - // encoding key type must be a string, an integer type, or a float. If true, the use of Stringer will override - // TextMarshaler/TextUnmarshaler. Defaults to false. - EncodeKeysWithStringer *bool -} - -// MapCodec creates a new *MapCodecOptions -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -func MapCodec() *MapCodecOptions { - return &MapCodecOptions{} -} - -// SetDecodeZerosMap specifies if the map should be zeroed before decoding into it. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.ZeroMaps] instead. -func (t *MapCodecOptions) SetDecodeZerosMap(b bool) *MapCodecOptions { - t.DecodeZerosMap = &b - return t -} - -// SetEncodeNilAsEmpty specifies if a nil map should encode as an empty document instead of null. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilMapAsEmpty] instead. -func (t *MapCodecOptions) SetEncodeNilAsEmpty(b bool) *MapCodecOptions { - t.EncodeNilAsEmpty = &b - return t -} - -// SetEncodeKeysWithStringer specifies how keys should be handled. If false, the behavior matches encoding/json, where the -// encoding key type must either be a string, an integer type, or implement bsoncodec.KeyMarshaler and the decoding key -// type must either be a string, an integer type, or implement bsoncodec.KeyUnmarshaler. If true, keys are encoded with -// fmt.Sprint() and the encoding key type must be a string, an integer type, or a float. If true, the use of Stringer -// will override TextMarshaler/TextUnmarshaler. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.StringifyMapKeysWithFmt] instead. -func (t *MapCodecOptions) SetEncodeKeysWithStringer(b bool) *MapCodecOptions { - t.EncodeKeysWithStringer = &b - return t -} - -// MergeMapCodecOptions combines the given *MapCodecOptions into a single *MapCodecOptions in a last one wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeMapCodecOptions(opts ...*MapCodecOptions) *MapCodecOptions { - s := MapCodec() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.DecodeZerosMap != nil { - s.DecodeZerosMap = opt.DecodeZerosMap - } - if opt.EncodeNilAsEmpty != nil { - s.EncodeNilAsEmpty = opt.EncodeNilAsEmpty - } - if opt.EncodeKeysWithStringer != nil { - s.EncodeKeysWithStringer = opt.EncodeKeysWithStringer - } - } - - return s -} diff --git a/bson/bsonoptions/slice_codec_options.go b/bson/bsonoptions/slice_codec_options.go deleted file mode 100644 index 3c1e4f35ba..0000000000 --- a/bson/bsonoptions/slice_codec_options.go +++ /dev/null @@ -1,49 +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 bsonoptions - -// SliceCodecOptions represents all possible options for slice encoding and decoding. -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -type SliceCodecOptions struct { - EncodeNilAsEmpty *bool // Specifies if a nil slice should encode as an empty array instead of null. Defaults to false. -} - -// SliceCodec creates a new *SliceCodecOptions -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -func SliceCodec() *SliceCodecOptions { - return &SliceCodecOptions{} -} - -// SetEncodeNilAsEmpty specifies if a nil slice should encode as an empty array instead of null. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.NilSliceAsEmpty] instead. -func (s *SliceCodecOptions) SetEncodeNilAsEmpty(b bool) *SliceCodecOptions { - s.EncodeNilAsEmpty = &b - return s -} - -// MergeSliceCodecOptions combines the given *SliceCodecOptions into a single *SliceCodecOptions in a last one wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeSliceCodecOptions(opts ...*SliceCodecOptions) *SliceCodecOptions { - s := SliceCodec() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.EncodeNilAsEmpty != nil { - s.EncodeNilAsEmpty = opt.EncodeNilAsEmpty - } - } - - return s -} diff --git a/bson/bsonoptions/string_codec_options.go b/bson/bsonoptions/string_codec_options.go deleted file mode 100644 index f8b76f996e..0000000000 --- a/bson/bsonoptions/string_codec_options.go +++ /dev/null @@ -1,52 +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 bsonoptions - -var defaultDecodeOIDAsHex = true - -// StringCodecOptions represents all possible options for string encoding and decoding. -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -type StringCodecOptions struct { - DecodeObjectIDAsHex *bool // Specifies if we should decode ObjectID as the hex value. Defaults to true. -} - -// StringCodec creates a new *StringCodecOptions -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -func StringCodec() *StringCodecOptions { - return &StringCodecOptions{} -} - -// SetDecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation. If false, a string made -// from the raw object ID bytes will be used. Defaults to true. -// -// Deprecated: Decoding object IDs as raw bytes will not be supported in Go Driver 2.0. -func (t *StringCodecOptions) SetDecodeObjectIDAsHex(b bool) *StringCodecOptions { - t.DecodeObjectIDAsHex = &b - return t -} - -// MergeStringCodecOptions combines the given *StringCodecOptions into a single *StringCodecOptions in a last one wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeStringCodecOptions(opts ...*StringCodecOptions) *StringCodecOptions { - s := &StringCodecOptions{&defaultDecodeOIDAsHex} - for _, opt := range opts { - if opt == nil { - continue - } - if opt.DecodeObjectIDAsHex != nil { - s.DecodeObjectIDAsHex = opt.DecodeObjectIDAsHex - } - } - - return s -} diff --git a/bson/bsonoptions/struct_codec_options.go b/bson/bsonoptions/struct_codec_options.go deleted file mode 100644 index 1cbfa32e8b..0000000000 --- a/bson/bsonoptions/struct_codec_options.go +++ /dev/null @@ -1,107 +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 bsonoptions - -var defaultOverwriteDuplicatedInlinedFields = true - -// StructCodecOptions represents all possible options for struct encoding and decoding. -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -type StructCodecOptions struct { - DecodeZeroStruct *bool // Specifies if structs should be zeroed before decoding into them. Defaults to false. - DecodeDeepZeroInline *bool // Specifies if structs should be recursively zeroed when a inline value is decoded. Defaults to false. - EncodeOmitDefaultStruct *bool // Specifies if default structs should be considered empty by omitempty. Defaults to false. - AllowUnexportedFields *bool // Specifies if unexported fields should be marshaled/unmarshaled. Defaults to false. - OverwriteDuplicatedInlinedFields *bool // Specifies if fields in inlined structs can be overwritten by higher level struct fields with the same key. Defaults to true. -} - -// StructCodec creates a new *StructCodecOptions -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -func StructCodec() *StructCodecOptions { - return &StructCodecOptions{} -} - -// SetDecodeZeroStruct specifies if structs should be zeroed before decoding into them. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.ZeroStructs] instead. -func (t *StructCodecOptions) SetDecodeZeroStruct(b bool) *StructCodecOptions { - t.DecodeZeroStruct = &b - return t -} - -// SetDecodeDeepZeroInline specifies if structs should be zeroed before decoding into them. Defaults to false. -// -// Deprecated: DecodeDeepZeroInline will not be supported in Go Driver 2.0. -func (t *StructCodecOptions) SetDecodeDeepZeroInline(b bool) *StructCodecOptions { - t.DecodeDeepZeroInline = &b - return t -} - -// SetEncodeOmitDefaultStruct specifies if default structs should be considered empty by omitempty. A default struct has all -// its values set to their default value. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.OmitZeroStruct] instead. -func (t *StructCodecOptions) SetEncodeOmitDefaultStruct(b bool) *StructCodecOptions { - t.EncodeOmitDefaultStruct = &b - return t -} - -// SetOverwriteDuplicatedInlinedFields specifies if inlined struct fields can be overwritten by higher level struct fields with the -// same bson key. When true and decoding, values will be written to the outermost struct with a matching key, and when -// encoding, keys will have the value of the top-most matching field. When false, decoding and encoding will error if -// there are duplicate keys after the struct is inlined. Defaults to true. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.ErrorOnInlineDuplicates] instead. -func (t *StructCodecOptions) SetOverwriteDuplicatedInlinedFields(b bool) *StructCodecOptions { - t.OverwriteDuplicatedInlinedFields = &b - return t -} - -// SetAllowUnexportedFields specifies if unexported fields should be marshaled/unmarshaled. Defaults to false. -// -// Deprecated: AllowUnexportedFields does not work on recent versions of Go and will not be -// supported in Go Driver 2.0. -func (t *StructCodecOptions) SetAllowUnexportedFields(b bool) *StructCodecOptions { - t.AllowUnexportedFields = &b - return t -} - -// MergeStructCodecOptions combines the given *StructCodecOptions into a single *StructCodecOptions in a last one wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeStructCodecOptions(opts ...*StructCodecOptions) *StructCodecOptions { - s := &StructCodecOptions{ - OverwriteDuplicatedInlinedFields: &defaultOverwriteDuplicatedInlinedFields, - } - for _, opt := range opts { - if opt == nil { - continue - } - - if opt.DecodeZeroStruct != nil { - s.DecodeZeroStruct = opt.DecodeZeroStruct - } - if opt.DecodeDeepZeroInline != nil { - s.DecodeDeepZeroInline = opt.DecodeDeepZeroInline - } - if opt.EncodeOmitDefaultStruct != nil { - s.EncodeOmitDefaultStruct = opt.EncodeOmitDefaultStruct - } - if opt.OverwriteDuplicatedInlinedFields != nil { - s.OverwriteDuplicatedInlinedFields = opt.OverwriteDuplicatedInlinedFields - } - if opt.AllowUnexportedFields != nil { - s.AllowUnexportedFields = opt.AllowUnexportedFields - } - } - - return s -} diff --git a/bson/bsonoptions/time_codec_options.go b/bson/bsonoptions/time_codec_options.go deleted file mode 100644 index 3f38433d22..0000000000 --- a/bson/bsonoptions/time_codec_options.go +++ /dev/null @@ -1,49 +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 bsonoptions - -// TimeCodecOptions represents all possible options for time.Time encoding and decoding. -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -type TimeCodecOptions struct { - UseLocalTimeZone *bool // Specifies if we should decode into the local time zone. Defaults to false. -} - -// TimeCodec creates a new *TimeCodecOptions -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -func TimeCodec() *TimeCodecOptions { - return &TimeCodecOptions{} -} - -// SetUseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Decoder.UseLocalTimeZone] instead. -func (t *TimeCodecOptions) SetUseLocalTimeZone(b bool) *TimeCodecOptions { - t.UseLocalTimeZone = &b - return t -} - -// MergeTimeCodecOptions combines the given *TimeCodecOptions into a single *TimeCodecOptions in a last one wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeTimeCodecOptions(opts ...*TimeCodecOptions) *TimeCodecOptions { - t := TimeCodec() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.UseLocalTimeZone != nil { - t.UseLocalTimeZone = opt.UseLocalTimeZone - } - } - - return t -} diff --git a/bson/bsonoptions/uint_codec_options.go b/bson/bsonoptions/uint_codec_options.go deleted file mode 100644 index 5091e4d963..0000000000 --- a/bson/bsonoptions/uint_codec_options.go +++ /dev/null @@ -1,49 +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 bsonoptions - -// UIntCodecOptions represents all possible options for uint encoding and decoding. -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -type UIntCodecOptions struct { - EncodeToMinSize *bool // Specifies if all uints except uint64 should be decoded to minimum size bsontype. Defaults to false. -} - -// UIntCodec creates a new *UIntCodecOptions -// -// Deprecated: Use the bson.Encoder and bson.Decoder configuration methods to set the desired BSON marshal -// and unmarshal behavior instead. -func UIntCodec() *UIntCodecOptions { - return &UIntCodecOptions{} -} - -// SetEncodeToMinSize specifies if all uints except uint64 should be decoded to minimum size bsontype. Defaults to false. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.IntMinSize] instead. -func (u *UIntCodecOptions) SetEncodeToMinSize(b bool) *UIntCodecOptions { - u.EncodeToMinSize = &b - return u -} - -// MergeUIntCodecOptions combines the given *UIntCodecOptions into a single *UIntCodecOptions in a last one wins fashion. -// -// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a -// single options struct instead. -func MergeUIntCodecOptions(opts ...*UIntCodecOptions) *UIntCodecOptions { - u := UIntCodec() - for _, opt := range opts { - if opt == nil { - continue - } - if opt.EncodeToMinSize != nil { - u.EncodeToMinSize = opt.EncodeToMinSize - } - } - - return u -} diff --git a/bson/byte_slice_codec.go b/bson/byte_slice_codec.go index 586c006467..58be6623e3 100644 --- a/bson/byte_slice_codec.go +++ b/bson/byte_slice_codec.go @@ -9,56 +9,34 @@ package bson import ( "fmt" "reflect" - - "go.mongodb.org/mongo-driver/bson/bsonoptions" ) -// ByteSliceCodec is the Codec used for []byte values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// ByteSliceCodec registered. -type ByteSliceCodec struct { - // EncodeNilAsEmpty causes EncodeValue to marshal nil Go byte slices as empty BSON binary values +// byteSliceCodec is the Codec used for []byte values. +type byteSliceCodec struct { + // encodeNilAsEmpty causes EncodeValue to marshal nil Go byte slices as empty BSON binary values // instead of BSON null. - // - // Deprecated: Use bson.Encoder.NilByteSliceAsEmpty instead. - EncodeNilAsEmpty bool + encodeNilAsEmpty bool } var ( - defaultByteSliceCodec = NewByteSliceCodec() - - // Assert that defaultByteSliceCodec satisfies the typeDecoder interface, which allows it to be + // Assert that byteSliceCodec satisfies the typeDecoder interface, which allows it to be // used by collection type decoders (e.g. map, slice, etc) to set individual values in a // collection. - _ typeDecoder = defaultByteSliceCodec + _ typeDecoder = (*byteSliceCodec)(nil) ) -// NewByteSliceCodec returns a ByteSliceCodec with options opts. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// ByteSliceCodec registered. -func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec { - byteSliceOpt := bsonoptions.MergeByteSliceCodecOptions(opts...) - codec := ByteSliceCodec{} - if byteSliceOpt.EncodeNilAsEmpty != nil { - codec.EncodeNilAsEmpty = *byteSliceOpt.EncodeNilAsEmpty - } - return &codec -} - // EncodeValue is the ValueEncoder for []byte. -func (bsc *ByteSliceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +func (bsc *byteSliceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tByteSlice { return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val} } - if val.IsNil() && !bsc.EncodeNilAsEmpty && !ec.nilByteSliceAsEmpty { + if val.IsNil() && !bsc.encodeNilAsEmpty && !ec.nilByteSliceAsEmpty { return vw.WriteNull() } return vw.WriteBinary(val.Interface().([]byte)) } -func (bsc *ByteSliceCodec) decodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func (bsc *byteSliceCodec) decodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tByteSlice { return emptyValue, ValueDecoderError{ Name: "ByteSliceDecodeValue", @@ -106,7 +84,7 @@ func (bsc *ByteSliceCodec) decodeType(_ DecodeContext, vr ValueReader, t reflect } // DecodeValue is the ValueDecoder for []byte. -func (bsc *ByteSliceCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +func (bsc *byteSliceCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tByteSlice { return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val} } diff --git a/bson/decoder.go b/bson/decoder.go index 6ea5ad97c1..482927ef3d 100644 --- a/bson/decoder.go +++ b/bson/decoder.go @@ -31,8 +31,6 @@ type Decoder struct { dc DecodeContext vr ValueReader - // We persist defaultDocumentM and defaultDocumentD on the Decoder to prevent overwriting from - // (*Decoder).SetContext. defaultDocumentM bool defaultDocumentD bool diff --git a/bson/default_value_decoders.go b/bson/default_value_decoders.go index bc8c7b9344..2b2af20795 100644 --- a/bson/default_value_decoders.go +++ b/bson/default_value_decoders.go @@ -14,14 +14,12 @@ import ( "net/url" "reflect" "strconv" - "time" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) var ( - defaultValueDecoders DefaultValueDecoders - errCannotTruncate = errors.New("float64 can only be truncated to a lower precision type when truncation is enabled") + errCannotTruncate = errors.New("float64 can only be truncated to a lower precision type when truncation is enabled") ) type decodeBinaryError struct { @@ -33,112 +31,85 @@ func (d decodeBinaryError) Error() string { return fmt.Sprintf("only binary values with subtype 0x00 or 0x02 can be decoded into %s, but got subtype %v", d.typeName, d.subtype) } -func newDefaultStructCodec() *StructCodec { - codec, err := NewStructCodec(DefaultStructTagParser) - if err != nil { - // This function is called from the codec registration path, so errors can't be propagated. If there's an error - // constructing the StructCodec, we panic to avoid losing it. - panic(fmt.Errorf("error creating default StructCodec: %w", err)) - } - return codec -} - -// DefaultValueDecoders is a namespace type for the default ValueDecoders used -// when creating a registry. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -type DefaultValueDecoders struct{} - -// RegisterDefaultDecoders will register the decoder methods attached to DefaultValueDecoders with +// registerDefaultDecoders will register the decoder methods attached to DefaultValueDecoders with // the provided RegistryBuilder. // // There is no support for decoding map[string]interface{} because there is no decoder for // interface{}, so users must either register this decoder themselves or use the // EmptyInterfaceDecoder available in the bson package. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) RegisterDefaultDecoders(rb *RegistryBuilder) { - if rb == nil { - panic(errors.New("argument to RegisterDefaultDecoders must not be nil")) - } - - intDecoder := decodeAdapter{dvd.IntDecodeValue, dvd.intDecodeType} - floatDecoder := decodeAdapter{dvd.FloatDecodeValue, dvd.floatDecodeType} - - rb. - RegisterTypeDecoder(tD, ValueDecoderFunc(dvd.DDecodeValue)). - RegisterTypeDecoder(tBinary, decodeAdapter{dvd.BinaryDecodeValue, dvd.binaryDecodeType}). - RegisterTypeDecoder(tUndefined, decodeAdapter{dvd.UndefinedDecodeValue, dvd.undefinedDecodeType}). - RegisterTypeDecoder(tDateTime, decodeAdapter{dvd.DateTimeDecodeValue, dvd.dateTimeDecodeType}). - RegisterTypeDecoder(tNull, decodeAdapter{dvd.NullDecodeValue, dvd.nullDecodeType}). - RegisterTypeDecoder(tRegex, decodeAdapter{dvd.RegexDecodeValue, dvd.regexDecodeType}). - RegisterTypeDecoder(tDBPointer, decodeAdapter{dvd.DBPointerDecodeValue, dvd.dBPointerDecodeType}). - RegisterTypeDecoder(tTimestamp, decodeAdapter{dvd.TimestampDecodeValue, dvd.timestampDecodeType}). - RegisterTypeDecoder(tMinKey, decodeAdapter{dvd.MinKeyDecodeValue, dvd.minKeyDecodeType}). - RegisterTypeDecoder(tMaxKey, decodeAdapter{dvd.MaxKeyDecodeValue, dvd.maxKeyDecodeType}). - RegisterTypeDecoder(tJavaScript, decodeAdapter{dvd.JavaScriptDecodeValue, dvd.javaScriptDecodeType}). - RegisterTypeDecoder(tSymbol, decodeAdapter{dvd.SymbolDecodeValue, dvd.symbolDecodeType}). - RegisterTypeDecoder(tByteSlice, defaultByteSliceCodec). - RegisterTypeDecoder(tTime, defaultTimeCodec). - RegisterTypeDecoder(tEmpty, defaultEmptyInterfaceCodec). - RegisterTypeDecoder(tCoreArray, defaultArrayCodec). - RegisterTypeDecoder(tOID, decodeAdapter{dvd.ObjectIDDecodeValue, dvd.objectIDDecodeType}). - RegisterTypeDecoder(tDecimal, decodeAdapter{dvd.Decimal128DecodeValue, dvd.decimal128DecodeType}). - RegisterTypeDecoder(tJSONNumber, decodeAdapter{dvd.JSONNumberDecodeValue, dvd.jsonNumberDecodeType}). - RegisterTypeDecoder(tURL, decodeAdapter{dvd.URLDecodeValue, dvd.urlDecodeType}). - RegisterTypeDecoder(tCoreDocument, ValueDecoderFunc(dvd.CoreDocumentDecodeValue)). - RegisterTypeDecoder(tCodeWithScope, decodeAdapter{dvd.CodeWithScopeDecodeValue, dvd.codeWithScopeDecodeType}). - RegisterDefaultDecoder(reflect.Bool, decodeAdapter{dvd.BooleanDecodeValue, dvd.booleanDecodeType}). - RegisterDefaultDecoder(reflect.Int, intDecoder). - RegisterDefaultDecoder(reflect.Int8, intDecoder). - RegisterDefaultDecoder(reflect.Int16, intDecoder). - RegisterDefaultDecoder(reflect.Int32, intDecoder). - RegisterDefaultDecoder(reflect.Int64, intDecoder). - RegisterDefaultDecoder(reflect.Uint, defaultUIntCodec). - RegisterDefaultDecoder(reflect.Uint8, defaultUIntCodec). - RegisterDefaultDecoder(reflect.Uint16, defaultUIntCodec). - RegisterDefaultDecoder(reflect.Uint32, defaultUIntCodec). - RegisterDefaultDecoder(reflect.Uint64, defaultUIntCodec). - RegisterDefaultDecoder(reflect.Float32, floatDecoder). - RegisterDefaultDecoder(reflect.Float64, floatDecoder). - RegisterDefaultDecoder(reflect.Array, ValueDecoderFunc(dvd.ArrayDecodeValue)). - RegisterDefaultDecoder(reflect.Map, defaultMapCodec). - RegisterDefaultDecoder(reflect.Slice, defaultSliceCodec). - RegisterDefaultDecoder(reflect.String, defaultStringCodec). - RegisterDefaultDecoder(reflect.Struct, newDefaultStructCodec()). - RegisterDefaultDecoder(reflect.Ptr, NewPointerCodec()). - RegisterTypeMapEntry(TypeDouble, tFloat64). - RegisterTypeMapEntry(TypeString, tString). - RegisterTypeMapEntry(TypeArray, tA). - RegisterTypeMapEntry(TypeBinary, tBinary). - RegisterTypeMapEntry(TypeUndefined, tUndefined). - RegisterTypeMapEntry(TypeObjectID, tOID). - RegisterTypeMapEntry(TypeBoolean, tBool). - RegisterTypeMapEntry(TypeDateTime, tDateTime). - RegisterTypeMapEntry(TypeRegex, tRegex). - RegisterTypeMapEntry(TypeDBPointer, tDBPointer). - RegisterTypeMapEntry(TypeJavaScript, tJavaScript). - RegisterTypeMapEntry(TypeSymbol, tSymbol). - RegisterTypeMapEntry(TypeCodeWithScope, tCodeWithScope). - RegisterTypeMapEntry(TypeInt32, tInt32). - RegisterTypeMapEntry(TypeInt64, tInt64). - RegisterTypeMapEntry(TypeTimestamp, tTimestamp). - RegisterTypeMapEntry(TypeDecimal128, tDecimal). - RegisterTypeMapEntry(TypeMinKey, tMinKey). - RegisterTypeMapEntry(TypeMaxKey, tMaxKey). - RegisterTypeMapEntry(Type(0), tD). - RegisterTypeMapEntry(TypeEmbeddedDocument, tD). - RegisterHookDecoder(tValueUnmarshaler, ValueDecoderFunc(dvd.ValueUnmarshalerDecodeValue)). - RegisterHookDecoder(tUnmarshaler, ValueDecoderFunc(dvd.UnmarshalerDecodeValue)) +func registerDefaultDecoders(reg *Registry) { + intDecoder := decodeAdapter{intDecodeValue, intDecodeType} + floatDecoder := decodeAdapter{floatDecodeValue, floatDecodeType} + uintCodec := &uintCodec{} + + reg.RegisterTypeDecoder(tD, ValueDecoderFunc(dDecodeValue)) + reg.RegisterTypeDecoder(tBinary, decodeAdapter{binaryDecodeValue, binaryDecodeType}) + reg.RegisterTypeDecoder(tUndefined, decodeAdapter{undefinedDecodeValue, undefinedDecodeType}) + reg.RegisterTypeDecoder(tDateTime, decodeAdapter{dateTimeDecodeValue, dateTimeDecodeType}) + reg.RegisterTypeDecoder(tNull, decodeAdapter{nullDecodeValue, nullDecodeType}) + reg.RegisterTypeDecoder(tRegex, decodeAdapter{regexDecodeValue, regexDecodeType}) + reg.RegisterTypeDecoder(tDBPointer, decodeAdapter{dbPointerDecodeValue, dbPointerDecodeType}) + reg.RegisterTypeDecoder(tTimestamp, decodeAdapter{timestampDecodeValue, timestampDecodeType}) + reg.RegisterTypeDecoder(tMinKey, decodeAdapter{minKeyDecodeValue, minKeyDecodeType}) + reg.RegisterTypeDecoder(tMaxKey, decodeAdapter{maxKeyDecodeValue, maxKeyDecodeType}) + reg.RegisterTypeDecoder(tJavaScript, decodeAdapter{javaScriptDecodeValue, javaScriptDecodeType}) + reg.RegisterTypeDecoder(tSymbol, decodeAdapter{symbolDecodeValue, symbolDecodeType}) + reg.RegisterTypeDecoder(tByteSlice, &byteSliceCodec{}) + reg.RegisterTypeDecoder(tTime, &timeCodec{}) + reg.RegisterTypeDecoder(tEmpty, &emptyInterfaceCodec{}) + reg.RegisterTypeDecoder(tCoreArray, &arrayCodec{}) + reg.RegisterTypeDecoder(tOID, decodeAdapter{objectIDDecodeValue, objectIDDecodeType}) + reg.RegisterTypeDecoder(tDecimal, decodeAdapter{decimal128DecodeValue, decimal128DecodeType}) + reg.RegisterTypeDecoder(tJSONNumber, decodeAdapter{jsonNumberDecodeValue, jsonNumberDecodeType}) + reg.RegisterTypeDecoder(tURL, decodeAdapter{urlDecodeValue, urlDecodeType}) + reg.RegisterTypeDecoder(tCoreDocument, ValueDecoderFunc(coreDocumentDecodeValue)) + reg.RegisterTypeDecoder(tCodeWithScope, decodeAdapter{codeWithScopeDecodeValue, codeWithScopeDecodeType}) + reg.RegisterKindDecoder(reflect.Bool, decodeAdapter{booleanDecodeValue, booleanDecodeType}) + reg.RegisterKindDecoder(reflect.Int, intDecoder) + reg.RegisterKindDecoder(reflect.Int8, intDecoder) + reg.RegisterKindDecoder(reflect.Int16, intDecoder) + reg.RegisterKindDecoder(reflect.Int32, intDecoder) + reg.RegisterKindDecoder(reflect.Int64, intDecoder) + reg.RegisterKindDecoder(reflect.Uint, uintCodec) + reg.RegisterKindDecoder(reflect.Uint8, uintCodec) + reg.RegisterKindDecoder(reflect.Uint16, uintCodec) + reg.RegisterKindDecoder(reflect.Uint32, uintCodec) + reg.RegisterKindDecoder(reflect.Uint64, uintCodec) + reg.RegisterKindDecoder(reflect.Float32, floatDecoder) + reg.RegisterKindDecoder(reflect.Float64, floatDecoder) + reg.RegisterKindDecoder(reflect.Array, ValueDecoderFunc(arrayDecodeValue)) + reg.RegisterKindDecoder(reflect.Map, &mapCodec{}) + reg.RegisterKindDecoder(reflect.Slice, &sliceCodec{}) + reg.RegisterKindDecoder(reflect.String, &stringCodec{}) + reg.RegisterKindDecoder(reflect.Struct, newStructCodec(nil)) + reg.RegisterKindDecoder(reflect.Ptr, &pointerCodec{}) + reg.RegisterTypeMapEntry(TypeDouble, tFloat64) + reg.RegisterTypeMapEntry(TypeString, tString) + reg.RegisterTypeMapEntry(TypeArray, tA) + reg.RegisterTypeMapEntry(TypeBinary, tBinary) + reg.RegisterTypeMapEntry(TypeUndefined, tUndefined) + reg.RegisterTypeMapEntry(TypeObjectID, tOID) + reg.RegisterTypeMapEntry(TypeBoolean, tBool) + reg.RegisterTypeMapEntry(TypeDateTime, tDateTime) + reg.RegisterTypeMapEntry(TypeRegex, tRegex) + reg.RegisterTypeMapEntry(TypeDBPointer, tDBPointer) + reg.RegisterTypeMapEntry(TypeJavaScript, tJavaScript) + reg.RegisterTypeMapEntry(TypeSymbol, tSymbol) + reg.RegisterTypeMapEntry(TypeCodeWithScope, tCodeWithScope) + reg.RegisterTypeMapEntry(TypeInt32, tInt32) + reg.RegisterTypeMapEntry(TypeInt64, tInt64) + reg.RegisterTypeMapEntry(TypeTimestamp, tTimestamp) + reg.RegisterTypeMapEntry(TypeDecimal128, tDecimal) + reg.RegisterTypeMapEntry(TypeMinKey, tMinKey) + reg.RegisterTypeMapEntry(TypeMaxKey, tMaxKey) + reg.RegisterTypeMapEntry(Type(0), tD) + reg.RegisterTypeMapEntry(TypeEmbeddedDocument, tD) + reg.RegisterInterfaceDecoder(tValueUnmarshaler, ValueDecoderFunc(valueUnmarshalerDecodeValue)) + reg.RegisterInterfaceDecoder(tUnmarshaler, ValueDecoderFunc(unmarshalerDecodeValue)) } -// DDecodeValue is the ValueDecoderFunc for D instances. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// dDecodeValue is the ValueDecoderFunc for D instances. +func dDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.IsValid() || !val.CanSet() || val.Type() != tD { return ValueDecoderError{Name: "DDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} } @@ -194,7 +165,7 @@ func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr ValueReader, v return nil } -func (dvd DefaultValueDecoders) booleanDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func booleanDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t.Kind() != reflect.Bool { return emptyValue, ValueDecoderError{ Name: "BooleanDecodeValue", @@ -240,16 +211,13 @@ func (dvd DefaultValueDecoders) booleanDecodeType(_ DecodeContext, vr ValueReade return reflect.ValueOf(b), nil } -// BooleanDecodeValue is the ValueDecoderFunc for bool types. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) BooleanDecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { +// booleanDecodeValue is the ValueDecoderFunc for bool types. +func booleanDecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { if !val.IsValid() || !val.CanSet() || val.Kind() != reflect.Bool { return ValueDecoderError{Name: "BooleanDecodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val} } - elem, err := dvd.booleanDecodeType(dctx, vr, val.Type()) + elem, err := booleanDecodeType(dctx, vr, val.Type()) if err != nil { return err } @@ -258,7 +226,7 @@ func (dvd DefaultValueDecoders) BooleanDecodeValue(dctx DecodeContext, vr ValueR return nil } -func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func intDecodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { var i64 int64 var err error switch vrType := vr.Type(); vrType { @@ -341,11 +309,8 @@ func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr ValueReader, t re } } -// IntDecodeValue is the ValueDecoderFunc for int types. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) IntDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// intDecodeValue is the ValueDecoderFunc for int types. +func intDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() { return ValueDecoderError{ Name: "IntDecodeValue", @@ -354,7 +319,7 @@ func (dvd DefaultValueDecoders) IntDecodeValue(dc DecodeContext, vr ValueReader, } } - elem, err := dvd.intDecodeType(dc, vr, val.Type()) + elem, err := intDecodeType(dc, vr, val.Type()) if err != nil { return err } @@ -363,90 +328,7 @@ func (dvd DefaultValueDecoders) IntDecodeValue(dc DecodeContext, vr ValueReader, return nil } -// UintDecodeValue is the ValueDecoderFunc for uint types. -// -// Deprecated: UintDecodeValue is not registered by default. Use UintCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) UintDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { - var i64 int64 - var err error - switch vr.Type() { - case TypeInt32: - i32, err := vr.ReadInt32() - if err != nil { - return err - } - i64 = int64(i32) - case TypeInt64: - i64, err = vr.ReadInt64() - if err != nil { - return err - } - case TypeDouble: - f64, err := vr.ReadDouble() - if err != nil { - return err - } - if !dc.Truncate && math.Floor(f64) != f64 { - return errors.New("UintDecodeValue can only truncate float64 to an integer type when truncation is enabled") - } - if f64 > float64(math.MaxInt64) { - return fmt.Errorf("%g overflows int64", f64) - } - i64 = int64(f64) - case TypeBoolean: - b, err := vr.ReadBoolean() - if err != nil { - return err - } - if b { - i64 = 1 - } - default: - return fmt.Errorf("cannot decode %v into an integer type", vr.Type()) - } - - if !val.CanSet() { - return ValueDecoderError{ - Name: "UintDecodeValue", - Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, - Received: val, - } - } - - switch val.Kind() { - case reflect.Uint8: - if i64 < 0 || i64 > math.MaxUint8 { - return fmt.Errorf("%d overflows uint8", i64) - } - case reflect.Uint16: - if i64 < 0 || i64 > math.MaxUint16 { - return fmt.Errorf("%d overflows uint16", i64) - } - case reflect.Uint32: - if i64 < 0 || i64 > math.MaxUint32 { - return fmt.Errorf("%d overflows uint32", i64) - } - case reflect.Uint64: - if i64 < 0 { - return fmt.Errorf("%d overflows uint64", i64) - } - case reflect.Uint: - if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint - return fmt.Errorf("%d overflows uint", i64) - } - default: - return ValueDecoderError{ - Name: "UintDecodeValue", - Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, - Received: val, - } - } - - val.SetUint(uint64(i64)) - return nil -} - -func (dvd DefaultValueDecoders) floatDecodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func floatDecodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { var f float64 var err error switch vrType := vr.Type(); vrType { @@ -505,11 +387,8 @@ func (dvd DefaultValueDecoders) floatDecodeType(dc DecodeContext, vr ValueReader } } -// FloatDecodeValue is the ValueDecoderFunc for float types. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) FloatDecodeValue(ec DecodeContext, vr ValueReader, val reflect.Value) error { +// floatDecodeValue is the ValueDecoderFunc for float types. +func floatDecodeValue(ec DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() { return ValueDecoderError{ Name: "FloatDecodeValue", @@ -518,7 +397,7 @@ func (dvd DefaultValueDecoders) FloatDecodeValue(ec DecodeContext, vr ValueReade } } - elem, err := dvd.floatDecodeType(ec, vr, val.Type()) + elem, err := floatDecodeType(ec, vr, val.Type()) if err != nil { return err } @@ -527,31 +406,7 @@ func (dvd DefaultValueDecoders) FloatDecodeValue(ec DecodeContext, vr ValueReade return nil } -// StringDecodeValue is the ValueDecoderFunc for string types. -// -// Deprecated: StringDecodeValue is not registered by default. Use StringCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) StringDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { - var str string - var err error - switch vr.Type() { - // TODO(GODRIVER-577): Handle JavaScript and Symbol BSON types when allowed. - case TypeString: - str, err = vr.ReadString() - if err != nil { - return err - } - default: - return fmt.Errorf("cannot decode %v into a string type", vr.Type()) - } - if !val.CanSet() || val.Kind() != reflect.String { - return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val} - } - - val.SetString(str) - return nil -} - -func (DefaultValueDecoders) javaScriptDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func javaScriptDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tJavaScript { return emptyValue, ValueDecoderError{ Name: "JavaScriptDecodeValue", @@ -579,16 +434,13 @@ func (DefaultValueDecoders) javaScriptDecodeType(_ DecodeContext, vr ValueReader return reflect.ValueOf(JavaScript(js)), nil } -// JavaScriptDecodeValue is the ValueDecoderFunc for the JavaScript type. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) JavaScriptDecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { +// javaScriptDecodeValue is the ValueDecoderFunc for the JavaScript type. +func javaScriptDecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tJavaScript { return ValueDecoderError{Name: "JavaScriptDecodeValue", Types: []reflect.Type{tJavaScript}, Received: val} } - elem, err := dvd.javaScriptDecodeType(dctx, vr, tJavaScript) + elem, err := javaScriptDecodeType(dctx, vr, tJavaScript) if err != nil { return err } @@ -597,7 +449,7 @@ func (dvd DefaultValueDecoders) JavaScriptDecodeValue(dctx DecodeContext, vr Val return nil } -func (DefaultValueDecoders) symbolDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func symbolDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tSymbol { return emptyValue, ValueDecoderError{ Name: "SymbolDecodeValue", @@ -637,16 +489,13 @@ func (DefaultValueDecoders) symbolDecodeType(_ DecodeContext, vr ValueReader, t return reflect.ValueOf(Symbol(symbol)), nil } -// SymbolDecodeValue is the ValueDecoderFunc for the Symbol type. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) SymbolDecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { +// symbolDecodeValue is the ValueDecoderFunc for the Symbol type. +func symbolDecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tSymbol { return ValueDecoderError{Name: "SymbolDecodeValue", Types: []reflect.Type{tSymbol}, Received: val} } - elem, err := dvd.symbolDecodeType(dctx, vr, tSymbol) + elem, err := symbolDecodeType(dctx, vr, tSymbol) if err != nil { return err } @@ -655,7 +504,7 @@ func (dvd DefaultValueDecoders) SymbolDecodeValue(dctx DecodeContext, vr ValueRe return nil } -func (DefaultValueDecoders) binaryDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func binaryDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tBinary { return emptyValue, ValueDecoderError{ Name: "BinaryDecodeValue", @@ -684,16 +533,13 @@ func (DefaultValueDecoders) binaryDecodeType(_ DecodeContext, vr ValueReader, t return reflect.ValueOf(Binary{Subtype: subtype, Data: data}), nil } -// BinaryDecodeValue is the ValueDecoderFunc for Binary. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) BinaryDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// binaryDecodeValue is the ValueDecoderFunc for Binary. +func binaryDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tBinary { return ValueDecoderError{Name: "BinaryDecodeValue", Types: []reflect.Type{tBinary}, Received: val} } - elem, err := dvd.binaryDecodeType(dc, vr, tBinary) + elem, err := binaryDecodeType(dc, vr, tBinary) if err != nil { return err } @@ -702,7 +548,7 @@ func (dvd DefaultValueDecoders) BinaryDecodeValue(dc DecodeContext, vr ValueRead return nil } -func (DefaultValueDecoders) undefinedDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func undefinedDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tUndefined { return emptyValue, ValueDecoderError{ Name: "UndefinedDecodeValue", @@ -727,16 +573,13 @@ func (DefaultValueDecoders) undefinedDecodeType(_ DecodeContext, vr ValueReader, return reflect.ValueOf(Undefined{}), nil } -// UndefinedDecodeValue is the ValueDecoderFunc for Undefined. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) UndefinedDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// undefinedDecodeValue is the ValueDecoderFunc for Undefined. +func undefinedDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tUndefined { return ValueDecoderError{Name: "UndefinedDecodeValue", Types: []reflect.Type{tUndefined}, Received: val} } - elem, err := dvd.undefinedDecodeType(dc, vr, tUndefined) + elem, err := undefinedDecodeType(dc, vr, tUndefined) if err != nil { return err } @@ -746,7 +589,7 @@ func (dvd DefaultValueDecoders) UndefinedDecodeValue(dc DecodeContext, vr ValueR } // Accept both 12-byte string and pretty-printed 24-byte hex string formats. -func (dvd DefaultValueDecoders) objectIDDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func objectIDDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tOID { return emptyValue, ValueDecoderError{ Name: "ObjectIDDecodeValue", @@ -791,16 +634,13 @@ func (dvd DefaultValueDecoders) objectIDDecodeType(_ DecodeContext, vr ValueRead return reflect.ValueOf(oid), nil } -// ObjectIDDecodeValue is the ValueDecoderFunc for ObjectID. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) ObjectIDDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// objectIDDecodeValue is the ValueDecoderFunc for ObjectID. +func objectIDDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tOID { return ValueDecoderError{Name: "ObjectIDDecodeValue", Types: []reflect.Type{tOID}, Received: val} } - elem, err := dvd.objectIDDecodeType(dc, vr, tOID) + elem, err := objectIDDecodeType(dc, vr, tOID) if err != nil { return err } @@ -809,7 +649,7 @@ func (dvd DefaultValueDecoders) ObjectIDDecodeValue(dc DecodeContext, vr ValueRe return nil } -func (DefaultValueDecoders) dateTimeDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func dateTimeDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tDateTime { return emptyValue, ValueDecoderError{ Name: "DateTimeDecodeValue", @@ -837,16 +677,13 @@ func (DefaultValueDecoders) dateTimeDecodeType(_ DecodeContext, vr ValueReader, return reflect.ValueOf(DateTime(dt)), nil } -// DateTimeDecodeValue is the ValueDecoderFunc for DateTime. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) DateTimeDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// dateTimeDecodeValue is the ValueDecoderFunc for DateTime. +func dateTimeDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tDateTime { return ValueDecoderError{Name: "DateTimeDecodeValue", Types: []reflect.Type{tDateTime}, Received: val} } - elem, err := dvd.dateTimeDecodeType(dc, vr, tDateTime) + elem, err := dateTimeDecodeType(dc, vr, tDateTime) if err != nil { return err } @@ -855,7 +692,7 @@ func (dvd DefaultValueDecoders) DateTimeDecodeValue(dc DecodeContext, vr ValueRe return nil } -func (DefaultValueDecoders) nullDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func nullDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tNull { return emptyValue, ValueDecoderError{ Name: "NullDecodeValue", @@ -880,16 +717,13 @@ func (DefaultValueDecoders) nullDecodeType(_ DecodeContext, vr ValueReader, t re return reflect.ValueOf(Null{}), nil } -// NullDecodeValue is the ValueDecoderFunc for Null. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) NullDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// nullDecodeValue is the ValueDecoderFunc for Null. +func nullDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tNull { return ValueDecoderError{Name: "NullDecodeValue", Types: []reflect.Type{tNull}, Received: val} } - elem, err := dvd.nullDecodeType(dc, vr, tNull) + elem, err := nullDecodeType(dc, vr, tNull) if err != nil { return err } @@ -898,7 +732,7 @@ func (dvd DefaultValueDecoders) NullDecodeValue(dc DecodeContext, vr ValueReader return nil } -func (DefaultValueDecoders) regexDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func regexDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tRegex { return emptyValue, ValueDecoderError{ Name: "RegexDecodeValue", @@ -926,16 +760,13 @@ func (DefaultValueDecoders) regexDecodeType(_ DecodeContext, vr ValueReader, t r return reflect.ValueOf(Regex{Pattern: pattern, Options: options}), nil } -// RegexDecodeValue is the ValueDecoderFunc for Regex. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) RegexDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// regexDecodeValue is the ValueDecoderFunc for Regex. +func regexDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tRegex { return ValueDecoderError{Name: "RegexDecodeValue", Types: []reflect.Type{tRegex}, Received: val} } - elem, err := dvd.regexDecodeType(dc, vr, tRegex) + elem, err := regexDecodeType(dc, vr, tRegex) if err != nil { return err } @@ -944,7 +775,7 @@ func (dvd DefaultValueDecoders) RegexDecodeValue(dc DecodeContext, vr ValueReade return nil } -func (DefaultValueDecoders) dBPointerDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func dbPointerDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tDBPointer { return emptyValue, ValueDecoderError{ Name: "DBPointerDecodeValue", @@ -973,16 +804,13 @@ func (DefaultValueDecoders) dBPointerDecodeType(_ DecodeContext, vr ValueReader, return reflect.ValueOf(DBPointer{DB: ns, Pointer: pointer}), nil } -// DBPointerDecodeValue is the ValueDecoderFunc for DBPointer. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) DBPointerDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// dbPointerDecodeValue is the ValueDecoderFunc for DBPointer. +func dbPointerDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tDBPointer { return ValueDecoderError{Name: "DBPointerDecodeValue", Types: []reflect.Type{tDBPointer}, Received: val} } - elem, err := dvd.dBPointerDecodeType(dc, vr, tDBPointer) + elem, err := dbPointerDecodeType(dc, vr, tDBPointer) if err != nil { return err } @@ -991,7 +819,7 @@ func (dvd DefaultValueDecoders) DBPointerDecodeValue(dc DecodeContext, vr ValueR return nil } -func (DefaultValueDecoders) timestampDecodeType(_ DecodeContext, vr ValueReader, reflectType reflect.Type) (reflect.Value, error) { +func timestampDecodeType(_ DecodeContext, vr ValueReader, reflectType reflect.Type) (reflect.Value, error) { if reflectType != tTimestamp { return emptyValue, ValueDecoderError{ Name: "TimestampDecodeValue", @@ -1019,16 +847,13 @@ func (DefaultValueDecoders) timestampDecodeType(_ DecodeContext, vr ValueReader, return reflect.ValueOf(Timestamp{T: t, I: incr}), nil } -// TimestampDecodeValue is the ValueDecoderFunc for Timestamp. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) TimestampDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// timestampDecodeValue is the ValueDecoderFunc for Timestamp. +func timestampDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tTimestamp { return ValueDecoderError{Name: "TimestampDecodeValue", Types: []reflect.Type{tTimestamp}, Received: val} } - elem, err := dvd.timestampDecodeType(dc, vr, tTimestamp) + elem, err := timestampDecodeType(dc, vr, tTimestamp) if err != nil { return err } @@ -1037,7 +862,7 @@ func (dvd DefaultValueDecoders) TimestampDecodeValue(dc DecodeContext, vr ValueR return nil } -func (DefaultValueDecoders) minKeyDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func minKeyDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tMinKey { return emptyValue, ValueDecoderError{ Name: "MinKeyDecodeValue", @@ -1064,16 +889,13 @@ func (DefaultValueDecoders) minKeyDecodeType(_ DecodeContext, vr ValueReader, t return reflect.ValueOf(MinKey{}), nil } -// MinKeyDecodeValue is the ValueDecoderFunc for MinKey. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) MinKeyDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// minKeyDecodeValue is the ValueDecoderFunc for MinKey. +func minKeyDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tMinKey { return ValueDecoderError{Name: "MinKeyDecodeValue", Types: []reflect.Type{tMinKey}, Received: val} } - elem, err := dvd.minKeyDecodeType(dc, vr, tMinKey) + elem, err := minKeyDecodeType(dc, vr, tMinKey) if err != nil { return err } @@ -1082,7 +904,7 @@ func (dvd DefaultValueDecoders) MinKeyDecodeValue(dc DecodeContext, vr ValueRead return nil } -func (DefaultValueDecoders) maxKeyDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func maxKeyDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tMaxKey { return emptyValue, ValueDecoderError{ Name: "MaxKeyDecodeValue", @@ -1109,16 +931,13 @@ func (DefaultValueDecoders) maxKeyDecodeType(_ DecodeContext, vr ValueReader, t return reflect.ValueOf(MaxKey{}), nil } -// MaxKeyDecodeValue is the ValueDecoderFunc for MaxKey. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) MaxKeyDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// maxKeyDecodeValue is the ValueDecoderFunc for MaxKey. +func maxKeyDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tMaxKey { return ValueDecoderError{Name: "MaxKeyDecodeValue", Types: []reflect.Type{tMaxKey}, Received: val} } - elem, err := dvd.maxKeyDecodeType(dc, vr, tMaxKey) + elem, err := maxKeyDecodeType(dc, vr, tMaxKey) if err != nil { return err } @@ -1127,7 +946,7 @@ func (dvd DefaultValueDecoders) MaxKeyDecodeValue(dc DecodeContext, vr ValueRead return nil } -func (dvd DefaultValueDecoders) decimal128DecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func decimal128DecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tDecimal { return emptyValue, ValueDecoderError{ Name: "Decimal128DecodeValue", @@ -1155,16 +974,13 @@ func (dvd DefaultValueDecoders) decimal128DecodeType(_ DecodeContext, vr ValueRe return reflect.ValueOf(d128), nil } -// Decimal128DecodeValue is the ValueDecoderFunc for Decimal128. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) Decimal128DecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { +// decimal128DecodeValue is the ValueDecoderFunc for Decimal128. +func decimal128DecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tDecimal { return ValueDecoderError{Name: "Decimal128DecodeValue", Types: []reflect.Type{tDecimal}, Received: val} } - elem, err := dvd.decimal128DecodeType(dctx, vr, tDecimal) + elem, err := decimal128DecodeType(dctx, vr, tDecimal) if err != nil { return err } @@ -1173,7 +989,7 @@ func (dvd DefaultValueDecoders) Decimal128DecodeValue(dctx DecodeContext, vr Val return nil } -func (dvd DefaultValueDecoders) jsonNumberDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func jsonNumberDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tJSONNumber { return emptyValue, ValueDecoderError{ Name: "JSONNumberDecodeValue", @@ -1217,16 +1033,13 @@ func (dvd DefaultValueDecoders) jsonNumberDecodeType(_ DecodeContext, vr ValueRe return reflect.ValueOf(jsonNum), nil } -// JSONNumberDecodeValue is the ValueDecoderFunc for json.Number. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) JSONNumberDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// jsonNumberDecodeValue is the ValueDecoderFunc for json.Number. +func jsonNumberDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tJSONNumber { return ValueDecoderError{Name: "JSONNumberDecodeValue", Types: []reflect.Type{tJSONNumber}, Received: val} } - elem, err := dvd.jsonNumberDecodeType(dc, vr, tJSONNumber) + elem, err := jsonNumberDecodeType(dc, vr, tJSONNumber) if err != nil { return err } @@ -1235,7 +1048,7 @@ func (dvd DefaultValueDecoders) JSONNumberDecodeValue(dc DecodeContext, vr Value return nil } -func (dvd DefaultValueDecoders) urlDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func urlDecodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tURL { return emptyValue, ValueDecoderError{ Name: "URLDecodeValue", @@ -1269,16 +1082,13 @@ func (dvd DefaultValueDecoders) urlDecodeType(_ DecodeContext, vr ValueReader, t return reflect.ValueOf(urlPtr).Elem(), nil } -// URLDecodeValue is the ValueDecoderFunc for url.URL. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) URLDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// urlDecodeValue is the ValueDecoderFunc for url.URL. +func urlDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tURL { return ValueDecoderError{Name: "URLDecodeValue", Types: []reflect.Type{tURL}, Received: val} } - elem, err := dvd.urlDecodeType(dc, vr, tURL) + elem, err := urlDecodeType(dc, vr, tURL) if err != nil { return err } @@ -1287,119 +1097,8 @@ func (dvd DefaultValueDecoders) URLDecodeValue(dc DecodeContext, vr ValueReader, return nil } -// TimeDecodeValue is the ValueDecoderFunc for time.Time. -// -// Deprecated: TimeDecodeValue is not registered by default. Use TimeCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) TimeDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { - if vr.Type() != TypeDateTime { - return fmt.Errorf("cannot decode %v into a time.Time", vr.Type()) - } - - dt, err := vr.ReadDateTime() - if err != nil { - return err - } - - if !val.CanSet() || val.Type() != tTime { - return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val} - } - - val.Set(reflect.ValueOf(time.Unix(dt/1000, dt%1000*1000000).UTC())) - return nil -} - -// ByteSliceDecodeValue is the ValueDecoderFunc for []byte. -// -// Deprecated: ByteSliceDecodeValue is not registered by default. Use ByteSliceCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) ByteSliceDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { - if vr.Type() != TypeBinary && vr.Type() != TypeNull { - return fmt.Errorf("cannot decode %v into a []byte", vr.Type()) - } - - if !val.CanSet() || val.Type() != tByteSlice { - return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val} - } - - if vr.Type() == TypeNull { - val.Set(reflect.Zero(val.Type())) - return vr.ReadNull() - } - - data, subtype, err := vr.ReadBinary() - if err != nil { - return err - } - if subtype != 0x00 { - return fmt.Errorf("ByteSliceDecodeValue can only be used to decode subtype 0x00 for %s, got %v", TypeBinary, subtype) - } - - val.Set(reflect.ValueOf(data)) - return nil -} - -// MapDecodeValue is the ValueDecoderFunc for map[string]* types. -// -// Deprecated: MapDecodeValue is not registered by default. Use MapCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) MapDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { - if !val.CanSet() || val.Kind() != reflect.Map || val.Type().Key().Kind() != reflect.String { - return ValueDecoderError{Name: "MapDecodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} - } - - switch vr.Type() { - case Type(0), TypeEmbeddedDocument: - case TypeNull: - val.Set(reflect.Zero(val.Type())) - return vr.ReadNull() - default: - return fmt.Errorf("cannot decode %v into a %s", vr.Type(), val.Type()) - } - - dr, err := vr.ReadDocument() - if err != nil { - return err - } - - if val.IsNil() { - val.Set(reflect.MakeMap(val.Type())) - } - - eType := val.Type().Elem() - decoder, err := dc.LookupDecoder(eType) - if err != nil { - return err - } - - if eType == tEmpty { - dc.Ancestor = val.Type() - } - - keyType := val.Type().Key() - for { - key, vr, err := dr.ReadElement() - if errors.Is(err, ErrEOD) { - break - } - if err != nil { - return err - } - - elem := reflect.New(eType).Elem() - - err = decoder.DecodeValue(dc, vr, elem) - if err != nil { - return err - } - - val.SetMapIndex(reflect.ValueOf(key).Convert(keyType), elem) - } - return nil -} - -// ArrayDecodeValue is the ValueDecoderFunc for array types. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) ArrayDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// arrayDecodeValue is the ValueDecoderFunc for array types. +func arrayDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Array { return ValueDecoderError{Name: "ArrayDecodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val} } @@ -1443,9 +1142,9 @@ func (dvd DefaultValueDecoders) ArrayDecodeValue(dc DecodeContext, vr ValueReade var elemsFunc func(DecodeContext, ValueReader, reflect.Value) ([]reflect.Value, error) switch val.Type().Elem() { case tE: - elemsFunc = dvd.decodeD + elemsFunc = decodeD default: - elemsFunc = dvd.decodeDefault + elemsFunc = decodeDefault } elems, err := elemsFunc(dc, vr, val) @@ -1464,56 +1163,8 @@ func (dvd DefaultValueDecoders) ArrayDecodeValue(dc DecodeContext, vr ValueReade return nil } -// SliceDecodeValue is the ValueDecoderFunc for slice types. -// -// Deprecated: SliceDecodeValue is not registered by default. Use SliceCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) SliceDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { - if !val.CanSet() || val.Kind() != reflect.Slice { - return ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} - } - - switch vr.Type() { - case TypeArray: - case TypeNull: - val.Set(reflect.Zero(val.Type())) - return vr.ReadNull() - case Type(0), TypeEmbeddedDocument: - if val.Type().Elem() != tE { - return fmt.Errorf("cannot decode document into %s", val.Type()) - } - default: - return fmt.Errorf("cannot decode %v into a slice", vr.Type()) - } - - var elemsFunc func(DecodeContext, ValueReader, reflect.Value) ([]reflect.Value, error) - switch val.Type().Elem() { - case tE: - dc.Ancestor = val.Type() - elemsFunc = dvd.decodeD - default: - elemsFunc = dvd.decodeDefault - } - - elems, err := elemsFunc(dc, vr, val) - if err != nil { - return err - } - - if val.IsNil() { - val.Set(reflect.MakeSlice(val.Type(), 0, len(elems))) - } - - val.SetLen(0) - val.Set(reflect.Append(val, elems...)) - - return nil -} - -// ValueUnmarshalerDecodeValue is the ValueDecoderFunc for ValueUnmarshaler implementations. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { +// valueUnmarshalerDecodeValue is the ValueDecoderFunc for ValueUnmarshaler implementations. +func valueUnmarshalerDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { if !val.IsValid() || (!val.Type().Implements(tValueUnmarshaler) && !reflect.PtrTo(val.Type()).Implements(tValueUnmarshaler)) { return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} } @@ -1545,11 +1196,8 @@ func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(_ DecodeContext, vr return m.UnmarshalBSONValue(t, src) } -// UnmarshalerDecodeValue is the ValueDecoderFunc for Unmarshaler implementations. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { +// unmarshalerDecodeValue is the ValueDecoderFunc for Unmarshaler implementations. +func unmarshalerDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { if !val.IsValid() || (!val.Type().Implements(tUnmarshaler) && !reflect.PtrTo(val.Type()).Implements(tUnmarshaler)) { return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} } @@ -1593,51 +1241,8 @@ func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(_ DecodeContext, vr Value return m.UnmarshalBSON(src) } -// EmptyInterfaceDecodeValue is the ValueDecoderFunc for interface{}. -// -// Deprecated: EmptyInterfaceDecodeValue is not registered by default. Use EmptyInterfaceCodec.DecodeValue instead. -func (dvd DefaultValueDecoders) EmptyInterfaceDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { - if !val.CanSet() || val.Type() != tEmpty { - return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val} - } - - rtype, err := dc.LookupTypeMapEntry(vr.Type()) - if err != nil { - switch vr.Type() { - case TypeEmbeddedDocument: - if dc.Ancestor != nil { - rtype = dc.Ancestor - break - } - rtype = tD - case TypeNull: - val.Set(reflect.Zero(val.Type())) - return vr.ReadNull() - default: - return err - } - } - - decoder, err := dc.LookupDecoder(rtype) - if err != nil { - return err - } - - elem := reflect.New(rtype).Elem() - err = decoder.DecodeValue(dc, vr, elem) - if err != nil { - return err - } - - val.Set(elem) - return nil -} - -// CoreDocumentDecodeValue is the ValueDecoderFunc for bsoncore.Document. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (DefaultValueDecoders) CoreDocumentDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { +// coreDocumentDecodeValue is the ValueDecoderFunc for bsoncore.Document. +func coreDocumentDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tCoreDocument { return ValueDecoderError{Name: "CoreDocumentDecodeValue", Types: []reflect.Type{tCoreDocument}, Received: val} } @@ -1653,7 +1258,7 @@ func (DefaultValueDecoders) CoreDocumentDecodeValue(_ DecodeContext, vr ValueRea return err } -func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr ValueReader, val reflect.Value) ([]reflect.Value, error) { +func decodeDefault(dc DecodeContext, vr ValueReader, val reflect.Value) ([]reflect.Value, error) { elems := make([]reflect.Value, 0) ar, err := vr.ReadArray() @@ -1690,31 +1295,7 @@ func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr ValueReader, return elems, nil } -func (dvd DefaultValueDecoders) readCodeWithScope(dc DecodeContext, vr ValueReader) (CodeWithScope, error) { - var cws CodeWithScope - - code, dr, err := vr.ReadCodeWithScope() - if err != nil { - return cws, err - } - - scope := reflect.New(tD).Elem() - elems, err := dvd.decodeElemsFromDocumentReader(dc, dr) - if err != nil { - return cws, err - } - - scope.Set(reflect.MakeSlice(tD, 0, len(elems))) - scope.Set(reflect.Append(scope, elems...)) - - cws = CodeWithScope{ - Code: JavaScript(code), - Scope: scope.Interface().(D), - } - return cws, nil -} - -func (dvd DefaultValueDecoders) codeWithScopeDecodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func codeWithScopeDecodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tCodeWithScope { return emptyValue, ValueDecoderError{ Name: "CodeWithScopeDecodeValue", @@ -1727,7 +1308,24 @@ func (dvd DefaultValueDecoders) codeWithScopeDecodeType(dc DecodeContext, vr Val var err error switch vrType := vr.Type(); vrType { case TypeCodeWithScope: - cws, err = dvd.readCodeWithScope(dc, vr) + code, dr, err := vr.ReadCodeWithScope() + if err != nil { + return emptyValue, err + } + + scope := reflect.New(tD).Elem() + elems, err := decodeElemsFromDocumentReader(dc, dr) + if err != nil { + return emptyValue, err + } + + scope.Set(reflect.MakeSlice(tD, 0, len(elems))) + scope.Set(reflect.Append(scope, elems...)) + + cws = CodeWithScope{ + Code: JavaScript(code), + Scope: scope.Interface().(D), + } case TypeNull: err = vr.ReadNull() case TypeUndefined: @@ -1742,16 +1340,13 @@ func (dvd DefaultValueDecoders) codeWithScopeDecodeType(dc DecodeContext, vr Val return reflect.ValueOf(cws), nil } -// CodeWithScopeDecodeValue is the ValueDecoderFunc for CodeWithScope. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value decoders registered. -func (dvd DefaultValueDecoders) CodeWithScopeDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +// codeWithScopeDecodeValue is the ValueDecoderFunc for CodeWithScope. +func codeWithScopeDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tCodeWithScope { return ValueDecoderError{Name: "CodeWithScopeDecodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val} } - elem, err := dvd.codeWithScopeDecodeType(dc, vr, tCodeWithScope) + elem, err := codeWithScopeDecodeType(dc, vr, tCodeWithScope) if err != nil { return err } @@ -1760,7 +1355,7 @@ func (dvd DefaultValueDecoders) CodeWithScopeDecodeValue(dc DecodeContext, vr Va return nil } -func (dvd DefaultValueDecoders) decodeD(dc DecodeContext, vr ValueReader, _ reflect.Value) ([]reflect.Value, error) { +func decodeD(dc DecodeContext, vr ValueReader, _ reflect.Value) ([]reflect.Value, error) { switch vr.Type() { case Type(0), TypeEmbeddedDocument: default: @@ -1772,10 +1367,10 @@ func (dvd DefaultValueDecoders) decodeD(dc DecodeContext, vr ValueReader, _ refl return nil, err } - return dvd.decodeElemsFromDocumentReader(dc, dr) + return decodeElemsFromDocumentReader(dc, dr) } -func (DefaultValueDecoders) decodeElemsFromDocumentReader(dc DecodeContext, dr DocumentReader) ([]reflect.Value, error) { +func decodeElemsFromDocumentReader(dc DecodeContext, dr DocumentReader) ([]reflect.Value, error) { decoder, err := dc.LookupDecoder(tEmpty) if err != nil { return nil, err diff --git a/bson/default_value_decoders_test.go b/bson/default_value_decoders_test.go index 699a958605..9d95af257e 100644 --- a/bson/default_value_decoders_test.go +++ b/bson/default_value_decoders_test.go @@ -22,12 +22,7 @@ import ( "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) -var ( - defaultTestStructCodec = newDefaultStructCodec() -) - func TestDefaultValueDecoders(t *testing.T) { - var dvd DefaultValueDecoders var wrong = func(string, string) string { return "wrong" } type mybool bool @@ -71,7 +66,7 @@ func TestDefaultValueDecoders(t *testing.T) { }{ { "BooleanDecodeValue", - ValueDecoderFunc(dvd.BooleanDecodeValue), + ValueDecoderFunc(booleanDecodeValue), []subtest{ { "wrong type", @@ -140,7 +135,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "IntDecodeValue", - ValueDecoderFunc(dvd.IntDecodeValue), + ValueDecoderFunc(intDecodeValue), []subtest{ { "wrong type", @@ -372,7 +367,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "defaultUIntCodec.DecodeValue", - defaultUIntCodec, + &uintCodec{}, []subtest{ { "wrong type", @@ -608,7 +603,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "FloatDecodeValue", - ValueDecoderFunc(dvd.FloatDecodeValue), + ValueDecoderFunc(floatDecodeValue), []subtest{ { "wrong type", @@ -737,7 +732,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "defaultTimeCodec.DecodeValue", - defaultTimeCodec, + &timeCodec{}, []subtest{ { "wrong type", @@ -791,7 +786,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "defaultMapCodec.DecodeValue", - defaultMapCodec, + &mapCodec{}, []subtest{ { "wrong kind", @@ -820,7 +815,7 @@ func TestDefaultValueDecoders(t *testing.T) { { "Lookup Error", map[string]string{}, - &DecodeContext{Registry: newTestRegistryBuilder().Build()}, + &DecodeContext{Registry: newTestRegistry()}, &valueReaderWriter{}, readDocument, ErrNoDecoder{Type: reflect.TypeOf("")}, @@ -869,7 +864,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "ArrayDecodeValue", - ValueDecoderFunc(dvd.ArrayDecodeValue), + ValueDecoderFunc(arrayDecodeValue), []subtest{ { "wrong kind", @@ -906,7 +901,7 @@ func TestDefaultValueDecoders(t *testing.T) { { "Lookup Error", [1]string{}, - &DecodeContext{Registry: newTestRegistryBuilder().Build()}, + &DecodeContext{Registry: newTestRegistry()}, &valueReaderWriter{BSONType: TypeArray}, readArray, ErrNoDecoder{Type: reflect.TypeOf("")}, @@ -963,7 +958,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "defaultSliceCodec.DecodeValue", - defaultSliceCodec, + &sliceCodec{}, []subtest{ { "wrong kind", @@ -1000,7 +995,7 @@ func TestDefaultValueDecoders(t *testing.T) { { "Lookup Error", []string{}, - &DecodeContext{Registry: newTestRegistryBuilder().Build()}, + &DecodeContext{Registry: newTestRegistry()}, &valueReaderWriter{BSONType: TypeArray}, readArray, ErrNoDecoder{Type: reflect.TypeOf("")}, @@ -1057,7 +1052,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "ObjectIDDecodeValue", - ValueDecoderFunc(dvd.ObjectIDDecodeValue), + ValueDecoderFunc(objectIDDecodeValue), []subtest{ { "wrong type", @@ -1144,7 +1139,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "Decimal128DecodeValue", - ValueDecoderFunc(dvd.Decimal128DecodeValue), + ValueDecoderFunc(decimal128DecodeValue), []subtest{ { "wrong type", @@ -1206,7 +1201,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "JSONNumberDecodeValue", - ValueDecoderFunc(dvd.JSONNumberDecodeValue), + ValueDecoderFunc(jsonNumberDecodeValue), []subtest{ { "wrong type", @@ -1300,7 +1295,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "URLDecodeValue", - ValueDecoderFunc(dvd.URLDecodeValue), + ValueDecoderFunc(urlDecodeValue), []subtest{ { "wrong type", @@ -1374,7 +1369,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "defaultByteSliceCodec.DecodeValue", - defaultByteSliceCodec, + &byteSliceCodec{}, []subtest{ { "wrong type", @@ -1442,7 +1437,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "defaultStringCodec.DecodeValue", - defaultStringCodec, + &stringCodec{}, []subtest{ { "symbol", @@ -1472,7 +1467,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "ValueUnmarshalerDecodeValue", - ValueDecoderFunc(dvd.ValueUnmarshalerDecodeValue), + ValueDecoderFunc(valueUnmarshalerDecodeValue), []subtest{ { "wrong type", @@ -1506,7 +1501,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "UnmarshalerDecodeValue", - ValueDecoderFunc(dvd.UnmarshalerDecodeValue), + ValueDecoderFunc(unmarshalerDecodeValue), []subtest{ { "wrong type", @@ -1551,7 +1546,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "PointerCodec.DecodeValue", - NewPointerCodec(), + &pointerCodec{}, []subtest{ { "not valid", nil, nil, nil, nothing, @@ -1585,7 +1580,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "BinaryDecodeValue", - ValueDecoderFunc(dvd.BinaryDecodeValue), + ValueDecoderFunc(binaryDecodeValue), []subtest{ { "wrong type", @@ -1645,7 +1640,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "UndefinedDecodeValue", - ValueDecoderFunc(dvd.UndefinedDecodeValue), + ValueDecoderFunc(undefinedDecodeValue), []subtest{ { "wrong type", @@ -1691,7 +1686,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "DateTimeDecodeValue", - ValueDecoderFunc(dvd.DateTimeDecodeValue), + ValueDecoderFunc(dateTimeDecodeValue), []subtest{ { "wrong type", @@ -1745,7 +1740,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "NullDecodeValue", - ValueDecoderFunc(dvd.NullDecodeValue), + ValueDecoderFunc(nullDecodeValue), []subtest{ { "wrong type", @@ -1783,7 +1778,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "RegexDecodeValue", - ValueDecoderFunc(dvd.RegexDecodeValue), + ValueDecoderFunc(regexDecodeValue), []subtest{ { "wrong type", @@ -1843,7 +1838,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "DBPointerDecodeValue", - ValueDecoderFunc(dvd.DBPointerDecodeValue), + ValueDecoderFunc(dbPointerDecodeValue), []subtest{ { "wrong type", @@ -1908,7 +1903,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "TimestampDecodeValue", - ValueDecoderFunc(dvd.TimestampDecodeValue), + ValueDecoderFunc(timestampDecodeValue), []subtest{ { "wrong type", @@ -1968,7 +1963,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "MinKeyDecodeValue", - ValueDecoderFunc(dvd.MinKeyDecodeValue), + ValueDecoderFunc(minKeyDecodeValue), []subtest{ { "wrong type", @@ -2022,7 +2017,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "MaxKeyDecodeValue", - ValueDecoderFunc(dvd.MaxKeyDecodeValue), + ValueDecoderFunc(maxKeyDecodeValue), []subtest{ { "wrong type", @@ -2076,7 +2071,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "JavaScriptDecodeValue", - ValueDecoderFunc(dvd.JavaScriptDecodeValue), + ValueDecoderFunc(javaScriptDecodeValue), []subtest{ { "wrong type", @@ -2130,7 +2125,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "SymbolDecodeValue", - ValueDecoderFunc(dvd.SymbolDecodeValue), + ValueDecoderFunc(symbolDecodeValue), []subtest{ { "wrong type", @@ -2184,7 +2179,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "CoreDocumentDecodeValue", - ValueDecoderFunc(dvd.CoreDocumentDecodeValue), + ValueDecoderFunc(coreDocumentDecodeValue), []subtest{ { "wrong type", @@ -2222,7 +2217,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "StructCodec.DecodeValue", - defaultTestStructCodec, + newStructCodec(nil), []subtest{ { "Not struct", @@ -2252,7 +2247,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "CodeWithScopeDecodeValue", - ValueDecoderFunc(dvd.CodeWithScopeDecodeValue), + ValueDecoderFunc(codeWithScopeDecodeValue), []subtest{ { "wrong type", @@ -2313,7 +2308,7 @@ func TestDefaultValueDecoders(t *testing.T) { }, { "CoreArrayDecodeValue", - defaultArrayCodec, + &arrayCodec{}, []subtest{ { "wrong type", @@ -2439,7 +2434,7 @@ func TestDefaultValueDecoders(t *testing.T) { Scope: D{{"bar", nil}}, } val := reflect.New(tCodeWithScope).Elem() - err = dvd.CodeWithScopeDecodeValue(dc, vr, val) + err = codeWithScopeDecodeValue(dc, vr, val) noerr(t, err) got := val.Interface().(CodeWithScope) @@ -2454,7 +2449,7 @@ func TestDefaultValueDecoders(t *testing.T) { want := errors.New("ubsonv error") valUnmarshaler := &testValueUnmarshaler{err: want} - got := dvd.ValueUnmarshalerDecodeValue(dc, llvrw, reflect.ValueOf(valUnmarshaler)) + got := valueUnmarshalerDecodeValue(dc, llvrw, reflect.ValueOf(valUnmarshaler)) if !assert.CompareErrors(got, want) { t.Errorf("Errors do not match. got %v; want %v", got, want) } @@ -2466,20 +2461,12 @@ func TestDefaultValueDecoders(t *testing.T) { val := reflect.ValueOf(testValueUnmarshaler{}) want := ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} - got := dvd.ValueUnmarshalerDecodeValue(dc, llvrw, val) + got := valueUnmarshalerDecodeValue(dc, llvrw, val) if !assert.CompareErrors(got, want) { t.Errorf("Errors do not match. got %v; want %v", got, want) } }) - t.Run("SliceCodec/DecodeValue/can't set slice", func(t *testing.T) { - var val []string - want := ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: reflect.ValueOf(val)} - got := dvd.SliceDecodeValue(DecodeContext{}, nil, reflect.ValueOf(val)) - if !assert.CompareErrors(got, want) { - t.Errorf("Errors do not match. got %v; want %v", got, want) - } - }) t.Run("SliceCodec/DecodeValue/too many elements", func(t *testing.T) { idx, doc := bsoncore.AppendDocumentStart(nil) aidx, doc := bsoncore.AppendArrayElementStart(doc, "foo") @@ -2499,7 +2486,7 @@ func TestDefaultValueDecoders(t *testing.T) { want := fmt.Errorf("more elements returned in array than can fit inside %T, got 2 elements", val) dc := DecodeContext{Registry: buildDefaultRegistry()} - got := dvd.ArrayDecodeValue(dc, vr, reflect.ValueOf(val)) + got := arrayDecodeValue(dc, vr, reflect.ValueOf(val)) if !assert.CompareErrors(got, want) { t.Errorf("Errors do not match. got %v; want %v", got, want) } @@ -3319,9 +3306,9 @@ func TestDefaultValueDecoders(t *testing.T) { t.Skip() } val := reflect.New(tEmpty).Elem() - dc := DecodeContext{Registry: newTestRegistryBuilder().Build()} + dc := DecodeContext{Registry: newTestRegistry()} want := ErrNoTypeMapEntry{Type: tc.bsontype} - got := defaultEmptyInterfaceCodec.DecodeValue(dc, llvr, val) + got := (&emptyInterfaceCodec{}).DecodeValue(dc, llvr, val) if !assert.CompareErrors(got, want) { t.Errorf("Errors are not equal. got %v; want %v", got, want) } @@ -3332,13 +3319,13 @@ func TestDefaultValueDecoders(t *testing.T) { t.Skip() } val := reflect.New(tEmpty).Elem() + reg := newTestRegistry() + reg.RegisterTypeMapEntry(tc.bsontype, reflect.TypeOf(tc.val)) dc := DecodeContext{ - Registry: newTestRegistryBuilder(). - RegisterTypeMapEntry(tc.bsontype, reflect.TypeOf(tc.val)). - Build(), + Registry: reg, } want := ErrNoDecoder{Type: reflect.TypeOf(tc.val)} - got := defaultEmptyInterfaceCodec.DecodeValue(dc, llvr, val) + got := (&emptyInterfaceCodec{}).DecodeValue(dc, llvr, val) if !assert.CompareErrors(got, want) { t.Errorf("Errors are not equal. got %v; want %v", got, want) } @@ -3350,13 +3337,13 @@ func TestDefaultValueDecoders(t *testing.T) { } want := errors.New("DecodeValue failure error") llc := &llCodec{t: t, err: want} + reg := newTestRegistry() + reg.RegisterTypeDecoder(reflect.TypeOf(tc.val), llc) + reg.RegisterTypeMapEntry(tc.bsontype, reflect.TypeOf(tc.val)) dc := DecodeContext{ - Registry: newTestRegistryBuilder(). - RegisterTypeDecoder(reflect.TypeOf(tc.val), llc). - RegisterTypeMapEntry(tc.bsontype, reflect.TypeOf(tc.val)). - Build(), + Registry: reg, } - got := defaultEmptyInterfaceCodec.DecodeValue(dc, llvr, reflect.New(tEmpty).Elem()) + got := (&emptyInterfaceCodec{}).DecodeValue(dc, llvr, reflect.New(tEmpty).Elem()) if !assert.CompareErrors(got, want) { t.Errorf("Errors are not equal. got %v; want %v", got, want) } @@ -3365,14 +3352,14 @@ func TestDefaultValueDecoders(t *testing.T) { t.Run("Success", func(t *testing.T) { want := tc.val llc := &llCodec{t: t, decodeval: tc.val} + reg := newTestRegistry() + reg.RegisterTypeDecoder(reflect.TypeOf(tc.val), llc) + reg.RegisterTypeMapEntry(tc.bsontype, reflect.TypeOf(tc.val)) dc := DecodeContext{ - Registry: newTestRegistryBuilder(). - RegisterTypeDecoder(reflect.TypeOf(tc.val), llc). - RegisterTypeMapEntry(tc.bsontype, reflect.TypeOf(tc.val)). - Build(), + Registry: reg, } got := reflect.New(tEmpty).Elem() - err := defaultEmptyInterfaceCodec.DecodeValue(dc, llvr, got) + err := (&emptyInterfaceCodec{}).DecodeValue(dc, llvr, got) noerr(t, err) if !cmp.Equal(got.Interface(), want, cmp.Comparer(compareDecimal128)) { t.Errorf("Did not receive expected value. got %v; want %v", got.Interface(), want) @@ -3385,7 +3372,7 @@ func TestDefaultValueDecoders(t *testing.T) { t.Run("non-interface{}", func(t *testing.T) { val := uint64(1234567890) want := ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.ValueOf(val)} - got := defaultEmptyInterfaceCodec.DecodeValue(DecodeContext{}, nil, reflect.ValueOf(val)) + got := (&emptyInterfaceCodec{}).DecodeValue(DecodeContext{}, nil, reflect.ValueOf(val)) if !assert.CompareErrors(got, want) { t.Errorf("Errors are not equal. got %v; want %v", got, want) } @@ -3394,7 +3381,7 @@ func TestDefaultValueDecoders(t *testing.T) { t.Run("nil *interface{}", func(t *testing.T) { var val interface{} want := ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.ValueOf(val)} - got := defaultEmptyInterfaceCodec.DecodeValue(DecodeContext{}, nil, reflect.ValueOf(val)) + got := (&emptyInterfaceCodec{}).DecodeValue(DecodeContext{}, nil, reflect.ValueOf(val)) if !assert.CompareErrors(got, want) { t.Errorf("Errors are not equal. got %v; want %v", got, want) } @@ -3404,7 +3391,7 @@ func TestDefaultValueDecoders(t *testing.T) { llvr := &valueReaderWriter{BSONType: TypeDouble} want := ErrNoTypeMapEntry{Type: TypeDouble} val := reflect.New(tEmpty).Elem() - got := defaultEmptyInterfaceCodec.DecodeValue(DecodeContext{Registry: newTestRegistryBuilder().Build()}, llvr, val) + got := (&emptyInterfaceCodec{}).DecodeValue(DecodeContext{Registry: newTestRegistry()}, llvr, val) if !assert.CompareErrors(got, want) { t.Errorf("Errors are not equal. got %v; want %v", got, want) } @@ -3415,7 +3402,7 @@ func TestDefaultValueDecoders(t *testing.T) { want := D{{"pi", 3.14159}} var got interface{} val := reflect.ValueOf(&got).Elem() - err := defaultEmptyInterfaceCodec.DecodeValue(DecodeContext{Registry: buildDefaultRegistry()}, vr, val) + err := (&emptyInterfaceCodec{}).DecodeValue(DecodeContext{Registry: buildDefaultRegistry()}, vr, val) noerr(t, err) if !cmp.Equal(got, want) { t.Errorf("Did not get correct result. got %v; want %v", got, want) @@ -3425,15 +3412,25 @@ func TestDefaultValueDecoders(t *testing.T) { // registering a custom type map entry for both Type(0) anad TypeEmbeddedDocument should cause // both top-level and embedded documents to decode to registered type when unmarshalling to interface{} - topLevelRb := newTestRegistryBuilder() - defaultValueEncoders.RegisterDefaultEncoders(topLevelRb) - defaultValueDecoders.RegisterDefaultDecoders(topLevelRb) - topLevelRb.RegisterTypeMapEntry(Type(0), reflect.TypeOf(M{})) - - embeddedRb := newTestRegistryBuilder() - defaultValueEncoders.RegisterDefaultEncoders(embeddedRb) - defaultValueDecoders.RegisterDefaultDecoders(embeddedRb) - embeddedRb.RegisterTypeMapEntry(Type(0), reflect.TypeOf(M{})) + topLevelReg := &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), + } + registerDefaultEncoders(topLevelReg) + registerDefaultDecoders(topLevelReg) + topLevelReg.RegisterTypeMapEntry(Type(0), reflect.TypeOf(M{})) + + embeddedReg := &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), + } + registerDefaultEncoders(embeddedReg) + registerDefaultDecoders(embeddedReg) + embeddedReg.RegisterTypeMapEntry(Type(0), reflect.TypeOf(M{})) // create doc {"nested": {"foo": 1}} innerDoc := bsoncore.BuildDocument( @@ -3454,15 +3451,15 @@ func TestDefaultValueDecoders(t *testing.T) { name string registry *Registry }{ - {"top level", topLevelRb.Build()}, - {"embedded", embeddedRb.Build()}, + {"top level", topLevelReg}, + {"embedded", embeddedReg}, } for _, tc := range testCases { var got interface{} vr := NewValueReader(doc) val := reflect.ValueOf(&got).Elem() - err := defaultEmptyInterfaceCodec.DecodeValue(DecodeContext{Registry: tc.registry}, vr, val) + err := (&emptyInterfaceCodec{}).DecodeValue(DecodeContext{Registry: tc.registry}, vr, val) noerr(t, err) if !cmp.Equal(got, want) { t.Fatalf("got %v, want %v", got, want) @@ -3473,11 +3470,15 @@ func TestDefaultValueDecoders(t *testing.T) { // If a type map entry is registered for TypeEmbeddedDocument, the decoder should use ancestor // information if available instead of the registered entry. - rb := newTestRegistryBuilder() - defaultValueEncoders.RegisterDefaultEncoders(rb) - defaultValueDecoders.RegisterDefaultDecoders(rb) - rb.RegisterTypeMapEntry(TypeEmbeddedDocument, reflect.TypeOf(M{})) - reg := rb.Build() + reg := &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), + } + registerDefaultEncoders(reg) + registerDefaultDecoders(reg) + reg.RegisterTypeMapEntry(TypeEmbeddedDocument, reflect.TypeOf(M{})) // build document {"nested": {"foo": 10}} inner := bsoncore.BuildDocument( @@ -3497,7 +3498,7 @@ func TestDefaultValueDecoders(t *testing.T) { var got D vr := NewValueReader(doc) val := reflect.ValueOf(&got).Elem() - err := defaultSliceCodec.DecodeValue(DecodeContext{Registry: reg}, vr, val) + err := (&sliceCodec{}).DecodeValue(DecodeContext{Registry: reg}, vr, val) noerr(t, err) if !cmp.Equal(got, want) { t.Fatalf("got %v, want %v", got, want) @@ -3510,8 +3511,8 @@ func TestDefaultValueDecoders(t *testing.T) { emptyInterfaceErrorDecode := func(DecodeContext, ValueReader, reflect.Value) error { return decodeValueError } - emptyInterfaceErrorRegistry := newTestRegistryBuilder(). - RegisterTypeDecoder(tEmpty, ValueDecoderFunc(emptyInterfaceErrorDecode)).Build() + emptyInterfaceErrorRegistry := newTestRegistry() + emptyInterfaceErrorRegistry.RegisterTypeDecoder(tEmpty, ValueDecoderFunc(emptyInterfaceErrorDecode)) // Set up a document {foo: 10} and an error that would happen if the value were decoded into interface{} // using the registry defined above. @@ -3563,11 +3564,14 @@ func TestDefaultValueDecoders(t *testing.T) { outerDoc := buildDocument(bsoncore.AppendDocumentElement(nil, "first", inner1Doc)) // Use a registry that has all default decoders with the custom interface{} decoder that always errors. - nestedRegistryBuilder := newTestRegistryBuilder() - defaultValueDecoders.RegisterDefaultDecoders(nestedRegistryBuilder) - nestedRegistry := nestedRegistryBuilder. - RegisterTypeDecoder(tEmpty, ValueDecoderFunc(emptyInterfaceErrorDecode)). - Build() + nestedRegistry := &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), + } + registerDefaultDecoders(nestedRegistry) + nestedRegistry.RegisterTypeDecoder(tEmpty, ValueDecoderFunc(emptyInterfaceErrorDecode)) nestedErr := &DecodeError{ keys: []string{"fourth", "1", "third", "randomKey", "second", "first"}, wrapped: decodeValueError, @@ -3587,7 +3591,7 @@ func TestDefaultValueDecoders(t *testing.T) { D{}, NewValueReader(docBytes), emptyInterfaceErrorRegistry, - defaultSliceCodec, + &sliceCodec{}, docEmptyInterfaceErr, }, { @@ -3596,7 +3600,7 @@ func TestDefaultValueDecoders(t *testing.T) { []string{}, &valueReaderWriter{BSONType: TypeArray}, nil, - defaultSliceCodec, + &sliceCodec{}, &DecodeError{ keys: []string{"0"}, wrapped: errors.New("cannot decode array into a string type"), @@ -3610,7 +3614,7 @@ func TestDefaultValueDecoders(t *testing.T) { [1]E{}, NewValueReader(docBytes), emptyInterfaceErrorRegistry, - ValueDecoderFunc(dvd.ArrayDecodeValue), + ValueDecoderFunc(arrayDecodeValue), docEmptyInterfaceErr, }, { @@ -3621,7 +3625,7 @@ func TestDefaultValueDecoders(t *testing.T) { [1]string{}, &valueReaderWriter{BSONType: TypeArray}, nil, - ValueDecoderFunc(dvd.ArrayDecodeValue), + ValueDecoderFunc(arrayDecodeValue), &DecodeError{ keys: []string{"0"}, wrapped: errors.New("cannot decode array into a string type"), @@ -3633,7 +3637,7 @@ func TestDefaultValueDecoders(t *testing.T) { map[string]interface{}{}, NewValueReader(docBytes), emptyInterfaceErrorRegistry, - defaultMapCodec, + &mapCodec{}, docEmptyInterfaceErr, }, { @@ -3642,7 +3646,7 @@ func TestDefaultValueDecoders(t *testing.T) { emptyInterfaceStruct{}, NewValueReader(docBytes), emptyInterfaceErrorRegistry, - defaultTestStructCodec, + newStructCodec(nil), emptyInterfaceStructErr, }, { @@ -3652,8 +3656,8 @@ func TestDefaultValueDecoders(t *testing.T) { "struct - no decoder found", stringStruct{}, NewValueReader(docBytes), - newTestRegistryBuilder().Build(), - defaultTestStructCodec, + newTestRegistry(), + newStructCodec(nil), stringStructErr, }, { @@ -3661,7 +3665,7 @@ func TestDefaultValueDecoders(t *testing.T) { outer{}, NewValueReader(outerDoc), nestedRegistry, - defaultTestStructCodec, + newStructCodec(nil), nestedErr, }, } @@ -3691,7 +3695,7 @@ func TestDefaultValueDecoders(t *testing.T) { dc := DecodeContext{Registry: buildDefaultRegistry()} vr := NewValueReader(outerBytes) val := reflect.New(reflect.TypeOf(outer{})).Elem() - err := defaultTestStructCodec.DecodeValue(dc, vr, val) + err := newStructCodec(nil).DecodeValue(dc, vr, val) var decodeErr *DecodeError assert.True(t, errors.As(err, &decodeErr), "expected DecodeError, got %v of type %T", err, err) @@ -3717,14 +3721,19 @@ func TestDefaultValueDecoders(t *testing.T) { bsoncore.BuildArrayElement(nil, "boolArray", trueValue), ) - rb := newTestRegistryBuilder() - defaultValueDecoders.RegisterDefaultDecoders(rb) - reg := rb.RegisterTypeMapEntry(TypeBoolean, reflect.TypeOf(mybool(true))).Build() + reg := &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), + } + registerDefaultDecoders(reg) + reg.RegisterTypeMapEntry(TypeBoolean, reflect.TypeOf(mybool(true))) dc := DecodeContext{Registry: reg} vr := NewValueReader(docBytes) val := reflect.New(tD).Elem() - err := defaultValueDecoders.DDecodeValue(dc, vr, val) + err := dDecodeValue(dc, vr, val) assert.Nil(t, err, "DDecodeValue error: %v", err) want := D{ @@ -3743,7 +3752,7 @@ func TestDefaultValueDecoders(t *testing.T) { dc := DecodeContext{Registry: buildDefaultRegistry()} vr := NewValueReader(docBytes) val := reflect.New(reflect.TypeOf(myMap{})).Elem() - err := defaultMapCodec.DecodeValue(dc, vr, val) + err := (&mapCodec{}).DecodeValue(dc, vr, val) assert.Nil(t, err, "DecodeValue error: %v", err) want := myMap{ @@ -3786,8 +3795,13 @@ func buildDocument(elems []byte) []byte { } func buildDefaultRegistry() *Registry { - rb := newTestRegistryBuilder() - defaultValueEncoders.RegisterDefaultEncoders(rb) - defaultValueDecoders.RegisterDefaultDecoders(rb) - return rb.Build() + reg := &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), + } + registerDefaultEncoders(reg) + registerDefaultDecoders(reg) + return reg } diff --git a/bson/default_value_encoders.go b/bson/default_value_encoders.go index f2773c36e5..c3ef806cb6 100644 --- a/bson/default_value_encoders.go +++ b/bson/default_value_encoders.go @@ -9,18 +9,14 @@ package bson import ( "encoding/json" "errors" - "fmt" "math" "net/url" "reflect" "sync" - "time" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) -var defaultValueEncoders DefaultValueEncoders - var bvwPool = NewValueWriterPool() var errInvalidValue = errors.New("cannot encode invalid element") @@ -53,73 +49,59 @@ func encodeElement(ec EncodeContext, dw DocumentWriter, e E) error { return nil } -// DefaultValueEncoders is a namespace type for the default ValueEncoders used -// when creating a registry. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -type DefaultValueEncoders struct{} - -// RegisterDefaultEncoders will register the encoder methods attached to DefaultValueEncoders with +// registerDefaultEncoders will register the encoder methods attached to DefaultValueEncoders with // the provided RegistryBuilder. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) RegisterDefaultEncoders(rb *RegistryBuilder) { - if rb == nil { - panic(errors.New("argument to RegisterDefaultEncoders must not be nil")) - } - rb. - RegisterTypeEncoder(tByteSlice, defaultByteSliceCodec). - RegisterTypeEncoder(tTime, defaultTimeCodec). - RegisterTypeEncoder(tEmpty, defaultEmptyInterfaceCodec). - RegisterTypeEncoder(tCoreArray, defaultArrayCodec). - RegisterTypeEncoder(tOID, ValueEncoderFunc(dve.ObjectIDEncodeValue)). - RegisterTypeEncoder(tDecimal, ValueEncoderFunc(dve.Decimal128EncodeValue)). - RegisterTypeEncoder(tJSONNumber, ValueEncoderFunc(dve.JSONNumberEncodeValue)). - RegisterTypeEncoder(tURL, ValueEncoderFunc(dve.URLEncodeValue)). - RegisterTypeEncoder(tJavaScript, ValueEncoderFunc(dve.JavaScriptEncodeValue)). - RegisterTypeEncoder(tSymbol, ValueEncoderFunc(dve.SymbolEncodeValue)). - RegisterTypeEncoder(tBinary, ValueEncoderFunc(dve.BinaryEncodeValue)). - RegisterTypeEncoder(tUndefined, ValueEncoderFunc(dve.UndefinedEncodeValue)). - RegisterTypeEncoder(tDateTime, ValueEncoderFunc(dve.DateTimeEncodeValue)). - RegisterTypeEncoder(tNull, ValueEncoderFunc(dve.NullEncodeValue)). - RegisterTypeEncoder(tRegex, ValueEncoderFunc(dve.RegexEncodeValue)). - RegisterTypeEncoder(tDBPointer, ValueEncoderFunc(dve.DBPointerEncodeValue)). - RegisterTypeEncoder(tTimestamp, ValueEncoderFunc(dve.TimestampEncodeValue)). - RegisterTypeEncoder(tMinKey, ValueEncoderFunc(dve.MinKeyEncodeValue)). - RegisterTypeEncoder(tMaxKey, ValueEncoderFunc(dve.MaxKeyEncodeValue)). - RegisterTypeEncoder(tCoreDocument, ValueEncoderFunc(dve.CoreDocumentEncodeValue)). - RegisterTypeEncoder(tCodeWithScope, ValueEncoderFunc(dve.CodeWithScopeEncodeValue)). - RegisterDefaultEncoder(reflect.Bool, ValueEncoderFunc(dve.BooleanEncodeValue)). - RegisterDefaultEncoder(reflect.Int, ValueEncoderFunc(dve.IntEncodeValue)). - RegisterDefaultEncoder(reflect.Int8, ValueEncoderFunc(dve.IntEncodeValue)). - RegisterDefaultEncoder(reflect.Int16, ValueEncoderFunc(dve.IntEncodeValue)). - RegisterDefaultEncoder(reflect.Int32, ValueEncoderFunc(dve.IntEncodeValue)). - RegisterDefaultEncoder(reflect.Int64, ValueEncoderFunc(dve.IntEncodeValue)). - RegisterDefaultEncoder(reflect.Uint, defaultUIntCodec). - RegisterDefaultEncoder(reflect.Uint8, defaultUIntCodec). - RegisterDefaultEncoder(reflect.Uint16, defaultUIntCodec). - RegisterDefaultEncoder(reflect.Uint32, defaultUIntCodec). - RegisterDefaultEncoder(reflect.Uint64, defaultUIntCodec). - RegisterDefaultEncoder(reflect.Float32, ValueEncoderFunc(dve.FloatEncodeValue)). - RegisterDefaultEncoder(reflect.Float64, ValueEncoderFunc(dve.FloatEncodeValue)). - RegisterDefaultEncoder(reflect.Array, ValueEncoderFunc(dve.ArrayEncodeValue)). - RegisterDefaultEncoder(reflect.Map, defaultMapCodec). - RegisterDefaultEncoder(reflect.Slice, defaultSliceCodec). - RegisterDefaultEncoder(reflect.String, defaultStringCodec). - RegisterDefaultEncoder(reflect.Struct, newDefaultStructCodec()). - RegisterDefaultEncoder(reflect.Ptr, NewPointerCodec()). - RegisterHookEncoder(tValueMarshaler, ValueEncoderFunc(dve.ValueMarshalerEncodeValue)). - RegisterHookEncoder(tMarshaler, ValueEncoderFunc(dve.MarshalerEncodeValue)). - RegisterHookEncoder(tProxy, ValueEncoderFunc(dve.ProxyEncodeValue)) -} - -// BooleanEncodeValue is the ValueEncoderFunc for bool types. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) BooleanEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +func registerDefaultEncoders(reg *Registry) { + mapEncoder := &mapCodec{} + uintCodec := &uintCodec{} + + reg.RegisterTypeEncoder(tByteSlice, &byteSliceCodec{}) + reg.RegisterTypeEncoder(tTime, &timeCodec{}) + reg.RegisterTypeEncoder(tEmpty, &emptyInterfaceCodec{}) + reg.RegisterTypeEncoder(tCoreArray, &arrayCodec{}) + reg.RegisterTypeEncoder(tOID, ValueEncoderFunc(objectIDEncodeValue)) + reg.RegisterTypeEncoder(tDecimal, ValueEncoderFunc(decimal128EncodeValue)) + reg.RegisterTypeEncoder(tJSONNumber, ValueEncoderFunc(jsonNumberEncodeValue)) + reg.RegisterTypeEncoder(tURL, ValueEncoderFunc(urlEncodeValue)) + reg.RegisterTypeEncoder(tJavaScript, ValueEncoderFunc(javaScriptEncodeValue)) + reg.RegisterTypeEncoder(tSymbol, ValueEncoderFunc(symbolEncodeValue)) + reg.RegisterTypeEncoder(tBinary, ValueEncoderFunc(binaryEncodeValue)) + reg.RegisterTypeEncoder(tUndefined, ValueEncoderFunc(undefinedEncodeValue)) + reg.RegisterTypeEncoder(tDateTime, ValueEncoderFunc(dateTimeEncodeValue)) + reg.RegisterTypeEncoder(tNull, ValueEncoderFunc(nullEncodeValue)) + reg.RegisterTypeEncoder(tRegex, ValueEncoderFunc(regexEncodeValue)) + reg.RegisterTypeEncoder(tDBPointer, ValueEncoderFunc(dbPointerEncodeValue)) + reg.RegisterTypeEncoder(tTimestamp, ValueEncoderFunc(timestampEncodeValue)) + reg.RegisterTypeEncoder(tMinKey, ValueEncoderFunc(minKeyEncodeValue)) + reg.RegisterTypeEncoder(tMaxKey, ValueEncoderFunc(maxKeyEncodeValue)) + reg.RegisterTypeEncoder(tCoreDocument, ValueEncoderFunc(coreDocumentEncodeValue)) + reg.RegisterTypeEncoder(tCodeWithScope, ValueEncoderFunc(codeWithScopeEncodeValue)) + reg.RegisterKindEncoder(reflect.Bool, ValueEncoderFunc(booleanEncodeValue)) + reg.RegisterKindEncoder(reflect.Int, ValueEncoderFunc(intEncodeValue)) + reg.RegisterKindEncoder(reflect.Int8, ValueEncoderFunc(intEncodeValue)) + reg.RegisterKindEncoder(reflect.Int16, ValueEncoderFunc(intEncodeValue)) + reg.RegisterKindEncoder(reflect.Int32, ValueEncoderFunc(intEncodeValue)) + reg.RegisterKindEncoder(reflect.Int64, ValueEncoderFunc(intEncodeValue)) + reg.RegisterKindEncoder(reflect.Uint, uintCodec) + reg.RegisterKindEncoder(reflect.Uint8, uintCodec) + reg.RegisterKindEncoder(reflect.Uint16, uintCodec) + reg.RegisterKindEncoder(reflect.Uint32, uintCodec) + reg.RegisterKindEncoder(reflect.Uint64, uintCodec) + reg.RegisterKindEncoder(reflect.Float32, ValueEncoderFunc(floatEncodeValue)) + reg.RegisterKindEncoder(reflect.Float64, ValueEncoderFunc(floatEncodeValue)) + reg.RegisterKindEncoder(reflect.Array, ValueEncoderFunc(arrayEncodeValue)) + reg.RegisterKindEncoder(reflect.Map, mapEncoder) + reg.RegisterKindEncoder(reflect.Slice, &sliceCodec{}) + reg.RegisterKindEncoder(reflect.String, &stringCodec{}) + reg.RegisterKindEncoder(reflect.Struct, newStructCodec(mapEncoder)) + reg.RegisterKindEncoder(reflect.Ptr, &pointerCodec{}) + reg.RegisterInterfaceEncoder(tValueMarshaler, ValueEncoderFunc(valueMarshalerEncodeValue)) + reg.RegisterInterfaceEncoder(tMarshaler, ValueEncoderFunc(marshalerEncodeValue)) + reg.RegisterInterfaceEncoder(tProxy, ValueEncoderFunc(proxyEncodeValue)) +} + +// booleanEncodeValue is the ValueEncoderFunc for bool types. +func booleanEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Bool { return ValueEncoderError{Name: "BooleanEncodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val} } @@ -130,11 +112,8 @@ func fitsIn32Bits(i int64) bool { return math.MinInt32 <= i && i <= math.MaxInt32 } -// IntEncodeValue is the ValueEncoderFunc for int types. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) IntEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +// intEncodeValue is the ValueEncoderFunc for int types. +func intEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { switch val.Kind() { case reflect.Int8, reflect.Int16, reflect.Int32: return vw.WriteInt32(int32(val.Int())) @@ -159,36 +138,8 @@ func (dve DefaultValueEncoders) IntEncodeValue(ec EncodeContext, vw ValueWriter, } } -// UintEncodeValue is the ValueEncoderFunc for uint types. -// -// Deprecated: UintEncodeValue is not registered by default. Use UintCodec.EncodeValue instead. -func (dve DefaultValueEncoders) UintEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { - switch val.Kind() { - case reflect.Uint8, reflect.Uint16: - return vw.WriteInt32(int32(val.Uint())) - case reflect.Uint, reflect.Uint32, reflect.Uint64: - u64 := val.Uint() - if ec.MinSize && u64 <= math.MaxInt32 { - return vw.WriteInt32(int32(u64)) - } - if u64 > math.MaxInt64 { - return fmt.Errorf("%d overflows int64", u64) - } - return vw.WriteInt64(int64(u64)) - } - - return ValueEncoderError{ - Name: "UintEncodeValue", - Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, - Received: val, - } -} - -// FloatEncodeValue is the ValueEncoderFunc for float types. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) FloatEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// floatEncodeValue is the ValueEncoderFunc for float types. +func floatEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { switch val.Kind() { case reflect.Float32, reflect.Float64: return vw.WriteDouble(val.Float()) @@ -197,48 +148,24 @@ func (dve DefaultValueEncoders) FloatEncodeValue(_ EncodeContext, vw ValueWriter return ValueEncoderError{Name: "FloatEncodeValue", Kinds: []reflect.Kind{reflect.Float32, reflect.Float64}, Received: val} } -// StringEncodeValue is the ValueEncoderFunc for string types. -// -// Deprecated: StringEncodeValue is not registered by default. Use StringCodec.EncodeValue instead. -func (dve DefaultValueEncoders) StringEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { - if val.Kind() != reflect.String { - return ValueEncoderError{ - Name: "StringEncodeValue", - Kinds: []reflect.Kind{reflect.String}, - Received: val, - } - } - - return vw.WriteString(val.String()) -} - -// ObjectIDEncodeValue is the ValueEncoderFunc for ObjectID. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) ObjectIDEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// objectIDEncodeValue is the ValueEncoderFunc for ObjectID. +func objectIDEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tOID { return ValueEncoderError{Name: "ObjectIDEncodeValue", Types: []reflect.Type{tOID}, Received: val} } return vw.WriteObjectID(val.Interface().(ObjectID)) } -// Decimal128EncodeValue is the ValueEncoderFunc for Decimal128. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) Decimal128EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// decimal128EncodeValue is the ValueEncoderFunc for Decimal128. +func decimal128EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tDecimal { return ValueEncoderError{Name: "Decimal128EncodeValue", Types: []reflect.Type{tDecimal}, Received: val} } return vw.WriteDecimal128(val.Interface().(Decimal128)) } -// JSONNumberEncodeValue is the ValueEncoderFunc for json.Number. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +// jsonNumberEncodeValue is the ValueEncoderFunc for json.Number. +func jsonNumberEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tJSONNumber { return ValueEncoderError{Name: "JSONNumberEncodeValue", Types: []reflect.Type{tJSONNumber}, Received: val} } @@ -246,7 +173,7 @@ func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw Value // Attempt int first, then float64 if i64, err := jsnum.Int64(); err == nil { - return dve.IntEncodeValue(ec, vw, reflect.ValueOf(i64)) + return intEncodeValue(ec, vw, reflect.ValueOf(i64)) } f64, err := jsnum.Float64() @@ -254,14 +181,11 @@ func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw Value return err } - return dve.FloatEncodeValue(ec, vw, reflect.ValueOf(f64)) + return floatEncodeValue(ec, vw, reflect.ValueOf(f64)) } -// URLEncodeValue is the ValueEncoderFunc for url.URL. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) URLEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// urlEncodeValue is the ValueEncoderFunc for url.URL. +func urlEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tURL { return ValueEncoderError{Name: "URLEncodeValue", Types: []reflect.Type{tURL}, Received: val} } @@ -269,108 +193,8 @@ func (dve DefaultValueEncoders) URLEncodeValue(_ EncodeContext, vw ValueWriter, return vw.WriteString(u.String()) } -// TimeEncodeValue is the ValueEncoderFunc for time.TIme. -// -// Deprecated: TimeEncodeValue is not registered by default. Use TimeCodec.EncodeValue instead. -func (dve DefaultValueEncoders) TimeEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { - if !val.IsValid() || val.Type() != tTime { - return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val} - } - tt := val.Interface().(time.Time) - dt := NewDateTimeFromTime(tt) - return vw.WriteDateTime(int64(dt)) -} - -// ByteSliceEncodeValue is the ValueEncoderFunc for []byte. -// -// Deprecated: ByteSliceEncodeValue is not registered by default. Use ByteSliceCodec.EncodeValue instead. -func (dve DefaultValueEncoders) ByteSliceEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { - if !val.IsValid() || val.Type() != tByteSlice { - return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val} - } - if val.IsNil() { - return vw.WriteNull() - } - return vw.WriteBinary(val.Interface().([]byte)) -} - -// MapEncodeValue is the ValueEncoderFunc for map[string]* types. -// -// Deprecated: MapEncodeValue is not registered by default. Use MapCodec.EncodeValue instead. -func (dve DefaultValueEncoders) MapEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { - if !val.IsValid() || val.Kind() != reflect.Map || val.Type().Key().Kind() != reflect.String { - return ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} - } - - if val.IsNil() { - // If we have a nill map but we can't WriteNull, that means we're probably trying to encode - // to a TopLevel document. We can't currently tell if this is what actually happened, but if - // there's a deeper underlying problem, the error will also be returned from WriteDocument, - // so just continue. The operations on a map reflection value are valid, so we can call - // MapKeys within mapEncodeValue without a problem. - err := vw.WriteNull() - if err == nil { - return nil - } - } - - dw, err := vw.WriteDocument() - if err != nil { - return err - } - - return dve.mapEncodeValue(ec, dw, val, nil) -} - -// mapEncodeValue handles encoding of the values of a map. The collisionFn returns -// true if the provided key exists, this is mainly used for inline maps in the -// struct codec. -func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw DocumentWriter, val reflect.Value, collisionFn func(string) bool) error { - - elemType := val.Type().Elem() - encoder, err := ec.LookupEncoder(elemType) - if err != nil && elemType.Kind() != reflect.Interface { - return err - } - - keys := val.MapKeys() - for _, key := range keys { - if collisionFn != nil && collisionFn(key.String()) { - return fmt.Errorf("Key %s of inlined map conflicts with a struct field name", key) - } - - currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.MapIndex(key)) - if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { - return lookupErr - } - - vw, err := dw.WriteDocumentElement(key.String()) - if err != nil { - return err - } - - if errors.Is(lookupErr, errInvalidValue) { - err = vw.WriteNull() - if err != nil { - return err - } - continue - } - - err = currEncoder.EncodeValue(ec, vw, currVal) - if err != nil { - return err - } - } - - return dw.WriteDocumentEnd() -} - -// ArrayEncodeValue is the ValueEncoderFunc for array types. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +// arrayEncodeValue is the ValueEncoderFunc for array types. +func arrayEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Array { return ValueEncoderError{Name: "ArrayEncodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val} } @@ -414,76 +238,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw ValueWrite } for idx := 0; idx < val.Len(); idx++ { - currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) - if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { - return lookupErr - } - - vw, err := aw.WriteArrayElement() - if err != nil { - return err - } - - if errors.Is(lookupErr, errInvalidValue) { - err = vw.WriteNull() - if err != nil { - return err - } - continue - } - - err = currEncoder.EncodeValue(ec, vw, currVal) - if err != nil { - return err - } - } - return aw.WriteArrayEnd() -} - -// SliceEncodeValue is the ValueEncoderFunc for slice types. -// -// Deprecated: SliceEncodeValue is not registered by default. Use SliceCodec.EncodeValue instead. -func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { - if !val.IsValid() || val.Kind() != reflect.Slice { - return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} - } - - if val.IsNil() { - return vw.WriteNull() - } - - // If we have a []E we want to treat it as a document instead of as an array. - if val.Type().ConvertibleTo(tD) { - d := val.Convert(tD).Interface().(D) - - dw, err := vw.WriteDocument() - if err != nil { - return err - } - - for _, e := range d { - err = encodeElement(ec, dw, e) - if err != nil { - return err - } - } - - return dw.WriteDocumentEnd() - } - - aw, err := vw.WriteArray() - if err != nil { - return err - } - - elemType := val.Type().Elem() - encoder, err := ec.LookupEncoder(elemType) - if err != nil && elemType.Kind() != reflect.Interface { - return err - } - - for idx := 0; idx < val.Len(); idx++ { - currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) + currEncoder, currVal, lookupErr := lookupElementEncoder(ec, encoder, val.Index(idx)) if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -509,7 +264,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw ValueWrite return aw.WriteArrayEnd() } -func (dve DefaultValueEncoders) lookupElementEncoder(ec EncodeContext, origEncoder ValueEncoder, currVal reflect.Value) (ValueEncoder, reflect.Value, error) { +func lookupElementEncoder(ec EncodeContext, origEncoder ValueEncoder, currVal reflect.Value) (ValueEncoder, reflect.Value, error) { if origEncoder != nil || (currVal.Kind() != reflect.Interface) { return origEncoder, currVal, nil } @@ -522,30 +277,8 @@ func (dve DefaultValueEncoders) lookupElementEncoder(ec EncodeContext, origEncod return currEncoder, currVal, err } -// EmptyInterfaceEncodeValue is the ValueEncoderFunc for interface{}. -// -// Deprecated: EmptyInterfaceEncodeValue is not registered by default. Use EmptyInterfaceCodec.EncodeValue instead. -func (dve DefaultValueEncoders) EmptyInterfaceEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { - if !val.IsValid() || val.Type() != tEmpty { - return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val} - } - - if val.IsNil() { - return vw.WriteNull() - } - encoder, err := ec.LookupEncoder(val.Elem().Type()) - if err != nil { - return err - } - - return encoder.EncodeValue(ec, vw, val.Elem()) -} - -// ValueMarshalerEncodeValue is the ValueEncoderFunc for ValueMarshaler implementations. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// valueMarshalerEncodeValue is the ValueEncoderFunc for ValueMarshaler implementations. +func valueMarshalerEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { // Either val or a pointer to val must implement ValueMarshaler switch { case !val.IsValid(): @@ -572,11 +305,8 @@ func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(_ EncodeContext, vw Va return copyValueFromBytes(vw, t, data) } -// MarshalerEncodeValue is the ValueEncoderFunc for Marshaler implementations. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) MarshalerEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// marshalerEncodeValue is the ValueEncoderFunc for Marshaler implementations. +func marshalerEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { // Either val or a pointer to val must implement Marshaler switch { case !val.IsValid(): @@ -603,11 +333,8 @@ func (dve DefaultValueEncoders) MarshalerEncodeValue(_ EncodeContext, vw ValueWr return copyValueFromBytes(vw, TypeEmbeddedDocument, data) } -// ProxyEncodeValue is the ValueEncoderFunc for Proxy implementations. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) ProxyEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +// proxyEncodeValue is the ValueEncoderFunc for Proxy implementations. +func proxyEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { // Either val or a pointer to val must implement Proxy switch { case !val.IsValid(): @@ -650,11 +377,8 @@ func (dve DefaultValueEncoders) ProxyEncodeValue(ec EncodeContext, vw ValueWrite return encoder.EncodeValue(ec, vw, vv) } -// JavaScriptEncodeValue is the ValueEncoderFunc for the JavaScript type. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) JavaScriptEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// javaScriptEncodeValue is the ValueEncoderFunc for the JavaScript type. +func javaScriptEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tJavaScript { return ValueEncoderError{Name: "JavaScriptEncodeValue", Types: []reflect.Type{tJavaScript}, Received: val} } @@ -662,11 +386,8 @@ func (DefaultValueEncoders) JavaScriptEncodeValue(_ EncodeContext, vw ValueWrite return vw.WriteJavascript(val.String()) } -// SymbolEncodeValue is the ValueEncoderFunc for the Symbol type. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) SymbolEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// symbolEncodeValue is the ValueEncoderFunc for the Symbol type. +func symbolEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tSymbol { return ValueEncoderError{Name: "SymbolEncodeValue", Types: []reflect.Type{tSymbol}, Received: val} } @@ -674,11 +395,8 @@ func (DefaultValueEncoders) SymbolEncodeValue(_ EncodeContext, vw ValueWriter, v return vw.WriteSymbol(val.String()) } -// BinaryEncodeValue is the ValueEncoderFunc for Binary. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) BinaryEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// binaryEncodeValue is the ValueEncoderFunc for Binary. +func binaryEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tBinary { return ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val} } @@ -687,11 +405,8 @@ func (DefaultValueEncoders) BinaryEncodeValue(_ EncodeContext, vw ValueWriter, v return vw.WriteBinaryWithSubtype(b.Data, b.Subtype) } -// UndefinedEncodeValue is the ValueEncoderFunc for Undefined. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) UndefinedEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// undefinedEncodeValue is the ValueEncoderFunc for Undefined. +func undefinedEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tUndefined { return ValueEncoderError{Name: "UndefinedEncodeValue", Types: []reflect.Type{tUndefined}, Received: val} } @@ -699,11 +414,8 @@ func (DefaultValueEncoders) UndefinedEncodeValue(_ EncodeContext, vw ValueWriter return vw.WriteUndefined() } -// DateTimeEncodeValue is the ValueEncoderFunc for DateTime. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) DateTimeEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// dateTimeEncodeValue is the ValueEncoderFunc for DateTime. +func dateTimeEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tDateTime { return ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: val} } @@ -711,11 +423,8 @@ func (DefaultValueEncoders) DateTimeEncodeValue(_ EncodeContext, vw ValueWriter, return vw.WriteDateTime(val.Int()) } -// NullEncodeValue is the ValueEncoderFunc for Null. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) NullEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// nullEncodeValue is the ValueEncoderFunc for Null. +func nullEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tNull { return ValueEncoderError{Name: "NullEncodeValue", Types: []reflect.Type{tNull}, Received: val} } @@ -723,11 +432,8 @@ func (DefaultValueEncoders) NullEncodeValue(_ EncodeContext, vw ValueWriter, val return vw.WriteNull() } -// RegexEncodeValue is the ValueEncoderFunc for Regex. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) RegexEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// regexEncodeValue is the ValueEncoderFunc for Regex. +func regexEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tRegex { return ValueEncoderError{Name: "RegexEncodeValue", Types: []reflect.Type{tRegex}, Received: val} } @@ -737,11 +443,8 @@ func (DefaultValueEncoders) RegexEncodeValue(_ EncodeContext, vw ValueWriter, va return vw.WriteRegex(regex.Pattern, regex.Options) } -// DBPointerEncodeValue is the ValueEncoderFunc for DBPointer. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) DBPointerEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// dbPointerEncodeValue is the ValueEncoderFunc for DBPointer. +func dbPointerEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tDBPointer { return ValueEncoderError{Name: "DBPointerEncodeValue", Types: []reflect.Type{tDBPointer}, Received: val} } @@ -751,11 +454,8 @@ func (DefaultValueEncoders) DBPointerEncodeValue(_ EncodeContext, vw ValueWriter return vw.WriteDBPointer(dbp.DB, dbp.Pointer) } -// TimestampEncodeValue is the ValueEncoderFunc for Timestamp. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) TimestampEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// timestampEncodeValue is the ValueEncoderFunc for Timestamp. +func timestampEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tTimestamp { return ValueEncoderError{Name: "TimestampEncodeValue", Types: []reflect.Type{tTimestamp}, Received: val} } @@ -765,11 +465,8 @@ func (DefaultValueEncoders) TimestampEncodeValue(_ EncodeContext, vw ValueWriter return vw.WriteTimestamp(ts.T, ts.I) } -// MinKeyEncodeValue is the ValueEncoderFunc for MinKey. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) MinKeyEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// minKeyEncodeValue is the ValueEncoderFunc for MinKey. +func minKeyEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tMinKey { return ValueEncoderError{Name: "MinKeyEncodeValue", Types: []reflect.Type{tMinKey}, Received: val} } @@ -777,11 +474,8 @@ func (DefaultValueEncoders) MinKeyEncodeValue(_ EncodeContext, vw ValueWriter, v return vw.WriteMinKey() } -// MaxKeyEncodeValue is the ValueEncoderFunc for MaxKey. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) MaxKeyEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// maxKeyEncodeValue is the ValueEncoderFunc for MaxKey. +func maxKeyEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tMaxKey { return ValueEncoderError{Name: "MaxKeyEncodeValue", Types: []reflect.Type{tMaxKey}, Received: val} } @@ -789,11 +483,8 @@ func (DefaultValueEncoders) MaxKeyEncodeValue(_ EncodeContext, vw ValueWriter, v return vw.WriteMaxKey() } -// CoreDocumentEncodeValue is the ValueEncoderFunc for bsoncore.Document. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (DefaultValueEncoders) CoreDocumentEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// coreDocumentEncodeValue is the ValueEncoderFunc for bsoncore.Document. +func coreDocumentEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tCoreDocument { return ValueEncoderError{Name: "CoreDocumentEncodeValue", Types: []reflect.Type{tCoreDocument}, Received: val} } @@ -803,11 +494,8 @@ func (DefaultValueEncoders) CoreDocumentEncodeValue(_ EncodeContext, vw ValueWri return copyDocumentFromBytes(vw, cdoc) } -// CodeWithScopeEncodeValue is the ValueEncoderFunc for CodeWithScope. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with all default -// value encoders registered. -func (dve DefaultValueEncoders) CodeWithScopeEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +// codeWithScopeEncodeValue is the ValueEncoderFunc for CodeWithScope. +func codeWithScopeEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tCodeWithScope { return ValueEncoderError{Name: "CodeWithScopeEncodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val} } diff --git a/bson/default_value_encoders_test.go b/bson/default_value_encoders_test.go index 481c6cb1a1..fb16750007 100644 --- a/bson/default_value_encoders_test.go +++ b/bson/default_value_encoders_test.go @@ -35,7 +35,6 @@ func (ms myStruct) Foo() int { } func TestDefaultValueEncoders(t *testing.T) { - var dve DefaultValueEncoders var wrong = func(string, string) string { return "wrong" } type mybool bool @@ -80,7 +79,7 @@ func TestDefaultValueEncoders(t *testing.T) { }{ { "BooleanEncodeValue", - ValueEncoderFunc(dve.BooleanEncodeValue), + ValueEncoderFunc(booleanEncodeValue), []subtest{ { "wrong type", @@ -96,7 +95,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "IntEncodeValue", - ValueEncoderFunc(dve.IntEncodeValue), + ValueEncoderFunc(intEncodeValue), []subtest{ { "wrong type", @@ -136,7 +135,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "UintEncodeValue", - defaultUIntCodec, + &uintCodec{}, []subtest{ { "wrong type", @@ -177,7 +176,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "FloatEncodeValue", - ValueEncoderFunc(dve.FloatEncodeValue), + ValueEncoderFunc(floatEncodeValue), []subtest{ { "wrong type", @@ -199,7 +198,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "TimeEncodeValue", - defaultTimeCodec, + &timeCodec{}, []subtest{ { "wrong type", @@ -214,7 +213,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "MapEncodeValue", - defaultMapCodec, + &mapCodec{}, []subtest{ { "wrong kind", @@ -235,7 +234,7 @@ func TestDefaultValueEncoders(t *testing.T) { { "Lookup Error", map[string]int{"foo": 1}, - &EncodeContext{Registry: newTestRegistryBuilder().Build()}, + &EncodeContext{Registry: newTestRegistry()}, &valueReaderWriter{}, writeDocument, fmt.Errorf("no encoder found for int"), @@ -259,7 +258,7 @@ func TestDefaultValueEncoders(t *testing.T) { { "empty map/success", map[string]interface{}{}, - &EncodeContext{Registry: newTestRegistryBuilder().Build()}, + &EncodeContext{Registry: newTestRegistry()}, &valueReaderWriter{}, writeDocumentEnd, nil, @@ -294,7 +293,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "ArrayEncodeValue", - ValueEncoderFunc(dve.ArrayEncodeValue), + ValueEncoderFunc(arrayEncodeValue), []subtest{ { "wrong kind", @@ -315,7 +314,7 @@ func TestDefaultValueEncoders(t *testing.T) { { "Lookup Error", [1]int{1}, - &EncodeContext{Registry: newTestRegistryBuilder().Build()}, + &EncodeContext{Registry: newTestRegistry()}, &valueReaderWriter{}, writeArray, fmt.Errorf("no encoder found for int"), @@ -372,7 +371,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "SliceEncodeValue", - defaultSliceCodec, + &sliceCodec{}, []subtest{ { "wrong kind", @@ -393,7 +392,7 @@ func TestDefaultValueEncoders(t *testing.T) { { "Lookup Error", []int{1}, - &EncodeContext{Registry: newTestRegistryBuilder().Build()}, + &EncodeContext{Registry: newTestRegistry()}, &valueReaderWriter{}, writeArray, fmt.Errorf("no encoder found for int"), @@ -433,7 +432,7 @@ func TestDefaultValueEncoders(t *testing.T) { { "empty slice/success", []interface{}{}, - &EncodeContext{Registry: newTestRegistryBuilder().Build()}, + &EncodeContext{Registry: newTestRegistry()}, &valueReaderWriter{}, writeArrayEnd, nil, @@ -458,7 +457,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "ObjectIDEncodeValue", - ValueEncoderFunc(dve.ObjectIDEncodeValue), + ValueEncoderFunc(objectIDEncodeValue), []subtest{ { "wrong type", @@ -477,7 +476,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "Decimal128EncodeValue", - ValueEncoderFunc(dve.Decimal128EncodeValue), + ValueEncoderFunc(decimal128EncodeValue), []subtest{ { "wrong type", @@ -492,7 +491,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "JSONNumberEncodeValue", - ValueEncoderFunc(dve.JSONNumberEncodeValue), + ValueEncoderFunc(jsonNumberEncodeValue), []subtest{ { "wrong type", @@ -521,7 +520,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "URLEncodeValue", - ValueEncoderFunc(dve.URLEncodeValue), + ValueEncoderFunc(urlEncodeValue), []subtest{ { "wrong type", @@ -536,7 +535,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "ByteSliceEncodeValue", - defaultByteSliceCodec, + &byteSliceCodec{}, []subtest{ { "wrong type", @@ -552,7 +551,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "EmptyInterfaceEncodeValue", - defaultEmptyInterfaceCodec, + &emptyInterfaceCodec{}, []subtest{ { "wrong type", @@ -566,7 +565,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "ValueMarshalerEncodeValue", - ValueEncoderFunc(dve.ValueMarshalerEncodeValue), + ValueEncoderFunc(valueMarshalerEncodeValue), []subtest{ { "wrong type", @@ -644,7 +643,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "MarshalerEncodeValue", - ValueEncoderFunc(dve.MarshalerEncodeValue), + ValueEncoderFunc(marshalerEncodeValue), []subtest{ { "wrong type", @@ -706,7 +705,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "ProxyEncodeValue", - ValueEncoderFunc(dve.ProxyEncodeValue), + ValueEncoderFunc(proxyEncodeValue), []subtest{ { "wrong type", @@ -776,7 +775,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "PointerCodec.EncodeValue", - NewPointerCodec(), + &pointerCodec{}, []subtest{ { "nil", @@ -814,7 +813,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "pointer implementation addressable interface", - NewPointerCodec(), + &pointerCodec{}, []subtest{ { "ValueMarshaler", @@ -844,7 +843,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "JavaScriptEncodeValue", - ValueEncoderFunc(dve.JavaScriptEncodeValue), + ValueEncoderFunc(javaScriptEncodeValue), []subtest{ { "wrong type", @@ -859,7 +858,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "SymbolEncodeValue", - ValueEncoderFunc(dve.SymbolEncodeValue), + ValueEncoderFunc(symbolEncodeValue), []subtest{ { "wrong type", @@ -874,7 +873,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "BinaryEncodeValue", - ValueEncoderFunc(dve.BinaryEncodeValue), + ValueEncoderFunc(binaryEncodeValue), []subtest{ { "wrong type", @@ -889,7 +888,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "UndefinedEncodeValue", - ValueEncoderFunc(dve.UndefinedEncodeValue), + ValueEncoderFunc(undefinedEncodeValue), []subtest{ { "wrong type", @@ -904,7 +903,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "DateTimeEncodeValue", - ValueEncoderFunc(dve.DateTimeEncodeValue), + ValueEncoderFunc(dateTimeEncodeValue), []subtest{ { "wrong type", @@ -919,7 +918,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "NullEncodeValue", - ValueEncoderFunc(dve.NullEncodeValue), + ValueEncoderFunc(nullEncodeValue), []subtest{ { "wrong type", @@ -934,7 +933,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "RegexEncodeValue", - ValueEncoderFunc(dve.RegexEncodeValue), + ValueEncoderFunc(regexEncodeValue), []subtest{ { "wrong type", @@ -949,7 +948,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "DBPointerEncodeValue", - ValueEncoderFunc(dve.DBPointerEncodeValue), + ValueEncoderFunc(dbPointerEncodeValue), []subtest{ { "wrong type", @@ -971,7 +970,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "TimestampEncodeValue", - ValueEncoderFunc(dve.TimestampEncodeValue), + ValueEncoderFunc(timestampEncodeValue), []subtest{ { "wrong type", @@ -986,7 +985,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "MinKeyEncodeValue", - ValueEncoderFunc(dve.MinKeyEncodeValue), + ValueEncoderFunc(minKeyEncodeValue), []subtest{ { "wrong type", @@ -1001,7 +1000,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "MaxKeyEncodeValue", - ValueEncoderFunc(dve.MaxKeyEncodeValue), + ValueEncoderFunc(maxKeyEncodeValue), []subtest{ { "wrong type", @@ -1016,7 +1015,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "CoreDocumentEncodeValue", - ValueEncoderFunc(dve.CoreDocumentEncodeValue), + ValueEncoderFunc(coreDocumentEncodeValue), []subtest{ { "wrong type", @@ -1074,7 +1073,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "StructEncodeValue", - defaultTestStructCodec, + newStructCodec(&mapCodec{}), []subtest{ { "interface value", @@ -1096,7 +1095,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "CodeWithScopeEncodeValue", - ValueEncoderFunc(dve.CodeWithScopeEncodeValue), + ValueEncoderFunc(codeWithScopeEncodeValue), []subtest{ { "wrong type", @@ -1131,7 +1130,7 @@ func TestDefaultValueEncoders(t *testing.T) { }, { "CoreArrayEncodeValue", - defaultArrayCodec, + &arrayCodec{}, []subtest{ { "wrong type", @@ -1832,7 +1831,7 @@ func TestDefaultValueEncoders(t *testing.T) { t.Run("EmptyInterfaceEncodeValue/nil", func(t *testing.T) { val := reflect.New(tEmpty).Elem() llvrw := new(valueReaderWriter) - err := dve.EmptyInterfaceEncodeValue(EncodeContext{Registry: newTestRegistryBuilder().Build()}, llvrw, val) + err := (&emptyInterfaceCodec{}).EncodeValue(EncodeContext{Registry: newTestRegistry()}, llvrw, val) noerr(t, err) if llvrw.invoked != writeNull { t.Errorf("Incorrect method called. got %v; want %v", llvrw.invoked, writeNull) @@ -1843,7 +1842,7 @@ func TestDefaultValueEncoders(t *testing.T) { val := reflect.New(tEmpty).Elem() val.Set(reflect.ValueOf(int64(1234567890))) llvrw := new(valueReaderWriter) - got := dve.EmptyInterfaceEncodeValue(EncodeContext{Registry: newTestRegistryBuilder().Build()}, llvrw, val) + got := (&emptyInterfaceCodec{}).EncodeValue(EncodeContext{Registry: newTestRegistry()}, llvrw, val) 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/empty_interface_codec.go b/bson/empty_interface_codec.go index 56468e3068..49b3b98d74 100644 --- a/bson/empty_interface_codec.go +++ b/bson/empty_interface_codec.go @@ -8,47 +8,24 @@ package bson import ( "reflect" - - "go.mongodb.org/mongo-driver/bson/bsonoptions" ) -// EmptyInterfaceCodec is the Codec used for interface{} values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// EmptyInterfaceCodec registered. -type EmptyInterfaceCodec struct { - // DecodeBinaryAsSlice causes DecodeValue to unmarshal BSON binary field values that are the +// emptyInterfaceCodec is the Codec used for interface{} values. +type emptyInterfaceCodec struct { + // decodeBinaryAsSlice causes DecodeValue to unmarshal BSON binary field values that are the // "Generic" or "Old" BSON binary subtype as a Go byte slice instead of a Binary. - // - // Deprecated: Use bson.Decoder.BinaryAsSlice instead. - DecodeBinaryAsSlice bool + decodeBinaryAsSlice bool } var ( - defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec() - - // Assert that defaultEmptyInterfaceCodec satisfies the typeDecoder interface, which allows it + // Assert that emptyInterfaceCodec satisfies the typeDecoder interface, which allows it // to be used by collection type decoders (e.g. map, slice, etc) to set individual values in a // collection. - _ typeDecoder = defaultEmptyInterfaceCodec + _ typeDecoder = (*emptyInterfaceCodec)(nil) ) -// NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// EmptyInterfaceCodec registered. -func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec { - interfaceOpt := bsonoptions.MergeEmptyInterfaceCodecOptions(opts...) - - codec := EmptyInterfaceCodec{} - if interfaceOpt.DecodeBinaryAsSlice != nil { - codec.DecodeBinaryAsSlice = *interfaceOpt.DecodeBinaryAsSlice - } - return &codec -} - // EncodeValue is the ValueEncoderFunc for interface{}. -func (eic EmptyInterfaceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +func (eic *emptyInterfaceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tEmpty { return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val} } @@ -64,7 +41,7 @@ func (eic EmptyInterfaceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val return encoder.EncodeValue(ec, vw, val.Elem()) } -func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, valueType Type) (reflect.Type, error) { +func (eic *emptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, valueType Type) (reflect.Type, error) { isDocument := valueType == Type(0) || valueType == TypeEmbeddedDocument if isDocument { if dc.defaultDocumentType != nil { @@ -105,7 +82,7 @@ func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, val return nil, err } -func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func (eic *emptyInterfaceCodec) decodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tEmpty { return emptyValue, ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.Zero(t)} } @@ -130,7 +107,7 @@ func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr ValueReader, t re return emptyValue, err } - if (eic.DecodeBinaryAsSlice || dc.binaryAsSlice) && rtype == tBinary { + if (eic.decodeBinaryAsSlice || dc.binaryAsSlice) && rtype == tBinary { binElem := elem.Interface().(Binary) if binElem.Subtype == TypeBinaryGeneric || binElem.Subtype == TypeBinaryBinaryOld { elem = reflect.ValueOf(binElem.Data) @@ -141,7 +118,7 @@ func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr ValueReader, t re } // DecodeValue is the ValueDecoderFunc for interface{}. -func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +func (eic *emptyInterfaceCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tEmpty { return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val} } diff --git a/bson/map_codec.go b/bson/map_codec.go index 9592957db4..766a904b59 100644 --- a/bson/map_codec.go +++ b/bson/map_codec.go @@ -12,34 +12,21 @@ import ( "fmt" "reflect" "strconv" - - "go.mongodb.org/mongo-driver/bson/bsonoptions" ) -var defaultMapCodec = NewMapCodec() - -// MapCodec is the Codec used for map values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// MapCodec registered. -type MapCodec struct { +// mapCodec is the Codec used for map values. +type mapCodec struct { // DecodeZerosMap causes DecodeValue to delete any existing values from Go maps in the destination // value passed to Decode before unmarshaling BSON documents into them. - // - // Deprecated: Use bson.Decoder.ZeroMaps instead. - DecodeZerosMap bool + decodeZerosMap bool // EncodeNilAsEmpty causes EncodeValue to marshal nil Go maps as empty BSON documents instead of // BSON null. - // - // Deprecated: Use bson.Encoder.NilMapAsEmpty instead. - EncodeNilAsEmpty bool + encodeNilAsEmpty bool // EncodeKeysWithStringer causes the Encoder to convert Go map keys to BSON document field name // strings using fmt.Sprintf() instead of the default string conversion logic. - // - // Deprecated: Use bson.Encoder.StringifyMapKeysWithFmt instead. - EncodeKeysWithStringer bool + encodeKeysWithStringer bool } // KeyMarshaler is the interface implemented by an object that can marshal itself into a string key. @@ -58,33 +45,13 @@ type KeyUnmarshaler interface { UnmarshalKey(key string) error } -// NewMapCodec returns a MapCodec with options opts. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// MapCodec registered. -func NewMapCodec(opts ...*bsonoptions.MapCodecOptions) *MapCodec { - mapOpt := bsonoptions.MergeMapCodecOptions(opts...) - - codec := MapCodec{} - if mapOpt.DecodeZerosMap != nil { - codec.DecodeZerosMap = *mapOpt.DecodeZerosMap - } - if mapOpt.EncodeNilAsEmpty != nil { - codec.EncodeNilAsEmpty = *mapOpt.EncodeNilAsEmpty - } - if mapOpt.EncodeKeysWithStringer != nil { - codec.EncodeKeysWithStringer = *mapOpt.EncodeKeysWithStringer - } - return &codec -} - // EncodeValue is the ValueEncoder for map[*]* types. -func (mc *MapCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +func (mc *mapCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Map { return ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} } - if val.IsNil() && !mc.EncodeNilAsEmpty && !ec.nilMapAsEmpty { + if val.IsNil() && !mc.encodeNilAsEmpty && !ec.nilMapAsEmpty { // If we have a nil map but we can't WriteNull, that means we're probably trying to encode // to a TopLevel document. We can't currently tell if this is what actually happened, but if // there's a deeper underlying problem, the error will also be returned from WriteDocument, @@ -101,13 +68,17 @@ func (mc *MapCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Va return err } - return mc.mapEncodeValue(ec, dw, val, nil) + err = mc.encodeMapElements(ec, dw, val, nil) + if err != nil { + return err + } + return dw.WriteDocumentEnd() } -// mapEncodeValue handles encoding of the values of a map. The collisionFn returns +// encodeMapElements handles encoding of the values of a map. The collisionFn returns // true if the provided key exists, this is mainly used for inline maps in the // struct codec. -func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw DocumentWriter, val reflect.Value, collisionFn func(string) bool) error { +func (mc *mapCodec) encodeMapElements(ec EncodeContext, dw DocumentWriter, val reflect.Value, collisionFn func(string) bool) error { elemType := val.Type().Elem() encoder, err := ec.LookupEncoder(elemType) @@ -126,7 +97,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw DocumentWriter, val refl return fmt.Errorf("Key %s of inlined map conflicts with a struct field name", key) } - currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.MapIndex(key)) + currEncoder, currVal, lookupErr := lookupElementEncoder(ec, encoder, val.MapIndex(key)) if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -150,11 +121,11 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw DocumentWriter, val refl } } - return dw.WriteDocumentEnd() + return nil } // DecodeValue is the ValueDecoder for map[string/decimal]* types. -func (mc *MapCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +func (mc *mapCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if val.Kind() != reflect.Map || (!val.CanSet() && val.IsNil()) { return ValueDecoderError{Name: "MapDecodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} } @@ -180,7 +151,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Va val.Set(reflect.MakeMap(val.Type())) } - if val.Len() > 0 && (mc.DecodeZerosMap || dc.zeroMaps) { + if val.Len() > 0 && (mc.decodeZerosMap || dc.zeroMaps) { clearMap(val) } @@ -228,8 +199,8 @@ func clearMap(m reflect.Value) { } } -func (mc *MapCodec) encodeKey(val reflect.Value, encodeKeysWithStringer bool) (string, error) { - if mc.EncodeKeysWithStringer || encodeKeysWithStringer { +func (mc *mapCodec) encodeKey(val reflect.Value, encodeKeysWithStringer bool) (string, error) { + if mc.encodeKeysWithStringer || encodeKeysWithStringer { return fmt.Sprint(val), nil } @@ -274,12 +245,12 @@ func (mc *MapCodec) encodeKey(val reflect.Value, encodeKeysWithStringer bool) (s var keyUnmarshalerType = reflect.TypeOf((*KeyUnmarshaler)(nil)).Elem() var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() -func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, error) { +func (mc *mapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, error) { keyVal := reflect.ValueOf(key) var err error switch { // First, if EncodeKeysWithStringer is not enabled, try to decode withKeyUnmarshaler - case !mc.EncodeKeysWithStringer && reflect.PtrTo(keyType).Implements(keyUnmarshalerType): + case !mc.encodeKeysWithStringer && reflect.PtrTo(keyType).Implements(keyUnmarshalerType): keyVal = reflect.New(keyType) v := keyVal.Interface().(KeyUnmarshaler) err = v.UnmarshalKey(key) @@ -309,7 +280,7 @@ func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, } keyVal = reflect.ValueOf(n).Convert(keyType) case reflect.Float32, reflect.Float64: - if mc.EncodeKeysWithStringer { + if mc.encodeKeysWithStringer { parsed, err := strconv.ParseFloat(key, 64) if err != nil { return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %w", keyType.Kind(), err) diff --git a/bson/mgocompat/bson_test.go b/bson/mgocompat/bson_test.go index 6651509983..b013986db9 100644 --- a/bson/mgocompat/bson_test.go +++ b/bson/mgocompat/bson_test.go @@ -25,6 +25,10 @@ import ( "go.mongodb.org/mongo-driver/internal/assert" ) +var ( + errSetZero = errors.New("set to zero") +) + // Wrap up the document elements contained in data, prepending the int32 // length of the data, and appending the '\x00' value closing the document. func wrapInDoc(data string) string { @@ -471,7 +475,7 @@ func (t *prefixPtr) GetBSON() (interface{}, error) { func (t *prefixPtr) SetBSON(raw bson.RawValue) error { var s string if raw.Type == 0x0A { - return ErrSetZero + return errSetZero } rval := reflect.ValueOf(&s).Elem() decoder, err := Registry.LookupDecoder(rval.Type()) @@ -498,7 +502,7 @@ func (t prefixVal) GetBSON() (interface{}, error) { func (t *prefixVal) SetBSON(raw bson.RawValue) error { var s string if raw.Type == 0x0A { - return ErrSetZero + return errSetZero } rval := reflect.ValueOf(&s).Elem() decoder, err := Registry.LookupDecoder(rval.Type()) @@ -1026,7 +1030,7 @@ func TestDMap(t *testing.T) { } func TestUnmarshalSetterErrSetZero(t *testing.T) { - setterResult["foo"] = ErrSetZero + setterResult["foo"] = errSetZero defer delete(setterResult, "field") buf := new(bytes.Buffer) diff --git a/bson/mgocompat/registry.go b/bson/mgocompat/registry.go index 7024ab9fdc..7ffb90b22e 100644 --- a/bson/mgocompat/registry.go +++ b/bson/mgocompat/registry.go @@ -7,106 +7,12 @@ package mgocompat import ( - "errors" - "reflect" - "time" - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/bsonoptions" -) - -var ( - // ErrSetZero may be returned from a SetBSON method to have the value set to its respective zero value. - ErrSetZero = errors.New("set to zero") - - tInt = reflect.TypeOf(int(0)) - tTime = reflect.TypeOf(time.Time{}) - tM = reflect.TypeOf(bson.M{}) - tInterfaceSlice = reflect.TypeOf([]interface{}{}) - tByteSlice = reflect.TypeOf([]byte{}) - tEmpty = reflect.TypeOf((*interface{})(nil)).Elem() - tGetter = reflect.TypeOf((*Getter)(nil)).Elem() - tSetter = reflect.TypeOf((*Setter)(nil)).Elem() ) // Registry is the mgo compatible bson.Registry. It contains the default and // primitive codecs with mgo compatible options. -var Registry = NewRegistryBuilder().Build() +var Registry = bson.NewMgoRegistry() // RespectNilValuesRegistry is the bson.Registry compatible with mgo withSetRespectNilValues set to true. -var RespectNilValuesRegistry = NewRespectNilValuesRegistryBuilder().Build() - -// NewRegistryBuilder creates a new bson.RegistryBuilder configured with the default encoders and -// decoders from the bson.DefaultValueEncoders and bson.DefaultValueDecoders types and the -// PrimitiveCodecs type in this package. -func NewRegistryBuilder() *bson.RegistryBuilder { - rb := bson.NewRegistryBuilder() - bson.DefaultValueEncoders{}.RegisterDefaultEncoders(rb) - bson.DefaultValueDecoders{}.RegisterDefaultDecoders(rb) - bson.PrimitiveCodecs{}.RegisterPrimitiveCodecs(rb) - - structcodec, _ := bson.NewStructCodec(bson.DefaultStructTagParser, - bsonoptions.StructCodec(). - SetDecodeZeroStruct(true). - SetEncodeOmitDefaultStruct(true). - SetOverwriteDuplicatedInlinedFields(false). - SetAllowUnexportedFields(true)) - emptyInterCodec := bson.NewEmptyInterfaceCodec( - bsonoptions.EmptyInterfaceCodec(). - SetDecodeBinaryAsSlice(true)) - mapCodec := bson.NewMapCodec( - bsonoptions.MapCodec(). - SetDecodeZerosMap(true). - SetEncodeNilAsEmpty(true). - SetEncodeKeysWithStringer(true)) - uintcodec := bson.NewUIntCodec(bsonoptions.UIntCodec().SetEncodeToMinSize(true)) - - rb.RegisterTypeDecoder(tEmpty, emptyInterCodec). - RegisterDefaultDecoder(reflect.String, bson.NewStringCodec(bsonoptions.StringCodec().SetDecodeObjectIDAsHex(false))). - RegisterDefaultDecoder(reflect.Struct, structcodec). - RegisterDefaultDecoder(reflect.Map, mapCodec). - RegisterTypeEncoder(tByteSlice, bson.NewByteSliceCodec(bsonoptions.ByteSliceCodec().SetEncodeNilAsEmpty(true))). - RegisterDefaultEncoder(reflect.Struct, structcodec). - RegisterDefaultEncoder(reflect.Slice, bson.NewSliceCodec(bsonoptions.SliceCodec().SetEncodeNilAsEmpty(true))). - RegisterDefaultEncoder(reflect.Map, mapCodec). - RegisterDefaultEncoder(reflect.Uint, uintcodec). - RegisterDefaultEncoder(reflect.Uint8, uintcodec). - RegisterDefaultEncoder(reflect.Uint16, uintcodec). - RegisterDefaultEncoder(reflect.Uint32, uintcodec). - RegisterDefaultEncoder(reflect.Uint64, uintcodec). - RegisterTypeMapEntry(bson.TypeInt32, tInt). - RegisterTypeMapEntry(bson.TypeDateTime, tTime). - RegisterTypeMapEntry(bson.TypeArray, tInterfaceSlice). - RegisterTypeMapEntry(bson.Type(0), tM). - RegisterTypeMapEntry(bson.TypeEmbeddedDocument, tM). - RegisterHookEncoder(tGetter, bson.ValueEncoderFunc(GetterEncodeValue)). - RegisterHookDecoder(tSetter, bson.ValueDecoderFunc(SetterDecodeValue)) - - return rb -} - -// NewRespectNilValuesRegistryBuilder creates a new bson.RegistryBuilder configured to behave like mgo/bson -// with RespectNilValues set to true. -func NewRespectNilValuesRegistryBuilder() *bson.RegistryBuilder { - rb := NewRegistryBuilder() - - structcodec, _ := bson.NewStructCodec(bson.DefaultStructTagParser, - bsonoptions.StructCodec(). - SetDecodeZeroStruct(true). - SetEncodeOmitDefaultStruct(true). - SetOverwriteDuplicatedInlinedFields(false). - SetAllowUnexportedFields(true)) - mapCodec := bson.NewMapCodec( - bsonoptions.MapCodec(). - SetDecodeZerosMap(true). - SetEncodeNilAsEmpty(false)) - - rb.RegisterDefaultDecoder(reflect.Struct, structcodec). - RegisterDefaultDecoder(reflect.Map, mapCodec). - RegisterTypeEncoder(tByteSlice, bson.NewByteSliceCodec(bsonoptions.ByteSliceCodec().SetEncodeNilAsEmpty(false))). - RegisterDefaultEncoder(reflect.Struct, structcodec). - RegisterDefaultEncoder(reflect.Slice, bson.NewSliceCodec(bsonoptions.SliceCodec().SetEncodeNilAsEmpty(false))). - RegisterDefaultEncoder(reflect.Map, mapCodec) - - return rb -} +var RespectNilValuesRegistry = bson.NewRespectNilValuesMgoRegistry() diff --git a/bson/mgocompat/setter_getter.go b/bson/mgocompat/setter_getter.go deleted file mode 100644 index fc620fbba8..0000000000 --- a/bson/mgocompat/setter_getter.go +++ /dev/null @@ -1,131 +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 mgocompat - -import ( - "errors" - "reflect" - - "go.mongodb.org/mongo-driver/bson" -) - -// Setter interface: a value implementing the bson.Setter interface will receive the BSON -// value via the SetBSON method during unmarshaling, and the object -// itself will not be changed as usual. -// -// If setting the value works, the method should return nil or alternatively -// mgocompat.ErrSetZero to set the respective field to its zero value (nil for -// pointer types). If SetBSON returns a non-nil error, the unmarshalling -// procedure will stop and error out with the provided value. -// -// This interface is generally useful in pointer receivers, since the method -// will want to change the receiver. A type field that implements the Setter -// interface doesn't have to be a pointer, though. -// -// For example: -// -// type MyString string -// -// func (s *MyString) SetBSON(raw bson.RawValue) error { -// return raw.Unmarshal(s) -// } -type Setter interface { - SetBSON(raw bson.RawValue) error -} - -// Getter interface: a value implementing the bson.Getter interface will have its GetBSON -// method called when the given value has to be marshalled, and the result -// of this method will be marshaled in place of the actual object. -// -// If GetBSON returns return a non-nil error, the marshalling procedure -// will stop and error out with the provided value. -type Getter interface { - GetBSON() (interface{}, error) -} - -// SetterDecodeValue is the ValueDecoderFunc for Setter types. -func SetterDecodeValue(_ bson.DecodeContext, vr bson.ValueReader, val reflect.Value) error { - if !val.IsValid() || (!val.Type().Implements(tSetter) && !reflect.PtrTo(val.Type()).Implements(tSetter)) { - return bson.ValueDecoderError{Name: "SetterDecodeValue", Types: []reflect.Type{tSetter}, Received: val} - } - - if val.Kind() == reflect.Ptr && val.IsNil() { - if !val.CanSet() { - return bson.ValueDecoderError{Name: "SetterDecodeValue", Types: []reflect.Type{tSetter}, Received: val} - } - val.Set(reflect.New(val.Type().Elem())) - } - - if !val.Type().Implements(tSetter) { - if !val.CanAddr() { - return bson.ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tSetter}, Received: val} - } - val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. - } - - t, src, err := bson.CopyValueToBytes(vr) - if err != nil { - return err - } - - m, ok := val.Interface().(Setter) - if !ok { - return bson.ValueDecoderError{Name: "SetterDecodeValue", Types: []reflect.Type{tSetter}, Received: val} - } - if err := m.SetBSON(bson.RawValue{Type: t, Value: src}); err != nil { - if !errors.Is(err, ErrSetZero) { - return err - } - val.Set(reflect.Zero(val.Type())) - } - return nil -} - -// GetterEncodeValue is the ValueEncoderFunc for Getter types. -func GetterEncodeValue(ec bson.EncodeContext, vw bson.ValueWriter, val reflect.Value) error { - // Either val or a pointer to val must implement Getter - switch { - case !val.IsValid(): - return bson.ValueEncoderError{Name: "GetterEncodeValue", Types: []reflect.Type{tGetter}, Received: val} - case val.Type().Implements(tGetter): - // If Getter is implemented on a concrete type, make sure that val isn't a nil pointer - if isImplementationNil(val, tGetter) { - return vw.WriteNull() - } - case reflect.PtrTo(val.Type()).Implements(tGetter) && val.CanAddr(): - val = val.Addr() - default: - return bson.ValueEncoderError{Name: "GetterEncodeValue", Types: []reflect.Type{tGetter}, Received: val} - } - - m, ok := val.Interface().(Getter) - if !ok { - return vw.WriteNull() - } - x, err := m.GetBSON() - if err != nil { - return err - } - if x == nil { - return vw.WriteNull() - } - vv := reflect.ValueOf(x) - encoder, err := ec.Registry.LookupEncoder(vv.Type()) - if err != nil { - return err - } - return encoder.EncodeValue(ec, vw, vv) -} - -// isImplementationNil returns if val is a nil pointer and inter is implemented on a concrete type -func isImplementationNil(val reflect.Value, inter reflect.Type) bool { - vt := val.Type() - for vt.Kind() == reflect.Ptr { - vt = vt.Elem() - } - return vt.Implements(inter) && val.Kind() == reflect.Ptr && val.IsNil() -} diff --git a/bson/mgoregistry.go b/bson/mgoregistry.go new file mode 100644 index 0000000000..33621ce9b0 --- /dev/null +++ b/bson/mgoregistry.go @@ -0,0 +1,184 @@ +// 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 bson + +import ( + "errors" + "reflect" +) + +var ( + // errSetZero may be returned from a SetBSON method to have the value set to its respective zero value. + errSetZero = errors.New("set to zero") + + tInt = reflect.TypeOf(int(0)) + tM = reflect.TypeOf(M{}) + tInterfaceSlice = reflect.TypeOf([]interface{}{}) + tGetter = reflect.TypeOf((*getter)(nil)).Elem() + tSetter = reflect.TypeOf((*setter)(nil)).Elem() +) + +// NewMgoRegistry creates a new bson.Registry configured with the default encoders and decoders. +func NewMgoRegistry() *Registry { + mapCodec := &mapCodec{ + decodeZerosMap: true, + encodeNilAsEmpty: true, + encodeKeysWithStringer: true, + } + structCodec := &structCodec{ + elemEncoder: mapCodec, + decodeZeroStruct: true, + encodeOmitDefaultStruct: true, + allowUnexportedFields: true, + } + uintCodec := &uintCodec{encodeToMinSize: true} + + reg := NewRegistry() + reg.RegisterTypeDecoder(tEmpty, &emptyInterfaceCodec{decodeBinaryAsSlice: true}) + reg.RegisterKindDecoder(reflect.Struct, structCodec) + reg.RegisterKindDecoder(reflect.Map, mapCodec) + reg.RegisterTypeEncoder(tByteSlice, &byteSliceCodec{encodeNilAsEmpty: true}) + reg.RegisterKindEncoder(reflect.Struct, structCodec) + reg.RegisterKindEncoder(reflect.Slice, &sliceCodec{encodeNilAsEmpty: true}) + reg.RegisterKindEncoder(reflect.Map, mapCodec) + reg.RegisterKindEncoder(reflect.Uint, uintCodec) + reg.RegisterKindEncoder(reflect.Uint8, uintCodec) + reg.RegisterKindEncoder(reflect.Uint16, uintCodec) + reg.RegisterKindEncoder(reflect.Uint32, uintCodec) + reg.RegisterKindEncoder(reflect.Uint64, uintCodec) + reg.RegisterTypeMapEntry(TypeInt32, tInt) + reg.RegisterTypeMapEntry(TypeDateTime, tTime) + reg.RegisterTypeMapEntry(TypeArray, tInterfaceSlice) + reg.RegisterTypeMapEntry(Type(0), tM) + reg.RegisterTypeMapEntry(TypeEmbeddedDocument, tM) + reg.RegisterInterfaceEncoder(tGetter, ValueEncoderFunc(getterEncodeValue)) + reg.RegisterInterfaceDecoder(tSetter, ValueDecoderFunc(setterDecodeValue)) + return reg +} + +// NewRespectNilValuesMgoRegistry creates a new bson.Registry configured to behave like mgo/bson +// with RespectNilValues set to true. +func NewRespectNilValuesMgoRegistry() *Registry { + mapCodec := &mapCodec{ + decodeZerosMap: true, + } + + reg := NewMgoRegistry() + reg.RegisterKindDecoder(reflect.Map, mapCodec) + reg.RegisterTypeEncoder(tByteSlice, &byteSliceCodec{encodeNilAsEmpty: false}) + reg.RegisterKindEncoder(reflect.Slice, &sliceCodec{}) + reg.RegisterKindEncoder(reflect.Map, mapCodec) + return reg +} + +// setter interface: a value implementing the bson.Setter interface will receive the BSON +// value via the SetBSON method during unmarshaling, and the object +// itself will not be changed as usual. +// +// If setting the value works, the method should return nil or alternatively +// mgocompat.ErrSetZero to set the respective field to its zero value (nil for +// pointer types). If SetBSON returns a non-nil error, the unmarshalling +// procedure will stop and error out with the provided value. +// +// This interface is generally useful in pointer receivers, since the method +// will want to change the receiver. A type field that implements the Setter +// interface doesn't have to be a pointer, though. +// +// For example: +// +// type MyString string +// +// func (s *MyString) SetBSON(raw bson.RawValue) error { +// return raw.Unmarshal(s) +// } +type setter interface { + SetBSON(raw RawValue) error +} + +// getter interface: a value implementing the bson.Getter interface will have its GetBSON +// method called when the given value has to be marshalled, and the result +// of this method will be marshaled in place of the actual object. +// +// If GetBSON returns return a non-nil error, the marshalling procedure +// will stop and error out with the provided value. +type getter interface { + GetBSON() (interface{}, error) +} + +// setterDecodeValue is the ValueDecoderFunc for Setter types. +func setterDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { + if !val.IsValid() || (!val.Type().Implements(tSetter) && !reflect.PtrTo(val.Type()).Implements(tSetter)) { + return ValueDecoderError{Name: "SetterDecodeValue", Types: []reflect.Type{tSetter}, Received: val} + } + + if val.Kind() == reflect.Ptr && val.IsNil() { + if !val.CanSet() { + return ValueDecoderError{Name: "SetterDecodeValue", Types: []reflect.Type{tSetter}, Received: val} + } + val.Set(reflect.New(val.Type().Elem())) + } + + if !val.Type().Implements(tSetter) { + if !val.CanAddr() { + return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tSetter}, Received: val} + } + val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. + } + + t, src, err := CopyValueToBytes(vr) + if err != nil { + return err + } + + m, ok := val.Interface().(setter) + if !ok { + return ValueDecoderError{Name: "SetterDecodeValue", Types: []reflect.Type{tSetter}, Received: val} + } + if err := m.SetBSON(RawValue{Type: t, Value: src}); err != nil { + if !errors.Is(err, errSetZero) { + return err + } + val.Set(reflect.Zero(val.Type())) + } + return nil +} + +// getterEncodeValue is the ValueEncoderFunc for Getter types. +func getterEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { + // Either val or a pointer to val must implement Getter + switch { + case !val.IsValid(): + return ValueEncoderError{Name: "GetterEncodeValue", Types: []reflect.Type{tGetter}, Received: val} + case val.Type().Implements(tGetter): + // If Getter is implemented on a concrete type, make sure that val isn't a nil pointer + if isImplementationNil(val, tGetter) { + return vw.WriteNull() + } + case reflect.PtrTo(val.Type()).Implements(tGetter) && val.CanAddr(): + val = val.Addr() + default: + return ValueEncoderError{Name: "GetterEncodeValue", Types: []reflect.Type{tGetter}, Received: val} + } + + m, ok := val.Interface().(getter) + if !ok { + return vw.WriteNull() + } + x, err := m.GetBSON() + if err != nil { + return err + } + if x == nil { + return vw.WriteNull() + } + vv := reflect.ValueOf(x) + encoder, err := ec.Registry.LookupEncoder(vv.Type()) + if err != nil { + return err + } + return encoder.EncodeValue(ec, vw, vv) +} diff --git a/bson/pointer_codec.go b/bson/pointer_codec.go index 5946b9cc9f..3edb2a6a2d 100644 --- a/bson/pointer_codec.go +++ b/bson/pointer_codec.go @@ -10,29 +10,20 @@ import ( "reflect" ) -var _ ValueEncoder = &PointerCodec{} -var _ ValueDecoder = &PointerCodec{} +var ( + _ ValueEncoder = (*pointerCodec)(nil) + _ ValueDecoder = (*pointerCodec)(nil) +) -// PointerCodec is the Codec used for pointers. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// PointerCodec registered. -type PointerCodec struct { +// pointerCodec is the Codec used for pointers. +type pointerCodec struct { ecache typeEncoderCache dcache typeDecoderCache } -// NewPointerCodec returns a PointerCodec that has been initialized. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// PointerCodec registered. -func NewPointerCodec() *PointerCodec { - return &PointerCodec{} -} - // EncodeValue handles encoding a pointer by either encoding it to BSON Null if the pointer is nil // or looking up an encoder for the type of value the pointer points to. -func (pc *PointerCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +func (pc *pointerCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if val.Kind() != reflect.Ptr { if !val.IsValid() { return vw.WriteNull() @@ -62,7 +53,7 @@ func (pc *PointerCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflec // DecodeValue handles decoding a pointer by looking up a decoder for the type it points to and // using that to decode. If the BSON value is Null, this method will set the pointer to nil. -func (pc *PointerCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +func (pc *pointerCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Kind() != reflect.Ptr { return ValueDecoderError{Name: "PointerCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val} } diff --git a/bson/primitive_codecs.go b/bson/primitive_codecs.go index 262645ce4c..334549465e 100644 --- a/bson/primitive_codecs.go +++ b/bson/primitive_codecs.go @@ -7,7 +7,6 @@ package bson import ( - "errors" "fmt" "reflect" ) @@ -15,38 +14,20 @@ import ( var tRawValue = reflect.TypeOf(RawValue{}) var tRaw = reflect.TypeOf(Raw(nil)) -// PrimitiveCodecs is a namespace for all of the default Codecs for the primitive types -// defined in this package. -// -// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders -// registered. -type PrimitiveCodecs struct{} - -// RegisterPrimitiveCodecs will register the encode and decode methods attached to PrimitiveCodecs +// registerPrimitiveCodecs will register the encode and decode methods attached to PrimitiveCodecs // with the provided RegistryBuilder. if rb is nil, a new empty RegistryBuilder will be created. -// -// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders -// registered. -func (pc PrimitiveCodecs) RegisterPrimitiveCodecs(rb *RegistryBuilder) { - if rb == nil { - panic(errors.New("argument to RegisterPrimitiveCodecs must not be nil")) - } - - rb. - RegisterTypeEncoder(tRawValue, ValueEncoderFunc(pc.RawValueEncodeValue)). - RegisterTypeEncoder(tRaw, ValueEncoderFunc(pc.RawEncodeValue)). - RegisterTypeDecoder(tRawValue, ValueDecoderFunc(pc.RawValueDecodeValue)). - RegisterTypeDecoder(tRaw, ValueDecoderFunc(pc.RawDecodeValue)) +func registerPrimitiveCodecs(reg *Registry) { + reg.RegisterTypeEncoder(tRawValue, ValueEncoderFunc(rawValueEncodeValue)) + reg.RegisterTypeEncoder(tRaw, ValueEncoderFunc(rawEncodeValue)) + reg.RegisterTypeDecoder(tRawValue, ValueDecoderFunc(rawValueDecodeValue)) + reg.RegisterTypeDecoder(tRaw, ValueDecoderFunc(rawDecodeValue)) } -// RawValueEncodeValue is the ValueEncoderFunc for RawValue. +// rawValueEncodeValue is the ValueEncoderFunc for RawValue. // // If the RawValue's Type is "invalid" and the RawValue's Value is not empty or // nil, then this method will return an error. -// -// Deprecated: Use bson.NewRegistry to get a registry with all primitive -// encoders and decoders registered. -func (PrimitiveCodecs) RawValueEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +func rawValueEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tRawValue { return ValueEncoderError{ Name: "RawValueEncodeValue", @@ -64,11 +45,8 @@ func (PrimitiveCodecs) RawValueEncodeValue(_ EncodeContext, vw ValueWriter, val return copyValueFromBytes(vw, rawvalue.Type, rawvalue.Value) } -// RawValueDecodeValue is the ValueDecoderFunc for RawValue. -// -// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders -// registered. -func (PrimitiveCodecs) RawValueDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { +// rawValueDecodeValue is the ValueDecoderFunc for RawValue. +func rawValueDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tRawValue { return ValueDecoderError{Name: "RawValueDecodeValue", Types: []reflect.Type{tRawValue}, Received: val} } @@ -82,11 +60,8 @@ func (PrimitiveCodecs) RawValueDecodeValue(_ DecodeContext, vr ValueReader, val return nil } -// RawEncodeValue is the ValueEncoderFunc for Reader. -// -// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders -// registered. -func (PrimitiveCodecs) RawEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +// rawEncodeValue is the ValueEncoderFunc for Reader. +func rawEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tRaw { return ValueEncoderError{Name: "RawEncodeValue", Types: []reflect.Type{tRaw}, Received: val} } @@ -96,11 +71,8 @@ func (PrimitiveCodecs) RawEncodeValue(_ EncodeContext, vw ValueWriter, val refle return copyDocumentFromBytes(vw, rdr) } -// RawDecodeValue is the ValueDecoderFunc for Reader. -// -// Deprecated: Use bson.NewRegistry to get a registry with all primitive encoders and decoders -// registered. -func (PrimitiveCodecs) RawDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { +// rawDecodeValue is the ValueDecoderFunc for Reader. +func rawDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tRaw { return ValueDecoderError{Name: "RawDecodeValue", Types: []reflect.Type{tRaw}, Received: val} } diff --git a/bson/primitive_codecs_test.go b/bson/primitive_codecs_test.go index be3aeab978..6b0c4c1e05 100644 --- a/bson/primitive_codecs_test.go +++ b/bson/primitive_codecs_test.go @@ -32,8 +32,6 @@ func bytesFromDoc(doc interface{}) []byte { func TestPrimitiveValueEncoders(t *testing.T) { t.Parallel() - var pc PrimitiveCodecs - var wrong = func(string, string) string { return "wrong" } type subtest struct { @@ -52,7 +50,7 @@ func TestPrimitiveValueEncoders(t *testing.T) { }{ { "RawValueEncodeValue", - ValueEncoderFunc(pc.RawValueEncodeValue), + ValueEncoderFunc(rawValueEncodeValue), []subtest{ { "wrong type", @@ -100,7 +98,7 @@ func TestPrimitiveValueEncoders(t *testing.T) { }, { "RawEncodeValue", - ValueEncoderFunc(pc.RawEncodeValue), + ValueEncoderFunc(rawEncodeValue), []subtest{ { "wrong type", @@ -478,8 +476,6 @@ func TestPrimitiveValueEncoders(t *testing.T) { } func TestPrimitiveValueDecoders(t *testing.T) { - var pc PrimitiveCodecs - var wrong = func(string, string) string { return "wrong" } const cansetreflectiontest = "cansetreflectiontest" @@ -500,7 +496,7 @@ func TestPrimitiveValueDecoders(t *testing.T) { }{ { "RawValueDecodeValue", - ValueDecoderFunc(pc.RawValueDecodeValue), + ValueDecoderFunc(rawValueDecodeValue), []subtest{ { "wrong type", @@ -544,7 +540,7 @@ func TestPrimitiveValueDecoders(t *testing.T) { }, { "RawDecodeValue", - ValueDecoderFunc(pc.RawDecodeValue), + ValueDecoderFunc(rawDecodeValue), []subtest{ { "wrong type", diff --git a/bson/raw_value_test.go b/bson/raw_value_test.go index f02fe8f326..67444faa61 100644 --- a/bson/raw_value_test.go +++ b/bson/raw_value_test.go @@ -25,7 +25,7 @@ func TestRawValue(t *testing.T) { t.Run("Uses registry attached to value", func(t *testing.T) { t.Parallel() - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() val := RawValue{Type: TypeString, Value: bsoncore.AppendString(nil, "foobar"), r: reg} var s string want := ErrNoDecoder{Type: reflect.TypeOf(s)} @@ -63,7 +63,7 @@ func TestRawValue(t *testing.T) { t.Run("Returns lookup error", func(t *testing.T) { t.Parallel() - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() var val RawValue var s string want := ErrNoDecoder{Type: reflect.TypeOf(s)} @@ -114,7 +114,7 @@ func TestRawValue(t *testing.T) { t.Run("Returns lookup error", func(t *testing.T) { t.Parallel() - dc := DecodeContext{Registry: newTestRegistryBuilder().Build()} + dc := DecodeContext{Registry: newTestRegistry()} var val RawValue var s string want := ErrNoDecoder{Type: reflect.TypeOf(s)} diff --git a/bson/registry.go b/bson/registry.go index 74b99e93ab..bcd3133445 100644 --- a/bson/registry.go +++ b/bson/registry.go @@ -63,187 +63,6 @@ func (entme ErrNoTypeMapEntry) Error() string { return "no type map entry found for " + entme.Type.String() } -// ErrNotInterface is returned when the provided type is not an interface. -// -// Deprecated: ErrNotInterface will not be supported in Go Driver 2.0. -var ErrNotInterface = errors.New("The provided type is not an interface") - -// A RegistryBuilder is used to build a Registry. This type is not goroutine -// safe. -// -// Deprecated: Use Registry instead. -type RegistryBuilder struct { - registry *Registry -} - -// NewRegistryBuilder creates a new empty RegistryBuilder. -// -// Deprecated: Use NewRegistry instead. -func NewRegistryBuilder() *RegistryBuilder { - rb := &RegistryBuilder{ - registry: &Registry{ - typeEncoders: new(typeEncoderCache), - typeDecoders: new(typeDecoderCache), - kindEncoders: new(kindEncoderCache), - kindDecoders: new(kindDecoderCache), - }, - } - DefaultValueEncoders{}.RegisterDefaultEncoders(rb) - DefaultValueDecoders{}.RegisterDefaultDecoders(rb) - PrimitiveCodecs{}.RegisterPrimitiveCodecs(rb) - return rb -} - -// RegisterCodec will register the provided ValueCodec for the provided type. -// -// Deprecated: Use Registry.RegisterTypeEncoder and Registry.RegisterTypeDecoder instead. -func (rb *RegistryBuilder) RegisterCodec(t reflect.Type, codec ValueCodec) *RegistryBuilder { - rb.RegisterTypeEncoder(t, codec) - rb.RegisterTypeDecoder(t, codec) - return rb -} - -// RegisterTypeEncoder will register the provided ValueEncoder for the provided type. -// -// The type will be used directly, so an encoder can be registered for a type and a different encoder can be registered -// for a pointer to that type. -// -// If the given type is an interface, the encoder will be called when marshaling a type that is that interface. It -// will not be called when marshaling a non-interface type that implements the interface. -// -// Deprecated: Use Registry.RegisterTypeEncoder instead. -func (rb *RegistryBuilder) RegisterTypeEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { - rb.registry.RegisterTypeEncoder(t, enc) - return rb -} - -// RegisterHookEncoder will register an encoder for the provided interface type t. This encoder will be called when -// marshaling a type if the type implements t or a pointer to the type implements t. If the provided type is not -// an interface (i.e. t.Kind() != reflect.Interface), this method will panic. -// -// Deprecated: Use Registry.RegisterInterfaceEncoder instead. -func (rb *RegistryBuilder) RegisterHookEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { - rb.registry.RegisterInterfaceEncoder(t, enc) - return rb -} - -// RegisterTypeDecoder will register the provided ValueDecoder for the provided type. -// -// The type will be used directly, so a decoder can be registered for a type and a different decoder can be registered -// for a pointer to that type. -// -// If the given type is an interface, the decoder will be called when unmarshaling into a type that is that interface. -// It will not be called when unmarshaling into a non-interface type that implements the interface. -// -// Deprecated: Use Registry.RegisterTypeDecoder instead. -func (rb *RegistryBuilder) RegisterTypeDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { - rb.registry.RegisterTypeDecoder(t, dec) - return rb -} - -// RegisterHookDecoder will register an decoder for the provided interface type t. This decoder will be called when -// unmarshaling into a type if the type implements t or a pointer to the type implements t. If the provided type is not -// an interface (i.e. t.Kind() != reflect.Interface), this method will panic. -// -// Deprecated: Use Registry.RegisterInterfaceDecoder instead. -func (rb *RegistryBuilder) RegisterHookDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { - rb.registry.RegisterInterfaceDecoder(t, dec) - return rb -} - -// RegisterEncoder registers the provided type and encoder pair. -// -// Deprecated: Use Registry.RegisterTypeEncoder or Registry.RegisterInterfaceEncoder instead. -func (rb *RegistryBuilder) RegisterEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { - if t == tEmpty { - rb.registry.RegisterTypeEncoder(t, enc) - return rb - } - switch t.Kind() { - case reflect.Interface: - rb.registry.RegisterInterfaceEncoder(t, enc) - default: - rb.registry.RegisterTypeEncoder(t, enc) - } - return rb -} - -// RegisterDecoder registers the provided type and decoder pair. -// -// Deprecated: Use Registry.RegisterTypeDecoder or Registry.RegisterInterfaceDecoder instead. -func (rb *RegistryBuilder) RegisterDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { - if t == nil { - rb.registry.RegisterTypeDecoder(t, dec) - return rb - } - if t == tEmpty { - rb.registry.RegisterTypeDecoder(t, dec) - return rb - } - switch t.Kind() { - case reflect.Interface: - rb.registry.RegisterInterfaceDecoder(t, dec) - default: - rb.registry.RegisterTypeDecoder(t, dec) - } - return rb -} - -// RegisterDefaultEncoder will register the provided ValueEncoder to the provided -// kind. -// -// Deprecated: Use Registry.RegisterKindEncoder instead. -func (rb *RegistryBuilder) RegisterDefaultEncoder(kind reflect.Kind, enc ValueEncoder) *RegistryBuilder { - rb.registry.RegisterKindEncoder(kind, enc) - return rb -} - -// RegisterDefaultDecoder will register the provided ValueDecoder to the -// provided kind. -// -// Deprecated: Use Registry.RegisterKindDecoder instead. -func (rb *RegistryBuilder) RegisterDefaultDecoder(kind reflect.Kind, dec ValueDecoder) *RegistryBuilder { - rb.registry.RegisterKindDecoder(kind, dec) - return rb -} - -// RegisterTypeMapEntry will register the provided type to the BSON type. The primary usage for this -// mapping is decoding situations where an empty interface is used and a default type needs to be -// created and decoded into. -// -// By default, BSON documents will decode into interface{} values as bson.D. To change the default type for BSON -// documents, a type map entry for TypeEmbeddedDocument should be registered. For example, to force BSON documents -// to decode to bson.Raw, use the following code: -// -// rb.RegisterTypeMapEntry(TypeEmbeddedDocument, reflect.TypeOf(bson.Raw{})) -// -// Deprecated: Use Registry.RegisterTypeMapEntry instead. -func (rb *RegistryBuilder) RegisterTypeMapEntry(bt Type, rt reflect.Type) *RegistryBuilder { - rb.registry.RegisterTypeMapEntry(bt, rt) - return rb -} - -// Build creates a Registry from the current state of this RegistryBuilder. -// -// Deprecated: Use NewRegistry instead. -func (rb *RegistryBuilder) Build() *Registry { - r := &Registry{ - interfaceEncoders: append([]interfaceValueEncoder(nil), rb.registry.interfaceEncoders...), - interfaceDecoders: append([]interfaceValueDecoder(nil), rb.registry.interfaceDecoders...), - typeEncoders: rb.registry.typeEncoders.Clone(), - typeDecoders: rb.registry.typeDecoders.Clone(), - kindEncoders: rb.registry.kindEncoders.Clone(), - kindDecoders: rb.registry.kindDecoders.Clone(), - } - rb.registry.typeMap.Range(func(k, v interface{}) bool { - if k != nil && v != nil { - r.typeMap.Store(k, v) - } - return true - }) - return r -} - // A Registry is a store for ValueEncoders, ValueDecoders, and a type map. See the Registry type // documentation for examples of registering various custom encoders and decoders. A Registry can // have four main types of codecs: @@ -289,7 +108,16 @@ type Registry struct { // NewRegistry creates a new empty Registry. func NewRegistry() *Registry { - return NewRegistryBuilder().Build() + reg := &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), + } + registerDefaultEncoders(reg) + registerDefaultDecoders(reg) + registerPrimitiveCodecs(reg) + return reg } // RegisterTypeEncoder registers the provided ValueEncoder for the provided type. diff --git a/bson/registry_test.go b/bson/registry_test.go index 2bc87364d3..184501933a 100644 --- a/bson/registry_test.go +++ b/bson/registry_test.go @@ -15,15 +15,13 @@ import ( "go.mongodb.org/mongo-driver/internal/assert" ) -// newTestRegistryBuilder creates a new empty Registry. -func newTestRegistryBuilder() *RegistryBuilder { - return &RegistryBuilder{ - registry: &Registry{ - typeEncoders: new(typeEncoderCache), - typeDecoders: new(typeDecoderCache), - kindEncoders: new(kindEncoderCache), - kindDecoders: new(kindDecoderCache), - }, +// newTestRegistry creates a new Registry. +func newTestRegistry() *Registry { + return &Registry{ + typeEncoders: new(typeEncoderCache), + typeDecoders: new(typeDecoderCache), + kindEncoders: new(kindEncoderCache), + kindDecoders: new(kindDecoderCache), } } @@ -45,12 +43,11 @@ func TestRegistryBuilder(t *testing.T) { {i: reflect.TypeOf(t2f).Elem(), ve: fc2}, {i: reflect.TypeOf(t4f).Elem(), ve: fc4}, } - rb := newTestRegistryBuilder() + reg := newTestRegistry() for _, ip := range ips { - rb.RegisterHookEncoder(ip.i, ip.ve) + reg.RegisterInterfaceEncoder(ip.i, ip.ve) } - reg := rb.Build() got := reg.interfaceEncoders if !cmp.Equal(got, want, cmp.AllowUnexported(interfaceValueEncoder{}, fakeCodec{}), cmp.Comparer(typeComparer)) { t.Errorf("the registered interfaces are not correct: got %#v, want %#v", got, want) @@ -58,11 +55,11 @@ func TestRegistryBuilder(t *testing.T) { }) t.Run("type", func(t *testing.T) { ft1, ft2, ft4 := fakeType1{}, fakeType2{}, fakeType4{} - rb := newTestRegistryBuilder(). - RegisterTypeEncoder(reflect.TypeOf(ft1), fc1). - RegisterTypeEncoder(reflect.TypeOf(ft2), fc2). - RegisterTypeEncoder(reflect.TypeOf(ft1), fc3). - RegisterTypeEncoder(reflect.TypeOf(ft4), fc4) + reg := newTestRegistry() + reg.RegisterTypeEncoder(reflect.TypeOf(ft1), fc1) + reg.RegisterTypeEncoder(reflect.TypeOf(ft2), fc2) + reg.RegisterTypeEncoder(reflect.TypeOf(ft1), fc3) + reg.RegisterTypeEncoder(reflect.TypeOf(ft4), fc4) want := []struct { t reflect.Type c ValueEncoder @@ -72,7 +69,6 @@ func TestRegistryBuilder(t *testing.T) { {reflect.TypeOf(ft4), fc4}, } - reg := rb.Build() got := reg.typeEncoders for _, s := range want { wantT, wantC := s.t, s.c @@ -87,11 +83,11 @@ func TestRegistryBuilder(t *testing.T) { }) t.Run("kind", func(t *testing.T) { k1, k2, k4 := reflect.Struct, reflect.Slice, reflect.Map - rb := newTestRegistryBuilder(). - RegisterDefaultEncoder(k1, fc1). - RegisterDefaultEncoder(k2, fc2). - RegisterDefaultEncoder(k1, fc3). - RegisterDefaultEncoder(k4, fc4) + reg := newTestRegistry() + reg.RegisterKindEncoder(k1, fc1) + reg.RegisterKindEncoder(k2, fc2) + reg.RegisterKindEncoder(k1, fc3) + reg.RegisterKindEncoder(k4, fc4) want := []struct { k reflect.Kind c ValueEncoder @@ -101,7 +97,6 @@ func TestRegistryBuilder(t *testing.T) { {k4, fc4}, } - reg := rb.Build() got := reg.kindEncoders for _, s := range want { wantK, wantC := s.k, s.c @@ -118,16 +113,14 @@ func TestRegistryBuilder(t *testing.T) { t.Run("MapCodec", func(t *testing.T) { codec := &fakeCodec{num: 1} codec2 := &fakeCodec{num: 2} - rb := newTestRegistryBuilder() + reg := newTestRegistry() - rb.RegisterDefaultEncoder(reflect.Map, codec) - reg := rb.Build() + reg.RegisterKindEncoder(reflect.Map, codec) if reg.kindEncoders.get(reflect.Map) != codec { t.Errorf("map codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Map), codec) } - rb.RegisterDefaultEncoder(reflect.Map, codec2) - reg = rb.Build() + reg.RegisterKindEncoder(reflect.Map, codec2) if reg.kindEncoders.get(reflect.Map) != codec2 { t.Errorf("map codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Map), codec2) } @@ -135,16 +128,14 @@ func TestRegistryBuilder(t *testing.T) { t.Run("StructCodec", func(t *testing.T) { codec := &fakeCodec{num: 1} codec2 := &fakeCodec{num: 2} - rb := newTestRegistryBuilder() + reg := newTestRegistry() - rb.RegisterDefaultEncoder(reflect.Struct, codec) - reg := rb.Build() + reg.RegisterKindEncoder(reflect.Struct, codec) if reg.kindEncoders.get(reflect.Struct) != codec { t.Errorf("struct codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Struct), codec) } - rb.RegisterDefaultEncoder(reflect.Struct, codec2) - reg = rb.Build() + reg.RegisterKindEncoder(reflect.Struct, codec2) if reg.kindEncoders.get(reflect.Struct) != codec2 { t.Errorf("struct codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Struct), codec2) } @@ -152,16 +143,14 @@ func TestRegistryBuilder(t *testing.T) { t.Run("SliceCodec", func(t *testing.T) { codec := &fakeCodec{num: 1} codec2 := &fakeCodec{num: 2} - rb := newTestRegistryBuilder() + reg := newTestRegistry() - rb.RegisterDefaultEncoder(reflect.Slice, codec) - reg := rb.Build() + reg.RegisterKindEncoder(reflect.Slice, codec) if reg.kindEncoders.get(reflect.Slice) != codec { t.Errorf("slice codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Slice), codec) } - rb.RegisterDefaultEncoder(reflect.Slice, codec2) - reg = rb.Build() + reg.RegisterKindEncoder(reflect.Slice, codec2) if reg.kindEncoders.get(reflect.Slice) != codec2 { t.Errorf("slice codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Slice), codec2) } @@ -169,16 +158,14 @@ func TestRegistryBuilder(t *testing.T) { t.Run("ArrayCodec", func(t *testing.T) { codec := &fakeCodec{num: 1} codec2 := &fakeCodec{num: 2} - rb := newTestRegistryBuilder() + reg := newTestRegistry() - rb.RegisterDefaultEncoder(reflect.Array, codec) - reg := rb.Build() + reg.RegisterKindEncoder(reflect.Array, codec) if reg.kindEncoders.get(reflect.Array) != codec { t.Errorf("slice codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Array), codec) } - rb.RegisterDefaultEncoder(reflect.Array, codec2) - reg = rb.Build() + reg.RegisterKindEncoder(reflect.Array, codec2) if reg.kindEncoders.get(reflect.Array) != codec2 { t.Errorf("slice codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Array), codec2) } @@ -208,31 +195,30 @@ func TestRegistryBuilder(t *testing.T) { ti3ImplPtr = reflect.TypeOf((*testInterface3Impl)(nil)) fc1, fc2 = &fakeCodec{num: 1}, &fakeCodec{num: 2} fsc, fslcc, fmc = new(fakeStructCodec), new(fakeSliceCodec), new(fakeMapCodec) - pc = NewPointerCodec() + pc = &pointerCodec{} ) - reg := newTestRegistryBuilder(). - RegisterTypeEncoder(ft1, fc1). - RegisterTypeEncoder(ft2, fc2). - RegisterTypeEncoder(ti1, fc1). - RegisterDefaultEncoder(reflect.Struct, fsc). - RegisterDefaultEncoder(reflect.Slice, fslcc). - RegisterDefaultEncoder(reflect.Array, fslcc). - RegisterDefaultEncoder(reflect.Map, fmc). - RegisterDefaultEncoder(reflect.Ptr, pc). - RegisterTypeDecoder(ft1, fc1). - RegisterTypeDecoder(ft2, fc2). - RegisterTypeDecoder(ti1, fc1). // values whose exact type is testInterface1 will use fc1 encoder - RegisterDefaultDecoder(reflect.Struct, fsc). - RegisterDefaultDecoder(reflect.Slice, fslcc). - RegisterDefaultDecoder(reflect.Array, fslcc). - RegisterDefaultDecoder(reflect.Map, fmc). - RegisterDefaultDecoder(reflect.Ptr, pc). - RegisterHookEncoder(ti2, fc2). - RegisterHookDecoder(ti2, fc2). - RegisterHookEncoder(ti3, fc3). - RegisterHookDecoder(ti3, fc3). - Build() + reg := newTestRegistry() + reg.RegisterTypeEncoder(ft1, fc1) + reg.RegisterTypeEncoder(ft2, fc2) + reg.RegisterTypeEncoder(ti1, fc1) + reg.RegisterKindEncoder(reflect.Struct, fsc) + reg.RegisterKindEncoder(reflect.Slice, fslcc) + reg.RegisterKindEncoder(reflect.Array, fslcc) + reg.RegisterKindEncoder(reflect.Map, fmc) + reg.RegisterKindEncoder(reflect.Ptr, pc) + reg.RegisterTypeDecoder(ft1, fc1) + reg.RegisterTypeDecoder(ft2, fc2) + reg.RegisterTypeDecoder(ti1, fc1) // values whose exact type is testInterface1 will use fc1 encoder + reg.RegisterKindDecoder(reflect.Struct, fsc) + reg.RegisterKindDecoder(reflect.Slice, fslcc) + reg.RegisterKindDecoder(reflect.Array, fslcc) + reg.RegisterKindDecoder(reflect.Map, fmc) + reg.RegisterKindDecoder(reflect.Ptr, pc) + reg.RegisterInterfaceEncoder(ti2, fc2) + reg.RegisterInterfaceDecoder(ti2, fc2) + reg.RegisterInterfaceEncoder(ti3, fc3) + reg.RegisterInterfaceDecoder(ti3, fc3) testCases := []struct { name string @@ -348,7 +334,7 @@ func TestRegistryBuilder(t *testing.T) { } allowunexported := cmp.AllowUnexported(fakeCodec{}, fakeStructCodec{}, fakeSliceCodec{}, fakeMapCodec{}) - comparepc := func(pc1, pc2 *PointerCodec) bool { return true } + comparepc := func(pc1, pc2 *pointerCodec) bool { return true } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { t.Run("Encoder", func(t *testing.T) { @@ -409,10 +395,9 @@ func TestRegistryBuilder(t *testing.T) { }) }) t.Run("Type Map", func(t *testing.T) { - reg := newTestRegistryBuilder(). - RegisterTypeMapEntry(TypeString, reflect.TypeOf("")). - RegisterTypeMapEntry(TypeInt32, reflect.TypeOf(int(0))). - Build() + reg := newTestRegistry() + reg.RegisterTypeMapEntry(TypeString, reflect.TypeOf("")) + reg.RegisterTypeMapEntry(TypeInt32, reflect.TypeOf(int(0))) var got, want reflect.Type @@ -466,7 +451,7 @@ func TestRegistry(t *testing.T) { {i: reflect.TypeOf(t2f).Elem(), ve: fc2}, {i: reflect.TypeOf(t4f).Elem(), ve: fc4}, } - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() for _, ip := range ips { reg.RegisterInterfaceEncoder(ip.i, ip.ve) } @@ -479,7 +464,7 @@ func TestRegistry(t *testing.T) { t.Parallel() ft1, ft2, ft4 := fakeType1{}, fakeType2{}, fakeType4{} - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() reg.RegisterTypeEncoder(reflect.TypeOf(ft1), fc1) reg.RegisterTypeEncoder(reflect.TypeOf(ft2), fc2) reg.RegisterTypeEncoder(reflect.TypeOf(ft1), fc3) @@ -509,7 +494,7 @@ func TestRegistry(t *testing.T) { t.Parallel() k1, k2, k4 := reflect.Struct, reflect.Slice, reflect.Map - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() reg.RegisterKindEncoder(k1, fc1) reg.RegisterKindEncoder(k2, fc2) reg.RegisterKindEncoder(k1, fc3) @@ -543,7 +528,7 @@ func TestRegistry(t *testing.T) { codec := &fakeCodec{num: 1} codec2 := &fakeCodec{num: 2} - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() reg.RegisterKindEncoder(reflect.Map, codec) if reg.kindEncoders.get(reflect.Map) != codec { t.Errorf("map codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Map), codec) @@ -558,7 +543,7 @@ func TestRegistry(t *testing.T) { codec := &fakeCodec{num: 1} codec2 := &fakeCodec{num: 2} - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() reg.RegisterKindEncoder(reflect.Struct, codec) if reg.kindEncoders.get(reflect.Struct) != codec { t.Errorf("struct codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Struct), codec) @@ -573,7 +558,7 @@ func TestRegistry(t *testing.T) { codec := &fakeCodec{num: 1} codec2 := &fakeCodec{num: 2} - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() reg.RegisterKindEncoder(reflect.Slice, codec) if reg.kindEncoders.get(reflect.Slice) != codec { t.Errorf("slice codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Slice), codec) @@ -588,7 +573,7 @@ func TestRegistry(t *testing.T) { codec := &fakeCodec{num: 1} codec2 := &fakeCodec{num: 2} - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() reg.RegisterKindEncoder(reflect.Array, codec) if reg.kindEncoders.get(reflect.Array) != codec { t.Errorf("slice codec not properly set: got %#v, want %#v", reg.kindEncoders.get(reflect.Array), codec) @@ -625,10 +610,10 @@ func TestRegistry(t *testing.T) { ti3ImplPtr = reflect.TypeOf((*testInterface3Impl)(nil)) fc1, fc2 = &fakeCodec{num: 1}, &fakeCodec{num: 2} fsc, fslcc, fmc = new(fakeStructCodec), new(fakeSliceCodec), new(fakeMapCodec) - pc = NewPointerCodec() + pc = &pointerCodec{} ) - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() reg.RegisterTypeEncoder(ft1, fc1) reg.RegisterTypeEncoder(ft2, fc2) reg.RegisterTypeEncoder(ti1, fc1) @@ -764,7 +749,7 @@ func TestRegistry(t *testing.T) { } allowunexported := cmp.AllowUnexported(fakeCodec{}, fakeStructCodec{}, fakeSliceCodec{}, fakeMapCodec{}) - comparepc := func(pc1, pc2 *PointerCodec) bool { return true } + comparepc := func(pc1, pc2 *pointerCodec) bool { return true } for _, tc := range testCases { tc := tc @@ -869,7 +854,7 @@ func TestRegistry(t *testing.T) { }) t.Run("Type Map", func(t *testing.T) { t.Parallel() - reg := newTestRegistryBuilder().Build() + reg := newTestRegistry() reg.RegisterTypeMapEntry(TypeString, reflect.TypeOf("")) reg.RegisterTypeMapEntry(TypeInt32, reflect.TypeOf(int(0))) diff --git a/bson/slice_codec.go b/bson/slice_codec.go index 52449239b9..45509ae7f8 100644 --- a/bson/slice_codec.go +++ b/bson/slice_codec.go @@ -10,45 +10,22 @@ import ( "errors" "fmt" "reflect" - - "go.mongodb.org/mongo-driver/bson/bsonoptions" ) -var defaultSliceCodec = NewSliceCodec() - -// SliceCodec is the Codec used for slice values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// SliceCodec registered. -type SliceCodec struct { - // EncodeNilAsEmpty causes EncodeValue to marshal nil Go slices as empty BSON arrays instead of +// sliceCodec is the Codec used for slice values. +type sliceCodec struct { + // encodeNilAsEmpty causes EncodeValue to marshal nil Go slices as empty BSON arrays instead of // BSON null. - // - // Deprecated: Use bson.Encoder.NilSliceAsEmpty instead. - EncodeNilAsEmpty bool -} - -// NewSliceCodec returns a MapCodec with options opts. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// SliceCodec registered. -func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec { - sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...) - - codec := SliceCodec{} - if sliceOpt.EncodeNilAsEmpty != nil { - codec.EncodeNilAsEmpty = *sliceOpt.EncodeNilAsEmpty - } - return &codec + encodeNilAsEmpty bool } // EncodeValue is the ValueEncoder for slice types. -func (sc SliceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +func (sc *sliceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Slice { return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} } - if val.IsNil() && !sc.EncodeNilAsEmpty && !ec.nilSliceAsEmpty { + if val.IsNil() && !sc.encodeNilAsEmpty && !ec.nilSliceAsEmpty { return vw.WriteNull() } @@ -90,7 +67,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.V } for idx := 0; idx < val.Len(); idx++ { - currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx)) + currEncoder, currVal, lookupErr := lookupElementEncoder(ec, encoder, val.Index(idx)) if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -117,7 +94,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.V } // DecodeValue is the ValueDecoder for slice types. -func (sc *SliceCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +func (sc *sliceCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Kind() != reflect.Slice { return ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} } @@ -176,9 +153,9 @@ func (sc *SliceCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect. switch val.Type().Elem() { case tE: dc.Ancestor = val.Type() - elemsFunc = defaultValueDecoders.decodeD + elemsFunc = decodeD default: - elemsFunc = defaultValueDecoders.decodeDefault + elemsFunc = decodeDefault } elems, err := elemsFunc(dc, vr, val) diff --git a/bson/string_codec.go b/bson/string_codec.go index 50fb9229fe..db7c01bd8f 100644 --- a/bson/string_codec.go +++ b/bson/string_codec.go @@ -9,42 +9,24 @@ package bson import ( "fmt" "reflect" - - "go.mongodb.org/mongo-driver/bson/bsonoptions" ) -// StringCodec is the Codec used for string values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// StringCodec registered. -type StringCodec struct { +// stringCodec is the Codec used for string values. +type stringCodec struct { // DecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation. // If false, a string made from the raw object ID bytes will be used. Defaults to true. - // - // Deprecated: Decoding object IDs as raw bytes will not be supported in Go Driver 2.0. - DecodeObjectIDAsHex bool + decodeObjectIDAsHex bool } var ( - defaultStringCodec = NewStringCodec() - - // Assert that defaultStringCodec satisfies the typeDecoder interface, which allows it to be + // Assert that stringCodec satisfies the typeDecoder interface, which allows it to be // used by collection type decoders (e.g. map, slice, etc) to set individual values in a // collection. - _ typeDecoder = defaultStringCodec + _ typeDecoder = (*stringCodec)(nil) ) -// NewStringCodec returns a StringCodec with options opts. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// StringCodec registered. -func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec { - stringOpt := bsonoptions.MergeStringCodecOptions(opts...) - return &StringCodec{*stringOpt.DecodeObjectIDAsHex} -} - // EncodeValue is the ValueEncoder for string types. -func (sc *StringCodec) EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +func (sc *stringCodec) EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if val.Kind() != reflect.String { return ValueEncoderError{ Name: "StringEncodeValue", @@ -56,7 +38,7 @@ func (sc *StringCodec) EncodeValue(_ EncodeContext, vw ValueWriter, val reflect. return vw.WriteString(val.String()) } -func (sc *StringCodec) decodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func (sc *stringCodec) decodeType(_ DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t.Kind() != reflect.String { return emptyValue, ValueDecoderError{ Name: "StringDecodeValue", @@ -78,7 +60,7 @@ func (sc *StringCodec) decodeType(_ DecodeContext, vr ValueReader, t reflect.Typ if err != nil { return emptyValue, err } - if sc.DecodeObjectIDAsHex { + if sc.decodeObjectIDAsHex { str = oid.Hex() } else { // TODO(GODRIVER-2796): Return an error here instead of decoding to a garbled string. @@ -115,7 +97,7 @@ func (sc *StringCodec) decodeType(_ DecodeContext, vr ValueReader, t reflect.Typ } // DecodeValue is the ValueDecoder for string types. -func (sc *StringCodec) DecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { +func (sc *stringCodec) DecodeValue(dctx DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Kind() != reflect.String { return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val} } diff --git a/bson/string_codec_test.go b/bson/string_codec_test.go index 75ace60c5d..a231d0e647 100644 --- a/bson/string_codec_test.go +++ b/bson/string_codec_test.go @@ -10,7 +10,6 @@ import ( "reflect" "testing" - "go.mongodb.org/mongo-driver/bson/bsonoptions" "go.mongodb.org/mongo-driver/internal/assert" ) @@ -20,21 +19,19 @@ func TestStringCodec(t *testing.T) { byteArray := [12]byte(oid) reader := &valueReaderWriter{BSONType: TypeObjectID, Return: oid} testCases := []struct { - name string - opts *bsonoptions.StringCodecOptions - hex bool - result string + name string + stringCodec *stringCodec + hex bool + result string }{ - {"default", bsonoptions.StringCodec(), true, oid.Hex()}, - {"true", bsonoptions.StringCodec().SetDecodeObjectIDAsHex(true), true, oid.Hex()}, - {"false", bsonoptions.StringCodec().SetDecodeObjectIDAsHex(false), false, string(byteArray[:])}, + {"default", &stringCodec{}, true, oid.Hex()}, + {"true", &stringCodec{decodeObjectIDAsHex: true}, true, oid.Hex()}, + {"false", &stringCodec{decodeObjectIDAsHex: false}, false, string(byteArray[:])}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - stringCodec := NewStringCodec(tc.opts) - actual := reflect.New(reflect.TypeOf("")).Elem() - err := stringCodec.DecodeValue(DecodeContext{}, reader, actual) + err := tc.stringCodec.DecodeValue(DecodeContext{}, reader, actual) assert.Nil(t, err, "StringCodec.DecodeValue error: %v", err) actualString := actual.Interface().(string) diff --git a/bson/struct_codec.go b/bson/struct_codec.go index 917ac17bfd..a2f517ca72 100644 --- a/bson/struct_codec.go +++ b/bson/struct_codec.go @@ -14,8 +14,6 @@ import ( "strings" "sync" "time" - - "go.mongodb.org/mongo-driver/bson/bsonoptions" ) // DecodeError represents an error that occurs when unmarshalling BSON bytes into a native Go type. @@ -49,86 +47,53 @@ func (de *DecodeError) Keys() []string { return reversedKeys } -// StructCodec is the Codec used for struct values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// StructCodec registered. -type StructCodec struct { - cache sync.Map // map[reflect.Type]*structDescription - parser StructTagParser +// mapElementsEncoder handles encoding of the values of an inline map. +type mapElementsEncoder interface { + encodeMapElements(EncodeContext, DocumentWriter, reflect.Value, func(string) bool) error +} + +// structCodec is the Codec used for struct values. +type structCodec struct { + cache sync.Map // map[reflect.Type]*structDescription + elemEncoder mapElementsEncoder // DecodeZeroStruct causes DecodeValue to delete any existing values from Go structs in the // destination value passed to Decode before unmarshaling BSON documents into them. - // - // Deprecated: Use bson.Decoder.ZeroStructs instead. - DecodeZeroStruct bool + decodeZeroStruct bool // DecodeDeepZeroInline causes DecodeValue to delete any existing values from Go structs in the // destination value passed to Decode before unmarshaling BSON documents into them. - // - // Deprecated: DecodeDeepZeroInline will not be supported in Go Driver 2.0. - DecodeDeepZeroInline bool + decodeDeepZeroInline bool // 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. - // - // Deprecated: Use bson.Encoder.OmitZeroStruct instead. - EncodeOmitDefaultStruct bool + encodeOmitDefaultStruct bool // AllowUnexportedFields allows encoding and decoding values from un-exported struct fields. - // - // Deprecated: AllowUnexportedFields does not work on recent versions of Go and will not be - // supported in Go Driver 2.0. - AllowUnexportedFields bool + allowUnexportedFields bool // 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. - // - // Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates instead. - OverwriteDuplicatedInlinedFields bool + overwriteDuplicatedInlinedFields bool } -var _ ValueEncoder = &StructCodec{} -var _ ValueDecoder = &StructCodec{} - -// NewStructCodec returns a StructCodec that uses p for struct tag parsing. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// StructCodec registered. -func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) (*StructCodec, error) { - if p == nil { - return nil, errors.New("a StructTagParser must be provided to NewStructCodec") - } - - structOpt := bsonoptions.MergeStructCodecOptions(opts...) - - codec := &StructCodec{ - parser: p, - } +var ( + _ ValueEncoder = (*structCodec)(nil) + _ ValueDecoder = (*structCodec)(nil) +) - if structOpt.DecodeZeroStruct != nil { - codec.DecodeZeroStruct = *structOpt.DecodeZeroStruct - } - if structOpt.DecodeDeepZeroInline != nil { - codec.DecodeDeepZeroInline = *structOpt.DecodeDeepZeroInline - } - if structOpt.EncodeOmitDefaultStruct != nil { - codec.EncodeOmitDefaultStruct = *structOpt.EncodeOmitDefaultStruct - } - if structOpt.OverwriteDuplicatedInlinedFields != nil { - codec.OverwriteDuplicatedInlinedFields = *structOpt.OverwriteDuplicatedInlinedFields - } - if structOpt.AllowUnexportedFields != nil { - codec.AllowUnexportedFields = *structOpt.AllowUnexportedFields +// newStructCodec returns a StructCodec that uses p for struct tag parsing. +func newStructCodec(elemEncoder mapElementsEncoder) *structCodec { + return &structCodec{ + elemEncoder: elemEncoder, + overwriteDuplicatedInlinedFields: true, } - - return codec, nil } // EncodeValue handles encoding generic struct types. -func (sc *StructCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +func (sc *structCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Kind() != reflect.Struct { return ValueEncoderError{Name: "StructCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val} } @@ -153,7 +118,7 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect } } - desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(ec, desc.encoder, rv) + desc.encoder, rv, err = lookupElementEncoder(ec, desc.encoder, rv) if err != nil && !errors.Is(err, errInvalidValue) { return err @@ -188,7 +153,7 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect // nil interface separately. empty = rv.IsNil() } else { - empty = isEmpty(rv, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct) + empty = isEmpty(rv, sc.encodeOmitDefaultStruct || ec.omitZeroStruct) } if desc.omitEmpty && empty { continue @@ -216,14 +181,17 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect } } - if sd.inlineMap >= 0 { + if sd.inlineMap >= 0 && sc.elemEncoder != nil { rv := val.Field(sd.inlineMap) collisionFn := func(key string) bool { _, exists := sd.fm[key] return exists } - return defaultMapCodec.mapEncodeValue(ec, dw, rv, collisionFn) + err = sc.elemEncoder.encodeMapElements(ec, dw, rv, collisionFn) + if err != nil { + return err + } } return dw.WriteDocumentEnd() @@ -245,7 +213,7 @@ func newDecodeError(key string, original error) error { // DecodeValue implements the Codec interface. // By default, map types in val will not be cleared. If a map has existing key/value pairs, it will be extended with the new ones from vr. // For slices, the decoder will set the length of the slice to zero and append all elements. The underlying array will not be cleared. -func (sc *StructCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +func (sc *structCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Kind() != reflect.Struct { return ValueDecoderError{Name: "StructCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val} } @@ -275,10 +243,10 @@ func (sc *StructCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect return err } - if sc.DecodeZeroStruct || dc.zeroStructs { + if sc.decodeZeroStruct || dc.zeroStructs { val.Set(reflect.Zero(val.Type())) } - if sc.DecodeDeepZeroInline && sd.inline { + if sc.decodeDeepZeroInline && sd.inline { val.Set(deepZero(val.Type())) } @@ -461,7 +429,7 @@ func (bi byIndex) Less(i, j int) bool { return len(bi[i].inline) < len(bi[j].inline) } -func (sc *StructCodec) describeStruct( +func (sc *structCodec) describeStruct( r *Registry, t reflect.Type, useJSONStructTags bool, @@ -484,7 +452,7 @@ func (sc *StructCodec) describeStruct( return ds, nil } -func (sc *StructCodec) describeStructSlow( +func (sc *structCodec) describeStructSlow( r *Registry, t reflect.Type, useJSONStructTags bool, @@ -500,7 +468,7 @@ func (sc *StructCodec) describeStructSlow( var fields []fieldDescription for i := 0; i < numFields; i++ { sf := t.Field(i) - if sf.PkgPath != "" && (!sc.AllowUnexportedFields || !sf.Anonymous) { + if sf.PkgPath != "" && (!sc.allowUnexportedFields || !sf.Anonymous) { // field is private or unexported fields aren't allowed, ignore continue } @@ -522,13 +490,13 @@ func (sc *StructCodec) describeStructSlow( decoder: decoder, } - var stags StructTags + var stags *structTags // If the caller requested that we use JSON struct tags, use the JSONFallbackStructTagParser // instead of the parser defined on the codec. if useJSONStructTags { - stags, err = JSONFallbackStructTagParser.ParseStructTags(sf) + stags, err = parseJSONStructTags(sf) } else { - stags, err = sc.parser.ParseStructTags(sf) + stags, err = parseStructTags(sf) } if err != nil { return nil, err @@ -611,7 +579,7 @@ func (sc *StructCodec) describeStructSlow( continue } dominant, ok := dominantField(fields[i : i+advance]) - if !ok || !sc.OverwriteDuplicatedInlinedFields || errorOnDuplicates { + if !ok || !sc.overwriteDuplicatedInlinedFields || errorOnDuplicates { return nil, fmt.Errorf("struct %s has duplicated key %s", t.String(), name) } sd.fl = append(sd.fl, dominant) diff --git a/bson/struct_tag_parser.go b/bson/struct_tag_parser.go index d116c14040..26773a39e9 100644 --- a/bson/struct_tag_parser.go +++ b/bson/struct_tag_parser.go @@ -11,25 +11,7 @@ import ( "strings" ) -// StructTagParser returns the struct tags for a given struct field. -// -// Deprecated: Defining custom BSON struct tag parsers will not be supported in Go Driver 2.0. -type StructTagParser interface { - ParseStructTags(reflect.StructField) (StructTags, error) -} - -// StructTagParserFunc is an adapter that allows a generic function to be used -// as a StructTagParser. -// -// Deprecated: Defining custom BSON struct tag parsers will not be supported in Go Driver 2.0. -type StructTagParserFunc func(reflect.StructField) (StructTags, error) - -// ParseStructTags implements the StructTagParser interface. -func (stpf StructTagParserFunc) ParseStructTags(sf reflect.StructField) (StructTags, error) { - return stpf(sf) -} - -// StructTags represents the struct tag fields that the StructCodec uses during +// structTags represents the struct tag fields that the StructCodec uses during // the encoding and decoding process. // // In the case of a struct, the lowercased field name is used as the key for each exported @@ -55,7 +37,7 @@ func (stpf StructTagParserFunc) ParseStructTags(sf reflect.StructField) (StructT // for the name. // // Deprecated: Defining custom BSON struct tag parsers will not be supported in Go Driver 2.0. -type StructTags struct { +type structTags struct { Name string OmitEmpty bool MinSize bool @@ -89,9 +71,7 @@ type StructTags struct { // A struct tag either consisting entirely of '-' or with a bson key with a // value consisting entirely of '-' will return a StructTags with Skip true and // the remaining fields will be their default values. -// -// Deprecated: DefaultStructTagParser will be removed in Go Driver 2.0. -var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) { +func parseStructTags(sf reflect.StructField) (*structTags, error) { key := strings.ToLower(sf.Name) tag, ok := sf.Tag.Lookup("bson") if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 { @@ -100,11 +80,27 @@ var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (S return parseTags(key, tag) } -func parseTags(key string, tag string) (StructTags, error) { - var st StructTags +// jsonStructTagParser has the same behavior as DefaultStructTagParser +// but will also fallback to parsing the json tag instead on a field where the +// bson tag isn't available. +func parseJSONStructTags(sf reflect.StructField) (*structTags, error) { + key := strings.ToLower(sf.Name) + tag, ok := sf.Tag.Lookup("bson") + if !ok { + tag, ok = sf.Tag.Lookup("json") + } + if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 { + tag = string(sf.Tag) + } + + return parseTags(key, tag) +} + +func parseTags(key string, tag string) (*structTags, error) { + var st structTags if tag == "-" { st.Skip = true - return st, nil + return &st, nil } for idx, str := range strings.Split(tag, ",") { @@ -125,24 +121,5 @@ func parseTags(key string, tag string) (StructTags, error) { st.Name = key - return st, nil -} - -// JSONFallbackStructTagParser has the same behavior as DefaultStructTagParser -// but will also fallback to parsing the json tag instead on a field where the -// bson tag isn't available. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.Encoder.UseJSONStructTags] and -// [go.mongodb.org/mongo-driver/bson.Decoder.UseJSONStructTags] instead. -var JSONFallbackStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) { - key := strings.ToLower(sf.Name) - tag, ok := sf.Tag.Lookup("bson") - if !ok { - tag, ok = sf.Tag.Lookup("json") - } - if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 { - tag = string(sf.Tag) - } - - return parseTags(key, tag) + return &st, nil } diff --git a/bson/struct_tag_parser_test.go b/bson/struct_tag_parser_test.go index b03815488a..3592761e89 100644 --- a/bson/struct_tag_parser_test.go +++ b/bson/struct_tag_parser_test.go @@ -17,134 +17,134 @@ func TestStructTagParsers(t *testing.T) { testCases := []struct { name string sf reflect.StructField - want StructTags - parser StructTagParserFunc + want *structTags + parser func(reflect.StructField) (*structTags, error) }{ { "default no bson tag", reflect.StructField{Name: "foo", Tag: reflect.StructTag("bar")}, - StructTags{Name: "bar"}, - DefaultStructTagParser, + &structTags{Name: "bar"}, + parseStructTags, }, { "default empty", reflect.StructField{Name: "foo", Tag: reflect.StructTag("")}, - StructTags{Name: "foo"}, - DefaultStructTagParser, + &structTags{Name: "foo"}, + parseStructTags, }, { "default tag only dash", reflect.StructField{Name: "foo", Tag: reflect.StructTag("-")}, - StructTags{Skip: true}, - DefaultStructTagParser, + &structTags{Skip: true}, + parseStructTags, }, { "default bson tag only dash", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bson:"-"`)}, - StructTags{Skip: true}, - DefaultStructTagParser, + &structTags{Skip: true}, + parseStructTags, }, { "default all options", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bar,omitempty,minsize,truncate,inline`)}, - StructTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - DefaultStructTagParser, + &structTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseStructTags, }, { "default all options default name", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`,omitempty,minsize,truncate,inline`)}, - StructTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - DefaultStructTagParser, + &structTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseStructTags, }, { "default bson tag all options", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bson:"bar,omitempty,minsize,truncate,inline"`)}, - StructTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - DefaultStructTagParser, + &structTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseStructTags, }, { "default bson tag all options default name", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bson:",omitempty,minsize,truncate,inline"`)}, - StructTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - DefaultStructTagParser, + &structTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseStructTags, }, { "default ignore xml", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`xml:"bar"`)}, - StructTags{Name: "foo"}, - DefaultStructTagParser, + &structTags{Name: "foo"}, + parseStructTags, }, { "JSONFallback no bson tag", reflect.StructField{Name: "foo", Tag: reflect.StructTag("bar")}, - StructTags{Name: "bar"}, - JSONFallbackStructTagParser, + &structTags{Name: "bar"}, + parseStructTags, }, { "JSONFallback empty", reflect.StructField{Name: "foo", Tag: reflect.StructTag("")}, - StructTags{Name: "foo"}, - JSONFallbackStructTagParser, + &structTags{Name: "foo"}, + parseJSONStructTags, }, { "JSONFallback tag only dash", reflect.StructField{Name: "foo", Tag: reflect.StructTag("-")}, - StructTags{Skip: true}, - JSONFallbackStructTagParser, + &structTags{Skip: true}, + parseJSONStructTags, }, { "JSONFallback bson tag only dash", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bson:"-"`)}, - StructTags{Skip: true}, - JSONFallbackStructTagParser, + &structTags{Skip: true}, + parseJSONStructTags, }, { "JSONFallback all options", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bar,omitempty,minsize,truncate,inline`)}, - StructTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - JSONFallbackStructTagParser, + &structTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseJSONStructTags, }, { "JSONFallback all options default name", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`,omitempty,minsize,truncate,inline`)}, - StructTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - JSONFallbackStructTagParser, + &structTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseJSONStructTags, }, { "JSONFallback bson tag all options", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bson:"bar,omitempty,minsize,truncate,inline"`)}, - StructTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - JSONFallbackStructTagParser, + &structTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseJSONStructTags, }, { "JSONFallback bson tag all options default name", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bson:",omitempty,minsize,truncate,inline"`)}, - StructTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - JSONFallbackStructTagParser, + &structTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseJSONStructTags, }, { "JSONFallback json tag all options", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`json:"bar,omitempty,minsize,truncate,inline"`)}, - StructTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - JSONFallbackStructTagParser, + &structTags{Name: "bar", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseJSONStructTags, }, { "JSONFallback json tag all options default name", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`json:",omitempty,minsize,truncate,inline"`)}, - StructTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, - JSONFallbackStructTagParser, + &structTags{Name: "foo", OmitEmpty: true, MinSize: true, Truncate: true, Inline: true}, + parseJSONStructTags, }, { "JSONFallback bson tag overrides other tags", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`bson:"bar" json:"qux,truncate"`)}, - StructTags{Name: "bar"}, - JSONFallbackStructTagParser, + &structTags{Name: "bar"}, + parseJSONStructTags, }, { "JSONFallback ignore xml", reflect.StructField{Name: "foo", Tag: reflect.StructTag(`xml:"bar"`)}, - StructTags{Name: "foo"}, - JSONFallbackStructTagParser, + &structTags{Name: "foo"}, + parseJSONStructTags, }, } diff --git a/bson/time_codec.go b/bson/time_codec.go index a168d1e769..6bd3653579 100644 --- a/bson/time_codec.go +++ b/bson/time_codec.go @@ -10,48 +10,25 @@ import ( "fmt" "reflect" "time" - - "go.mongodb.org/mongo-driver/bson/bsonoptions" ) const ( timeFormatString = "2006-01-02T15:04:05.999Z07:00" ) -// TimeCodec is the Codec used for time.Time values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// TimeCodec registered. -type TimeCodec struct { - // UseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false. - // - // Deprecated: Use bson.Decoder.UseLocalTimeZone instead. - UseLocalTimeZone bool +// timeCodec is the Codec used for time.Time values. +type timeCodec struct { + // useLocalTimeZone specifies if we should decode into the local time zone. Defaults to false. + useLocalTimeZone bool } var ( - defaultTimeCodec = NewTimeCodec() - - // Assert that defaultTimeCodec satisfies the typeDecoder interface, which allows it to be used + // Assert that timeCodec satisfies the typeDecoder interface, which allows it to be used // by collection type decoders (e.g. map, slice, etc) to set individual values in a collection. - _ typeDecoder = defaultTimeCodec + _ typeDecoder = (*timeCodec)(nil) ) -// NewTimeCodec returns a TimeCodec with options opts. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// TimeCodec registered. -func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec { - timeOpt := bsonoptions.MergeTimeCodecOptions(opts...) - - codec := TimeCodec{} - if timeOpt.UseLocalTimeZone != nil { - codec.UseLocalTimeZone = *timeOpt.UseLocalTimeZone - } - return &codec -} - -func (tc *TimeCodec) decodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func (tc *timeCodec) decodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { if t != tTime { return emptyValue, ValueDecoderError{ Name: "TimeDecodeValue", @@ -102,14 +79,14 @@ func (tc *TimeCodec) decodeType(dc DecodeContext, vr ValueReader, t reflect.Type return emptyValue, fmt.Errorf("cannot decode %v into a time.Time", vrType) } - if !tc.UseLocalTimeZone && !dc.useLocalTimeZone { + if !tc.useLocalTimeZone && !dc.useLocalTimeZone { timeVal = timeVal.UTC() } return reflect.ValueOf(timeVal), nil } // DecodeValue is the ValueDecoderFunc for time.Time. -func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +func (tc *timeCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() || val.Type() != tTime { return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val} } @@ -124,7 +101,7 @@ func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.V } // EncodeValue is the ValueEncoderFunc for time.TIme. -func (tc *TimeCodec) EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { +func (tc *timeCodec) EncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error { if !val.IsValid() || val.Type() != tTime { return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val} } diff --git a/bson/time_codec_test.go b/bson/time_codec_test.go index 1f185692da..1bb35bafd3 100644 --- a/bson/time_codec_test.go +++ b/bson/time_codec_test.go @@ -11,7 +11,6 @@ import ( "testing" "time" - "go.mongodb.org/mongo-driver/bson/bsonoptions" "go.mongodb.org/mongo-driver/internal/assert" "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" ) @@ -22,20 +21,18 @@ func TestTimeCodec(t *testing.T) { t.Run("UseLocalTimeZone", func(t *testing.T) { reader := &valueReaderWriter{BSONType: TypeDateTime, Return: now.UnixNano() / int64(time.Millisecond)} testCases := []struct { - name string - opts *bsonoptions.TimeCodecOptions - utc bool + name string + timeCodec *timeCodec + utc bool }{ - {"default", bsonoptions.TimeCodec(), true}, - {"false", bsonoptions.TimeCodec().SetUseLocalTimeZone(false), true}, - {"true", bsonoptions.TimeCodec().SetUseLocalTimeZone(true), false}, + {"default", &timeCodec{}, true}, + {"false", &timeCodec{useLocalTimeZone: false}, true}, + {"true", &timeCodec{useLocalTimeZone: true}, false}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - timeCodec := NewTimeCodec(tc.opts) - actual := reflect.New(reflect.TypeOf(now)).Elem() - err := timeCodec.DecodeValue(DecodeContext{}, reader, actual) + err := tc.timeCodec.DecodeValue(DecodeContext{}, reader, actual) assert.Nil(t, err, "TimeCodec.DecodeValue error: %v", err) actualTime := actual.Interface().(time.Time) @@ -69,7 +66,7 @@ func TestTimeCodec(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { actual := reflect.New(reflect.TypeOf(now)).Elem() - err := defaultTimeCodec.DecodeValue(DecodeContext{}, tc.reader, actual) + err := (&timeCodec{}).DecodeValue(DecodeContext{}, tc.reader, actual) assert.Nil(t, err, "DecodeValue error: %v", err) actualTime := actual.Interface().(time.Time) diff --git a/bson/uint_codec.go b/bson/uint_codec.go index 73bc01966e..9650862834 100644 --- a/bson/uint_codec.go +++ b/bson/uint_codec.go @@ -10,46 +10,23 @@ import ( "fmt" "math" "reflect" - - "go.mongodb.org/mongo-driver/bson/bsonoptions" ) -// UIntCodec is the Codec used for uint values. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// UIntCodec registered. -type UIntCodec struct { - // EncodeToMinSize causes EncodeValue to marshal Go uint values (excluding uint64) as the +// uintCodec is the Codec used for uint values. +type uintCodec struct { + // encodeToMinSize causes EncodeValue to marshal Go uint values (excluding uint64) as the // minimum BSON int size (either 32-bit or 64-bit) that can represent the integer value. - // - // Deprecated: Use bson.Encoder.IntMinSize instead. - EncodeToMinSize bool + encodeToMinSize bool } var ( - defaultUIntCodec = NewUIntCodec() - - // Assert that defaultUIntCodec satisfies the typeDecoder interface, which allows it to be used + // Assert that uintCodec satisfies the typeDecoder interface, which allows it to be used // by collection type decoders (e.g. map, slice, etc) to set individual values in a collection. - _ typeDecoder = defaultUIntCodec + _ typeDecoder = (*uintCodec)(nil) ) -// NewUIntCodec returns a UIntCodec with options opts. -// -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// UIntCodec registered. -func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec { - uintOpt := bsonoptions.MergeUIntCodecOptions(opts...) - - codec := UIntCodec{} - if uintOpt.EncodeToMinSize != nil { - codec.EncodeToMinSize = *uintOpt.EncodeToMinSize - } - return &codec -} - // EncodeValue is the ValueEncoder for uint types. -func (uic *UIntCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { +func (uic *uintCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Value) error { switch val.Kind() { case reflect.Uint8, reflect.Uint16: return vw.WriteInt32(int32(val.Uint())) @@ -57,7 +34,7 @@ func (uic *UIntCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect. u64 := val.Uint() // If ec.MinSize or if encodeToMinSize is true for a non-uint64 value we should write val as an int32 - useMinSize := ec.MinSize || (uic.EncodeToMinSize && val.Kind() != reflect.Uint64) + useMinSize := ec.MinSize || (uic.encodeToMinSize && val.Kind() != reflect.Uint64) if u64 <= math.MaxInt32 && useMinSize { return vw.WriteInt32(int32(u64)) @@ -75,7 +52,7 @@ func (uic *UIntCodec) EncodeValue(ec EncodeContext, vw ValueWriter, val reflect. } } -func (uic *UIntCodec) decodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { +func (uic *uintCodec) decodeType(dc DecodeContext, vr ValueReader, t reflect.Type) (reflect.Value, error) { var i64 int64 var err error switch vrType := vr.Type(); vrType { @@ -163,7 +140,7 @@ func (uic *UIntCodec) decodeType(dc DecodeContext, vr ValueReader, t reflect.Typ } // DecodeValue is the ValueDecoder for uint types. -func (uic *UIntCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { +func (uic *uintCodec) DecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error { if !val.CanSet() { return ValueDecoderError{ Name: "UintDecodeValue", diff --git a/bson/unmarshal_value_test.go b/bson/unmarshal_value_test.go index 8d9dfb5351..fd379b5daa 100644 --- a/bson/unmarshal_value_test.go +++ b/bson/unmarshal_value_test.go @@ -76,7 +76,7 @@ func TestUnmarshalValue(t *testing.T) { }, } reg := NewRegistry() - reg.RegisterTypeDecoder(reflect.TypeOf([]byte{}), NewSliceCodec()) + reg.RegisterTypeDecoder(reflect.TypeOf([]byte{}), &sliceCodec{}) for _, tc := range testCases { tc := tc @@ -111,7 +111,7 @@ func BenchmarkSliceCodecUnmarshal(b *testing.B) { }, } reg := NewRegistry() - reg.RegisterTypeDecoder(reflect.TypeOf([]byte{}), NewSliceCodec()) + reg.RegisterTypeDecoder(reflect.TypeOf([]byte{}), &sliceCodec{}) for _, bm := range benchmarks { b.Run(bm.name, func(b *testing.B) { b.RunParallel(func(pb *testing.PB) {