summaryrefslogtreecommitdiff
path: root/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/go.mongodb.org/mongo-driver/bson/bsoncodec')
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go50
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go238
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go111
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go63
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go1729
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go766
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go90
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go147
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go309
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go65
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go109
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go14
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go469
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go199
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go119
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go664
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go139
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go127
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go57
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go173
20 files changed, 5638 insertions, 0 deletions
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go
new file mode 100644
index 000000000..4e24f9eed
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go
@@ -0,0 +1,50 @@
+// 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 bsoncodec
+
+import (
+ "reflect"
+
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
+)
+
+// ArrayCodec is the Codec used for bsoncore.Array values.
+type ArrayCodec struct{}
+
+var defaultArrayCodec = NewArrayCodec()
+
+// NewArrayCodec returns an ArrayCodec.
+func NewArrayCodec() *ArrayCodec {
+ return &ArrayCodec{}
+}
+
+// EncodeValue is the ValueEncoder for bsoncore.Array values.
+func (ac *ArrayCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tCoreArray {
+ return ValueEncoderError{Name: "CoreArrayEncodeValue", Types: []reflect.Type{tCoreArray}, Received: val}
+ }
+
+ arr := val.Interface().(bsoncore.Array)
+ return bsonrw.Copier{}.CopyArrayFromBytes(vw, arr)
+}
+
+// DecodeValue is the ValueDecoder for bsoncore.Array values.
+func (ac *ArrayCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tCoreArray {
+ return ValueDecoderError{Name: "CoreArrayDecodeValue", Types: []reflect.Type{tCoreArray}, Received: val}
+ }
+
+ if val.IsNil() {
+ val.Set(reflect.MakeSlice(val.Type(), 0, 0))
+ }
+
+ val.SetLen(0)
+ arr, err := bsonrw.Copier{}.AppendArrayBytes(val.Interface().(bsoncore.Array), vr)
+ val.Set(reflect.ValueOf(arr))
+ return err
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go
new file mode 100644
index 000000000..098ed69f9
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go
@@ -0,0 +1,238 @@
+// 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 bsoncodec // import "go.mongodb.org/mongo-driver/bson/bsoncodec"
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+var (
+ emptyValue = reflect.Value{}
+)
+
+// Marshaler is an interface implemented by types that can marshal themselves
+// into a BSON document represented as bytes. The bytes returned must be a valid
+// BSON document if the error is nil.
+type Marshaler interface {
+ MarshalBSON() ([]byte, error)
+}
+
+// ValueMarshaler is an interface implemented by types that can marshal
+// themselves into a BSON value as bytes. The type must be the valid type for
+// the bytes returned. The bytes and byte type together must be valid if the
+// error is nil.
+type ValueMarshaler interface {
+ MarshalBSONValue() (bsontype.Type, []byte, error)
+}
+
+// Unmarshaler is an interface implemented by types that can unmarshal a BSON
+// document representation of themselves. The BSON bytes can be assumed to be
+// valid. UnmarshalBSON must copy the BSON bytes if it wishes to retain the data
+// after returning.
+type Unmarshaler interface {
+ UnmarshalBSON([]byte) error
+}
+
+// ValueUnmarshaler is an interface implemented by types that can unmarshal a
+// BSON value representation of themselves. The BSON bytes and type can be
+// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it
+// wishes to retain the data after returning.
+type ValueUnmarshaler interface {
+ UnmarshalBSONValue(bsontype.Type, []byte) error
+}
+
+// ValueEncoderError is an error returned from a ValueEncoder when the provided value can't be
+// encoded by the ValueEncoder.
+type ValueEncoderError struct {
+ Name string
+ Types []reflect.Type
+ Kinds []reflect.Kind
+ Received reflect.Value
+}
+
+func (vee ValueEncoderError) Error() string {
+ typeKinds := make([]string, 0, len(vee.Types)+len(vee.Kinds))
+ for _, t := range vee.Types {
+ typeKinds = append(typeKinds, t.String())
+ }
+ for _, k := range vee.Kinds {
+ if k == reflect.Map {
+ typeKinds = append(typeKinds, "map[string]*")
+ continue
+ }
+ typeKinds = append(typeKinds, k.String())
+ }
+ received := vee.Received.Kind().String()
+ if vee.Received.IsValid() {
+ received = vee.Received.Type().String()
+ }
+ return fmt.Sprintf("%s can only encode valid %s, but got %s", vee.Name, strings.Join(typeKinds, ", "), received)
+}
+
+// ValueDecoderError is an error returned from a ValueDecoder when the provided value can't be
+// decoded by the ValueDecoder.
+type ValueDecoderError struct {
+ Name string
+ Types []reflect.Type
+ Kinds []reflect.Kind
+ Received reflect.Value
+}
+
+func (vde ValueDecoderError) Error() string {
+ typeKinds := make([]string, 0, len(vde.Types)+len(vde.Kinds))
+ for _, t := range vde.Types {
+ typeKinds = append(typeKinds, t.String())
+ }
+ for _, k := range vde.Kinds {
+ if k == reflect.Map {
+ typeKinds = append(typeKinds, "map[string]*")
+ continue
+ }
+ typeKinds = append(typeKinds, k.String())
+ }
+ received := vde.Received.Kind().String()
+ if vde.Received.IsValid() {
+ received = vde.Received.Type().String()
+ }
+ return fmt.Sprintf("%s can only decode valid and settable %s, but got %s", vde.Name, strings.Join(typeKinds, ", "), received)
+}
+
+// EncodeContext is the contextual information required for a Codec to encode a
+// value.
+type EncodeContext struct {
+ *Registry
+ MinSize bool
+}
+
+// DecodeContext is the contextual information required for a Codec to decode a
+// value.
+type DecodeContext struct {
+ *Registry
+ Truncate bool
+
+ // Ancestor is the type of a containing document. This is mainly used to determine what type
+ // should be used when decoding an embedded document into an empty interface. For example, if
+ // Ancestor is a bson.M, BSON embedded document values being decoded into an empty interface
+ // will be decoded into a bson.M.
+ //
+ // Deprecated: Use DefaultDocumentM or DefaultDocumentD instead.
+ Ancestor reflect.Type
+
+ // defaultDocumentType specifies the Go type to decode top-level and nested BSON documents into. In particular, the
+ // usage for this field is restricted to data typed as "interface{}" or "map[string]interface{}". If DocumentType is
+ // set to a type that a BSON document cannot be unmarshaled into (e.g. "string"), unmarshalling will result in an
+ // error. DocumentType overrides the Ancestor field.
+ defaultDocumentType reflect.Type
+}
+
+// DefaultDocumentM will decode empty documents using the primitive.M type. This behavior is restricted to data typed as
+// "interface{}" or "map[string]interface{}".
+func (dc *DecodeContext) DefaultDocumentM() {
+ dc.defaultDocumentType = reflect.TypeOf(primitive.M{})
+}
+
+// DefaultDocumentD will decode empty documents using the primitive.D type. This behavior is restricted to data typed as
+// "interface{}" or "map[string]interface{}".
+func (dc *DecodeContext) DefaultDocumentD() {
+ dc.defaultDocumentType = reflect.TypeOf(primitive.D{})
+}
+
+// ValueCodec is the interface that groups the methods to encode and decode
+// values.
+type ValueCodec interface {
+ ValueEncoder
+ ValueDecoder
+}
+
+// ValueEncoder is the interface implemented by types that can handle the encoding of a value.
+type ValueEncoder interface {
+ EncodeValue(EncodeContext, bsonrw.ValueWriter, reflect.Value) error
+}
+
+// ValueEncoderFunc is an adapter function that allows a function with the correct signature to be
+// used as a ValueEncoder.
+type ValueEncoderFunc func(EncodeContext, bsonrw.ValueWriter, reflect.Value) error
+
+// EncodeValue implements the ValueEncoder interface.
+func (fn ValueEncoderFunc) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ return fn(ec, vw, val)
+}
+
+// ValueDecoder is the interface implemented by types that can handle the decoding of a value.
+type ValueDecoder interface {
+ DecodeValue(DecodeContext, bsonrw.ValueReader, reflect.Value) error
+}
+
+// ValueDecoderFunc is an adapter function that allows a function with the correct signature to be
+// used as a ValueDecoder.
+type ValueDecoderFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) error
+
+// DecodeValue implements the ValueDecoder interface.
+func (fn ValueDecoderFunc) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ return fn(dc, vr, val)
+}
+
+// typeDecoder is the interface implemented by types that can handle the decoding of a value given its type.
+type typeDecoder interface {
+ decodeType(DecodeContext, bsonrw.ValueReader, reflect.Type) (reflect.Value, error)
+}
+
+// typeDecoderFunc is an adapter function that allows a function with the correct signature to be used as a typeDecoder.
+type typeDecoderFunc func(DecodeContext, bsonrw.ValueReader, reflect.Type) (reflect.Value, error)
+
+func (fn typeDecoderFunc) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ return fn(dc, vr, t)
+}
+
+// decodeAdapter allows two functions with the correct signatures to be used as both a ValueDecoder and typeDecoder.
+type decodeAdapter struct {
+ ValueDecoderFunc
+ typeDecoderFunc
+}
+
+var _ ValueDecoder = decodeAdapter{}
+var _ typeDecoder = decodeAdapter{}
+
+// decodeTypeOrValue calls decoder.decodeType is decoder is a typeDecoder. Otherwise, it allocates a new element of type
+// t and calls decoder.DecodeValue on it.
+func decodeTypeOrValue(decoder ValueDecoder, dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ td, _ := decoder.(typeDecoder)
+ return decodeTypeOrValueWithInfo(decoder, td, dc, vr, t, true)
+}
+
+func decodeTypeOrValueWithInfo(vd ValueDecoder, td typeDecoder, dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type, convert bool) (reflect.Value, error) {
+ if td != nil {
+ val, err := td.decodeType(dc, vr, t)
+ if err == nil && convert && val.Type() != t {
+ // This conversion step is necessary for slices and maps. If a user declares variables like:
+ //
+ // type myBool bool
+ // var m map[string]myBool
+ //
+ // and tries to decode BSON bytes into the map, the decoding will fail if this conversion is not present
+ // because we'll try to assign a value of type bool to one of type myBool.
+ val = val.Convert(t)
+ }
+ return val, err
+ }
+
+ val := reflect.New(t).Elem()
+ err := vd.DecodeValue(dc, vr, val)
+ return val, err
+}
+
+// CodecZeroer is the interface implemented by Codecs that can also determine if
+// a value of the type that would be encoded is zero.
+type CodecZeroer interface {
+ IsTypeZero(interface{}) bool
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go
new file mode 100644
index 000000000..5a916cc15
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go
@@ -0,0 +1,111 @@
+// 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 bsoncodec
+
+import (
+ "fmt"
+ "reflect"
+
+ "go.mongodb.org/mongo-driver/bson/bsonoptions"
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+)
+
+// ByteSliceCodec is the Codec used for []byte values.
+type ByteSliceCodec struct {
+ EncodeNilAsEmpty bool
+}
+
+var (
+ defaultByteSliceCodec = NewByteSliceCodec()
+
+ _ ValueCodec = defaultByteSliceCodec
+ _ typeDecoder = defaultByteSliceCodec
+)
+
+// NewByteSliceCodec returns a StringCodec with options opts.
+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 bsonrw.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 {
+ return vw.WriteNull()
+ }
+ return vw.WriteBinary(val.Interface().([]byte))
+}
+
+func (bsc *ByteSliceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tByteSlice {
+ return emptyValue, ValueDecoderError{
+ Name: "ByteSliceDecodeValue",
+ Types: []reflect.Type{tByteSlice},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var data []byte
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.String:
+ str, err := vr.ReadString()
+ if err != nil {
+ return emptyValue, err
+ }
+ data = []byte(str)
+ case bsontype.Symbol:
+ sym, err := vr.ReadSymbol()
+ if err != nil {
+ return emptyValue, err
+ }
+ data = []byte(sym)
+ case bsontype.Binary:
+ var subtype byte
+ data, subtype, err = vr.ReadBinary()
+ if err != nil {
+ return emptyValue, err
+ }
+ if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
+ return emptyValue, decodeBinaryError{subtype: subtype, typeName: "[]byte"}
+ }
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a []byte", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(data), nil
+}
+
+// DecodeValue is the ValueDecoder for []byte.
+func (bsc *ByteSliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tByteSlice {
+ return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val}
+ }
+
+ elem, err := bsc.decodeType(dc, vr, tByteSlice)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go
new file mode 100644
index 000000000..cb8180f25
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go
@@ -0,0 +1,63 @@
+// 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 bsoncodec
+
+import (
+ "reflect"
+
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+)
+
+// condAddrEncoder is the encoder used when a pointer to the encoding value has an encoder.
+type condAddrEncoder struct {
+ canAddrEnc ValueEncoder
+ elseEnc ValueEncoder
+}
+
+var _ ValueEncoder = (*condAddrEncoder)(nil)
+
+// newCondAddrEncoder returns an condAddrEncoder.
+func newCondAddrEncoder(canAddrEnc, elseEnc ValueEncoder) *condAddrEncoder {
+ encoder := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
+ return &encoder
+}
+
+// EncodeValue is the ValueEncoderFunc for a value that may be addressable.
+func (cae *condAddrEncoder) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if val.CanAddr() {
+ return cae.canAddrEnc.EncodeValue(ec, vw, val)
+ }
+ if cae.elseEnc != nil {
+ return cae.elseEnc.EncodeValue(ec, vw, val)
+ }
+ return ErrNoEncoder{Type: val.Type()}
+}
+
+// condAddrDecoder is the decoder used when a pointer to the value has a decoder.
+type condAddrDecoder struct {
+ canAddrDec ValueDecoder
+ elseDec ValueDecoder
+}
+
+var _ ValueDecoder = (*condAddrDecoder)(nil)
+
+// newCondAddrDecoder returns an CondAddrDecoder.
+func newCondAddrDecoder(canAddrDec, elseDec ValueDecoder) *condAddrDecoder {
+ decoder := condAddrDecoder{canAddrDec: canAddrDec, elseDec: elseDec}
+ return &decoder
+}
+
+// DecodeValue is the ValueDecoderFunc for a value that may be addressable.
+func (cad *condAddrDecoder) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if val.CanAddr() {
+ return cad.canAddrDec.DecodeValue(dc, vr, val)
+ }
+ if cad.elseDec != nil {
+ return cad.elseDec.DecodeValue(dc, vr, val)
+ }
+ return ErrNoDecoder{Type: val.Type()}
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go
new file mode 100644
index 000000000..e95cab585
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go
@@ -0,0 +1,1729 @@
+// 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 bsoncodec
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math"
+ "net/url"
+ "reflect"
+ "strconv"
+ "time"
+
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+ "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
+)
+
+var (
+ defaultValueDecoders DefaultValueDecoders
+ errCannotTruncate = errors.New("float64 can only be truncated to an integer type when truncation is enabled")
+)
+
+type decodeBinaryError struct {
+ subtype byte
+ typeName string
+}
+
+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: %v", err))
+ }
+ return codec
+}
+
+// DefaultValueDecoders is a namespace type for the default ValueDecoders used
+// when creating a registry.
+type DefaultValueDecoders struct{}
+
+// 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.
+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(bsontype.Double, tFloat64).
+ RegisterTypeMapEntry(bsontype.String, tString).
+ RegisterTypeMapEntry(bsontype.Array, tA).
+ RegisterTypeMapEntry(bsontype.Binary, tBinary).
+ RegisterTypeMapEntry(bsontype.Undefined, tUndefined).
+ RegisterTypeMapEntry(bsontype.ObjectID, tOID).
+ RegisterTypeMapEntry(bsontype.Boolean, tBool).
+ RegisterTypeMapEntry(bsontype.DateTime, tDateTime).
+ RegisterTypeMapEntry(bsontype.Regex, tRegex).
+ RegisterTypeMapEntry(bsontype.DBPointer, tDBPointer).
+ RegisterTypeMapEntry(bsontype.JavaScript, tJavaScript).
+ RegisterTypeMapEntry(bsontype.Symbol, tSymbol).
+ RegisterTypeMapEntry(bsontype.CodeWithScope, tCodeWithScope).
+ RegisterTypeMapEntry(bsontype.Int32, tInt32).
+ RegisterTypeMapEntry(bsontype.Int64, tInt64).
+ RegisterTypeMapEntry(bsontype.Timestamp, tTimestamp).
+ RegisterTypeMapEntry(bsontype.Decimal128, tDecimal).
+ RegisterTypeMapEntry(bsontype.MinKey, tMinKey).
+ RegisterTypeMapEntry(bsontype.MaxKey, tMaxKey).
+ RegisterTypeMapEntry(bsontype.Type(0), tD).
+ RegisterTypeMapEntry(bsontype.EmbeddedDocument, tD).
+ RegisterHookDecoder(tValueUnmarshaler, ValueDecoderFunc(dvd.ValueUnmarshalerDecodeValue)).
+ RegisterHookDecoder(tUnmarshaler, ValueDecoderFunc(dvd.UnmarshalerDecodeValue))
+}
+
+// DDecodeValue is the ValueDecoderFunc for primitive.D instances.
+func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.IsValid() || !val.CanSet() || val.Type() != tD {
+ return ValueDecoderError{Name: "DDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val}
+ }
+
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Type(0), bsontype.EmbeddedDocument:
+ dc.Ancestor = tD
+ case bsontype.Null:
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadNull()
+ default:
+ return fmt.Errorf("cannot decode %v into a primitive.D", vrType)
+ }
+
+ dr, err := vr.ReadDocument()
+ if err != nil {
+ return err
+ }
+
+ decoder, err := dc.LookupDecoder(tEmpty)
+ if err != nil {
+ return err
+ }
+ tEmptyTypeDecoder, _ := decoder.(typeDecoder)
+
+ // Use the elements in the provided value if it's non nil. Otherwise, allocate a new D instance.
+ var elems primitive.D
+ if !val.IsNil() {
+ val.SetLen(0)
+ elems = val.Interface().(primitive.D)
+ } else {
+ elems = make(primitive.D, 0)
+ }
+
+ for {
+ key, elemVr, err := dr.ReadElement()
+ if err == bsonrw.ErrEOD {
+ break
+ } else if err != nil {
+ return err
+ }
+
+ // Pass false for convert because we don't need to call reflect.Value.Convert for tEmpty.
+ elem, err := decodeTypeOrValueWithInfo(decoder, tEmptyTypeDecoder, dc, elemVr, tEmpty, false)
+ if err != nil {
+ return err
+ }
+
+ elems = append(elems, primitive.E{Key: key, Value: elem.Interface()})
+ }
+
+ val.Set(reflect.ValueOf(elems))
+ return nil
+}
+
+func (dvd DefaultValueDecoders) booleanDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t.Kind() != reflect.Bool {
+ return emptyValue, ValueDecoderError{
+ Name: "BooleanDecodeValue",
+ Kinds: []reflect.Kind{reflect.Bool},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var b bool
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Int32:
+ i32, err := vr.ReadInt32()
+ if err != nil {
+ return emptyValue, err
+ }
+ b = (i32 != 0)
+ case bsontype.Int64:
+ i64, err := vr.ReadInt64()
+ if err != nil {
+ return emptyValue, err
+ }
+ b = (i64 != 0)
+ case bsontype.Double:
+ f64, err := vr.ReadDouble()
+ if err != nil {
+ return emptyValue, err
+ }
+ b = (f64 != 0)
+ case bsontype.Boolean:
+ b, err = vr.ReadBoolean()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a boolean", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(b), nil
+}
+
+// BooleanDecodeValue is the ValueDecoderFunc for bool types.
+func (dvd DefaultValueDecoders) BooleanDecodeValue(dctx DecodeContext, vr bsonrw.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())
+ if err != nil {
+ return err
+ }
+
+ val.SetBool(elem.Bool())
+ return nil
+}
+
+func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ var i64 int64
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Int32:
+ i32, err := vr.ReadInt32()
+ if err != nil {
+ return emptyValue, err
+ }
+ i64 = int64(i32)
+ case bsontype.Int64:
+ i64, err = vr.ReadInt64()
+ if err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Double:
+ f64, err := vr.ReadDouble()
+ if err != nil {
+ return emptyValue, err
+ }
+ if !dc.Truncate && math.Floor(f64) != f64 {
+ return emptyValue, errCannotTruncate
+ }
+ if f64 > float64(math.MaxInt64) {
+ return emptyValue, fmt.Errorf("%g overflows int64", f64)
+ }
+ i64 = int64(f64)
+ case bsontype.Boolean:
+ b, err := vr.ReadBoolean()
+ if err != nil {
+ return emptyValue, err
+ }
+ if b {
+ i64 = 1
+ }
+ case bsontype.Null:
+ if err = vr.ReadNull(); err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Undefined:
+ if err = vr.ReadUndefined(); err != nil {
+ return emptyValue, err
+ }
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType)
+ }
+
+ switch t.Kind() {
+ case reflect.Int8:
+ if i64 < math.MinInt8 || i64 > math.MaxInt8 {
+ return emptyValue, fmt.Errorf("%d overflows int8", i64)
+ }
+
+ return reflect.ValueOf(int8(i64)), nil
+ case reflect.Int16:
+ if i64 < math.MinInt16 || i64 > math.MaxInt16 {
+ return emptyValue, fmt.Errorf("%d overflows int16", i64)
+ }
+
+ return reflect.ValueOf(int16(i64)), nil
+ case reflect.Int32:
+ if i64 < math.MinInt32 || i64 > math.MaxInt32 {
+ return emptyValue, fmt.Errorf("%d overflows int32", i64)
+ }
+
+ return reflect.ValueOf(int32(i64)), nil
+ case reflect.Int64:
+ return reflect.ValueOf(i64), nil
+ case reflect.Int:
+ if int64(int(i64)) != i64 { // Can we fit this inside of an int
+ return emptyValue, fmt.Errorf("%d overflows int", i64)
+ }
+
+ return reflect.ValueOf(int(i64)), nil
+ default:
+ return emptyValue, ValueDecoderError{
+ Name: "IntDecodeValue",
+ Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
+ Received: reflect.Zero(t),
+ }
+ }
+}
+
+// IntDecodeValue is the ValueDecoderFunc for int types.
+func (dvd DefaultValueDecoders) IntDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() {
+ return ValueDecoderError{
+ Name: "IntDecodeValue",
+ Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
+ Received: val,
+ }
+ }
+
+ elem, err := dvd.intDecodeType(dc, vr, val.Type())
+ if err != nil {
+ return err
+ }
+
+ val.SetInt(elem.Int())
+ 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 bsonrw.ValueReader, val reflect.Value) error {
+ var i64 int64
+ var err error
+ switch vr.Type() {
+ case bsontype.Int32:
+ i32, err := vr.ReadInt32()
+ if err != nil {
+ return err
+ }
+ i64 = int64(i32)
+ case bsontype.Int64:
+ i64, err = vr.ReadInt64()
+ if err != nil {
+ return err
+ }
+ case bsontype.Double:
+ 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 bsontype.Boolean:
+ 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(ec DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ var f float64
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Int32:
+ i32, err := vr.ReadInt32()
+ if err != nil {
+ return emptyValue, err
+ }
+ f = float64(i32)
+ case bsontype.Int64:
+ i64, err := vr.ReadInt64()
+ if err != nil {
+ return emptyValue, err
+ }
+ f = float64(i64)
+ case bsontype.Double:
+ f, err = vr.ReadDouble()
+ if err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Boolean:
+ b, err := vr.ReadBoolean()
+ if err != nil {
+ return emptyValue, err
+ }
+ if b {
+ f = 1
+ }
+ case bsontype.Null:
+ if err = vr.ReadNull(); err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Undefined:
+ if err = vr.ReadUndefined(); err != nil {
+ return emptyValue, err
+ }
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a float32 or float64 type", vrType)
+ }
+
+ switch t.Kind() {
+ case reflect.Float32:
+ if !ec.Truncate && float64(float32(f)) != f {
+ return emptyValue, errCannotTruncate
+ }
+
+ return reflect.ValueOf(float32(f)), nil
+ case reflect.Float64:
+ return reflect.ValueOf(f), nil
+ default:
+ return emptyValue, ValueDecoderError{
+ Name: "FloatDecodeValue",
+ Kinds: []reflect.Kind{reflect.Float32, reflect.Float64},
+ Received: reflect.Zero(t),
+ }
+ }
+}
+
+// FloatDecodeValue is the ValueDecoderFunc for float types.
+func (dvd DefaultValueDecoders) FloatDecodeValue(ec DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() {
+ return ValueDecoderError{
+ Name: "FloatDecodeValue",
+ Kinds: []reflect.Kind{reflect.Float32, reflect.Float64},
+ Received: val,
+ }
+ }
+
+ elem, err := dvd.floatDecodeType(ec, vr, val.Type())
+ if err != nil {
+ return err
+ }
+
+ val.SetFloat(elem.Float())
+ return nil
+}
+
+// StringDecodeValue is the ValueDecoderFunc for string types.
+//
+// Deprecated: StringDecodeValue is not registered by default. Use StringCodec.DecodeValue instead.
+func (dvd DefaultValueDecoders) StringDecodeValue(dctx DecodeContext, vr bsonrw.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 bsontype.String:
+ 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(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tJavaScript {
+ return emptyValue, ValueDecoderError{
+ Name: "JavaScriptDecodeValue",
+ Types: []reflect.Type{tJavaScript},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var js string
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.JavaScript:
+ js, err = vr.ReadJavascript()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a primitive.JavaScript", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.JavaScript(js)), nil
+}
+
+// JavaScriptDecodeValue is the ValueDecoderFunc for the primitive.JavaScript type.
+func (dvd DefaultValueDecoders) JavaScriptDecodeValue(dctx DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.SetString(elem.String())
+ return nil
+}
+
+func (DefaultValueDecoders) symbolDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tSymbol {
+ return emptyValue, ValueDecoderError{
+ Name: "SymbolDecodeValue",
+ Types: []reflect.Type{tSymbol},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var symbol string
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.String:
+ symbol, err = vr.ReadString()
+ case bsontype.Symbol:
+ symbol, err = vr.ReadSymbol()
+ case bsontype.Binary:
+ data, subtype, err := vr.ReadBinary()
+ if err != nil {
+ return emptyValue, err
+ }
+
+ if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
+ return emptyValue, decodeBinaryError{subtype: subtype, typeName: "primitive.Symbol"}
+ }
+ symbol = string(data)
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a primitive.Symbol", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.Symbol(symbol)), nil
+}
+
+// SymbolDecodeValue is the ValueDecoderFunc for the primitive.Symbol type.
+func (dvd DefaultValueDecoders) SymbolDecodeValue(dctx DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.SetString(elem.String())
+ return nil
+}
+
+func (DefaultValueDecoders) binaryDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tBinary {
+ return emptyValue, ValueDecoderError{
+ Name: "BinaryDecodeValue",
+ Types: []reflect.Type{tBinary},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var data []byte
+ var subtype byte
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Binary:
+ data, subtype, err = vr.ReadBinary()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a Binary", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.Binary{Subtype: subtype, Data: data}), nil
+}
+
+// BinaryDecodeValue is the ValueDecoderFunc for Binary.
+func (dvd DefaultValueDecoders) BinaryDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (DefaultValueDecoders) undefinedDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tUndefined {
+ return emptyValue, ValueDecoderError{
+ Name: "UndefinedDecodeValue",
+ Types: []reflect.Type{tUndefined},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into an Undefined", vr.Type())
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.Undefined{}), nil
+}
+
+// UndefinedDecodeValue is the ValueDecoderFunc for Undefined.
+func (dvd DefaultValueDecoders) UndefinedDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+// Accept both 12-byte string and pretty-printed 24-byte hex string formats.
+func (dvd DefaultValueDecoders) objectIDDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tOID {
+ return emptyValue, ValueDecoderError{
+ Name: "ObjectIDDecodeValue",
+ Types: []reflect.Type{tOID},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var oid primitive.ObjectID
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.ObjectID:
+ oid, err = vr.ReadObjectID()
+ if err != nil {
+ return emptyValue, err
+ }
+ case bsontype.String:
+ str, err := vr.ReadString()
+ if err != nil {
+ return emptyValue, err
+ }
+ if oid, err = primitive.ObjectIDFromHex(str); err == nil {
+ break
+ }
+ if len(str) != 12 {
+ return emptyValue, fmt.Errorf("an ObjectID string must be exactly 12 bytes long (got %v)", len(str))
+ }
+ byteArr := []byte(str)
+ copy(oid[:], byteArr)
+ case bsontype.Null:
+ if err = vr.ReadNull(); err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Undefined:
+ if err = vr.ReadUndefined(); err != nil {
+ return emptyValue, err
+ }
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into an ObjectID", vrType)
+ }
+
+ return reflect.ValueOf(oid), nil
+}
+
+// ObjectIDDecodeValue is the ValueDecoderFunc for primitive.ObjectID.
+func (dvd DefaultValueDecoders) ObjectIDDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (DefaultValueDecoders) dateTimeDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tDateTime {
+ return emptyValue, ValueDecoderError{
+ Name: "DateTimeDecodeValue",
+ Types: []reflect.Type{tDateTime},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var dt int64
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.DateTime:
+ dt, err = vr.ReadDateTime()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a DateTime", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.DateTime(dt)), nil
+}
+
+// DateTimeDecodeValue is the ValueDecoderFunc for DateTime.
+func (dvd DefaultValueDecoders) DateTimeDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (DefaultValueDecoders) nullDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tNull {
+ return emptyValue, ValueDecoderError{
+ Name: "NullDecodeValue",
+ Types: []reflect.Type{tNull},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a Null", vr.Type())
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.Null{}), nil
+}
+
+// NullDecodeValue is the ValueDecoderFunc for Null.
+func (dvd DefaultValueDecoders) NullDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (DefaultValueDecoders) regexDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tRegex {
+ return emptyValue, ValueDecoderError{
+ Name: "RegexDecodeValue",
+ Types: []reflect.Type{tRegex},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var pattern, options string
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Regex:
+ pattern, options, err = vr.ReadRegex()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a Regex", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.Regex{Pattern: pattern, Options: options}), nil
+}
+
+// RegexDecodeValue is the ValueDecoderFunc for Regex.
+func (dvd DefaultValueDecoders) RegexDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (DefaultValueDecoders) dBPointerDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tDBPointer {
+ return emptyValue, ValueDecoderError{
+ Name: "DBPointerDecodeValue",
+ Types: []reflect.Type{tDBPointer},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var ns string
+ var pointer primitive.ObjectID
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.DBPointer:
+ ns, pointer, err = vr.ReadDBPointer()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a DBPointer", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.DBPointer{DB: ns, Pointer: pointer}), nil
+}
+
+// DBPointerDecodeValue is the ValueDecoderFunc for DBPointer.
+func (dvd DefaultValueDecoders) DBPointerDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (DefaultValueDecoders) timestampDecodeType(dc DecodeContext, vr bsonrw.ValueReader, reflectType reflect.Type) (reflect.Value, error) {
+ if reflectType != tTimestamp {
+ return emptyValue, ValueDecoderError{
+ Name: "TimestampDecodeValue",
+ Types: []reflect.Type{tTimestamp},
+ Received: reflect.Zero(reflectType),
+ }
+ }
+
+ var t, incr uint32
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Timestamp:
+ t, incr, err = vr.ReadTimestamp()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a Timestamp", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.Timestamp{T: t, I: incr}), nil
+}
+
+// TimestampDecodeValue is the ValueDecoderFunc for Timestamp.
+func (dvd DefaultValueDecoders) TimestampDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (DefaultValueDecoders) minKeyDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tMinKey {
+ return emptyValue, ValueDecoderError{
+ Name: "MinKeyDecodeValue",
+ Types: []reflect.Type{tMinKey},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.MinKey:
+ err = vr.ReadMinKey()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a MinKey", vr.Type())
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.MinKey{}), nil
+}
+
+// MinKeyDecodeValue is the ValueDecoderFunc for MinKey.
+func (dvd DefaultValueDecoders) MinKeyDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (DefaultValueDecoders) maxKeyDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tMaxKey {
+ return emptyValue, ValueDecoderError{
+ Name: "MaxKeyDecodeValue",
+ Types: []reflect.Type{tMaxKey},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.MaxKey:
+ err = vr.ReadMaxKey()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a MaxKey", vr.Type())
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(primitive.MaxKey{}), nil
+}
+
+// MaxKeyDecodeValue is the ValueDecoderFunc for MaxKey.
+func (dvd DefaultValueDecoders) MaxKeyDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (dvd DefaultValueDecoders) decimal128DecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tDecimal {
+ return emptyValue, ValueDecoderError{
+ Name: "Decimal128DecodeValue",
+ Types: []reflect.Type{tDecimal},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var d128 primitive.Decimal128
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Decimal128:
+ d128, err = vr.ReadDecimal128()
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a primitive.Decimal128", vr.Type())
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(d128), nil
+}
+
+// Decimal128DecodeValue is the ValueDecoderFunc for primitive.Decimal128.
+func (dvd DefaultValueDecoders) Decimal128DecodeValue(dctx DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (dvd DefaultValueDecoders) jsonNumberDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tJSONNumber {
+ return emptyValue, ValueDecoderError{
+ Name: "JSONNumberDecodeValue",
+ Types: []reflect.Type{tJSONNumber},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var jsonNum json.Number
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Double:
+ f64, err := vr.ReadDouble()
+ if err != nil {
+ return emptyValue, err
+ }
+ jsonNum = json.Number(strconv.FormatFloat(f64, 'f', -1, 64))
+ case bsontype.Int32:
+ i32, err := vr.ReadInt32()
+ if err != nil {
+ return emptyValue, err
+ }
+ jsonNum = json.Number(strconv.FormatInt(int64(i32), 10))
+ case bsontype.Int64:
+ i64, err := vr.ReadInt64()
+ if err != nil {
+ return emptyValue, err
+ }
+ jsonNum = json.Number(strconv.FormatInt(i64, 10))
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a json.Number", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(jsonNum), nil
+}
+
+// JSONNumberDecodeValue is the ValueDecoderFunc for json.Number.
+func (dvd DefaultValueDecoders) JSONNumberDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (dvd DefaultValueDecoders) urlDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tURL {
+ return emptyValue, ValueDecoderError{
+ Name: "URLDecodeValue",
+ Types: []reflect.Type{tURL},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ urlPtr := &url.URL{}
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.String:
+ var str string // Declare str here to avoid shadowing err during the ReadString call.
+ str, err = vr.ReadString()
+ if err != nil {
+ return emptyValue, err
+ }
+
+ urlPtr, err = url.Parse(str)
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a *url.URL", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(urlPtr).Elem(), nil
+}
+
+// URLDecodeValue is the ValueDecoderFunc for url.URL.
+func (dvd DefaultValueDecoders) URLDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+// TimeDecodeValue is the ValueDecoderFunc for time.Time.
+//
+// Deprecated: TimeDecodeValue is not registered by default. Use TimeCodec.DecodeValue instead.
+func (dvd DefaultValueDecoders) TimeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if vr.Type() != bsontype.DateTime {
+ 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(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if vr.Type() != bsontype.Binary && vr.Type() != bsontype.Null {
+ 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() == bsontype.Null {
+ 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", bsontype.Binary, 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 bsonrw.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 bsontype.Type(0), bsontype.EmbeddedDocument:
+ case bsontype.Null:
+ 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 err == bsonrw.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.
+func (dvd DefaultValueDecoders) ArrayDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.IsValid() || val.Kind() != reflect.Array {
+ return ValueDecoderError{Name: "ArrayDecodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val}
+ }
+
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Array:
+ case bsontype.Type(0), bsontype.EmbeddedDocument:
+ if val.Type().Elem() != tE {
+ return fmt.Errorf("cannot decode document into %s", val.Type())
+ }
+ case bsontype.Binary:
+ if val.Type().Elem() != tByte {
+ return fmt.Errorf("ArrayDecodeValue can only be used to decode binary into a byte array, got %v", vrType)
+ }
+ data, subtype, err := vr.ReadBinary()
+ if err != nil {
+ return err
+ }
+ if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
+ return fmt.Errorf("ArrayDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype)
+ }
+
+ if len(data) > val.Len() {
+ return fmt.Errorf("more elements returned in array than can fit inside %s", val.Type())
+ }
+
+ for idx, elem := range data {
+ val.Index(idx).Set(reflect.ValueOf(elem))
+ }
+ return nil
+ case bsontype.Null:
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadNull()
+ case bsontype.Undefined:
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadUndefined()
+ default:
+ return fmt.Errorf("cannot decode %v into an array", vrType)
+ }
+
+ var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error)
+ switch val.Type().Elem() {
+ case tE:
+ elemsFunc = dvd.decodeD
+ default:
+ elemsFunc = dvd.decodeDefault
+ }
+
+ elems, err := elemsFunc(dc, vr, val)
+ if err != nil {
+ return err
+ }
+
+ if len(elems) > val.Len() {
+ return fmt.Errorf("more elements returned in array than can fit inside %s, got %v elements", val.Type(), len(elems))
+ }
+
+ for idx, elem := range elems {
+ val.Index(idx).Set(elem)
+ }
+
+ 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 bsonrw.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 bsontype.Array:
+ case bsontype.Null:
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadNull()
+ case bsontype.Type(0), bsontype.EmbeddedDocument:
+ 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, bsonrw.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.
+func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(dc DecodeContext, vr bsonrw.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}
+ }
+
+ if val.Kind() == reflect.Ptr && val.IsNil() {
+ if !val.CanSet() {
+ return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val}
+ }
+ val.Set(reflect.New(val.Type().Elem()))
+ }
+
+ if !val.Type().Implements(tValueUnmarshaler) {
+ if !val.CanAddr() {
+ return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val}
+ }
+ val = val.Addr() // If the type doesn't implement the interface, a pointer to it must.
+ }
+
+ t, src, err := bsonrw.Copier{}.CopyValueToBytes(vr)
+ if err != nil {
+ return err
+ }
+
+ fn := val.Convert(tValueUnmarshaler).MethodByName("UnmarshalBSONValue")
+ errVal := fn.Call([]reflect.Value{reflect.ValueOf(t), reflect.ValueOf(src)})[0]
+ if !errVal.IsNil() {
+ return errVal.Interface().(error)
+ }
+ return nil
+}
+
+// UnmarshalerDecodeValue is the ValueDecoderFunc for Unmarshaler implementations.
+func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(dc DecodeContext, vr bsonrw.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}
+ }
+
+ if val.Kind() == reflect.Ptr && val.IsNil() {
+ if !val.CanSet() {
+ return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val}
+ }
+ val.Set(reflect.New(val.Type().Elem()))
+ }
+
+ _, src, err := bsonrw.Copier{}.CopyValueToBytes(vr)
+ if err != nil {
+ return err
+ }
+
+ // If the target Go value is a pointer and the BSON field value is empty, set the value to the
+ // zero value of the pointer (nil) and don't call UnmarshalBSON. UnmarshalBSON has no way to
+ // change the pointer value from within the function (only the value at the pointer address),
+ // so it can't set the pointer to "nil" itself. Since the most common Go value for an empty BSON
+ // field value is "nil", we set "nil" here and don't call UnmarshalBSON. This behavior matches
+ // the behavior of the Go "encoding/json" unmarshaler when the target Go value is a pointer and
+ // the JSON field value is "null".
+ if val.Kind() == reflect.Ptr && len(src) == 0 {
+ val.Set(reflect.Zero(val.Type()))
+ return nil
+ }
+
+ if !val.Type().Implements(tUnmarshaler) {
+ if !val.CanAddr() {
+ return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val}
+ }
+ val = val.Addr() // If the type doesn't implement the interface, a pointer to it must.
+ }
+
+ fn := val.Convert(tUnmarshaler).MethodByName("UnmarshalBSON")
+ errVal := fn.Call([]reflect.Value{reflect.ValueOf(src)})[0]
+ if !errVal.IsNil() {
+ return errVal.Interface().(error)
+ }
+ return nil
+}
+
+// EmptyInterfaceDecodeValue is the ValueDecoderFunc for interface{}.
+//
+// Deprecated: EmptyInterfaceDecodeValue is not registered by default. Use EmptyInterfaceCodec.DecodeValue instead.
+func (dvd DefaultValueDecoders) EmptyInterfaceDecodeValue(dc DecodeContext, vr bsonrw.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 bsontype.EmbeddedDocument:
+ if dc.Ancestor != nil {
+ rtype = dc.Ancestor
+ break
+ }
+ rtype = tD
+ case bsontype.Null:
+ 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.
+func (DefaultValueDecoders) CoreDocumentDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tCoreDocument {
+ return ValueDecoderError{Name: "CoreDocumentDecodeValue", Types: []reflect.Type{tCoreDocument}, Received: val}
+ }
+
+ if val.IsNil() {
+ val.Set(reflect.MakeSlice(val.Type(), 0, 0))
+ }
+
+ val.SetLen(0)
+
+ cdoc, err := bsonrw.Copier{}.AppendDocumentBytes(val.Interface().(bsoncore.Document), vr)
+ val.Set(reflect.ValueOf(cdoc))
+ return err
+}
+
+func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) ([]reflect.Value, error) {
+ elems := make([]reflect.Value, 0)
+
+ ar, err := vr.ReadArray()
+ if err != nil {
+ return nil, err
+ }
+
+ eType := val.Type().Elem()
+
+ decoder, err := dc.LookupDecoder(eType)
+ if err != nil {
+ return nil, err
+ }
+ eTypeDecoder, _ := decoder.(typeDecoder)
+
+ idx := 0
+ for {
+ vr, err := ar.ReadValue()
+ if err == bsonrw.ErrEOA {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true)
+ if err != nil {
+ return nil, newDecodeError(strconv.Itoa(idx), err)
+ }
+ elems = append(elems, elem)
+ idx++
+ }
+
+ return elems, nil
+}
+
+func (dvd DefaultValueDecoders) readCodeWithScope(dc DecodeContext, vr bsonrw.ValueReader) (primitive.CodeWithScope, error) {
+ var cws primitive.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 = primitive.CodeWithScope{
+ Code: primitive.JavaScript(code),
+ Scope: scope.Interface().(primitive.D),
+ }
+ return cws, nil
+}
+
+func (dvd DefaultValueDecoders) codeWithScopeDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tCodeWithScope {
+ return emptyValue, ValueDecoderError{
+ Name: "CodeWithScopeDecodeValue",
+ Types: []reflect.Type{tCodeWithScope},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var cws primitive.CodeWithScope
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.CodeWithScope:
+ cws, err = dvd.readCodeWithScope(dc, vr)
+ case bsontype.Null:
+ err = vr.ReadNull()
+ case bsontype.Undefined:
+ err = vr.ReadUndefined()
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a primitive.CodeWithScope", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(cws), nil
+}
+
+// CodeWithScopeDecodeValue is the ValueDecoderFunc for CodeWithScope.
+func (dvd DefaultValueDecoders) CodeWithScopeDecodeValue(dc DecodeContext, vr bsonrw.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)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+func (dvd DefaultValueDecoders) decodeD(dc DecodeContext, vr bsonrw.ValueReader, _ reflect.Value) ([]reflect.Value, error) {
+ switch vr.Type() {
+ case bsontype.Type(0), bsontype.EmbeddedDocument:
+ default:
+ return nil, fmt.Errorf("cannot decode %v into a D", vr.Type())
+ }
+
+ dr, err := vr.ReadDocument()
+ if err != nil {
+ return nil, err
+ }
+
+ return dvd.decodeElemsFromDocumentReader(dc, dr)
+}
+
+func (DefaultValueDecoders) decodeElemsFromDocumentReader(dc DecodeContext, dr bsonrw.DocumentReader) ([]reflect.Value, error) {
+ decoder, err := dc.LookupDecoder(tEmpty)
+ if err != nil {
+ return nil, err
+ }
+
+ elems := make([]reflect.Value, 0)
+ for {
+ key, vr, err := dr.ReadElement()
+ if err == bsonrw.ErrEOD {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ val := reflect.New(tEmpty).Elem()
+ err = decoder.DecodeValue(dc, vr, val)
+ if err != nil {
+ return nil, newDecodeError(key, err)
+ }
+
+ elems = append(elems, reflect.ValueOf(primitive.E{Key: key, Value: val.Interface()}))
+ }
+
+ return elems, nil
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go
new file mode 100644
index 000000000..6bdb43cb4
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go
@@ -0,0 +1,766 @@
+// 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 bsoncodec
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math"
+ "net/url"
+ "reflect"
+ "sync"
+ "time"
+
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+ "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
+)
+
+var defaultValueEncoders DefaultValueEncoders
+
+var bvwPool = bsonrw.NewBSONValueWriterPool()
+
+var errInvalidValue = errors.New("cannot encode invalid element")
+
+var sliceWriterPool = sync.Pool{
+ New: func() interface{} {
+ sw := make(bsonrw.SliceWriter, 0)
+ return &sw
+ },
+}
+
+func encodeElement(ec EncodeContext, dw bsonrw.DocumentWriter, e primitive.E) error {
+ vw, err := dw.WriteDocumentElement(e.Key)
+ if err != nil {
+ return err
+ }
+
+ if e.Value == nil {
+ return vw.WriteNull()
+ }
+ encoder, err := ec.LookupEncoder(reflect.TypeOf(e.Value))
+ if err != nil {
+ return err
+ }
+
+ err = encoder.EncodeValue(ec, vw, reflect.ValueOf(e.Value))
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// DefaultValueEncoders is a namespace type for the default ValueEncoders used
+// when creating a registry.
+type DefaultValueEncoders struct{}
+
+// RegisterDefaultEncoders will register the encoder methods attached to DefaultValueEncoders with
+// the provided RegistryBuilder.
+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.
+func (dve DefaultValueEncoders) BooleanEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Kind() != reflect.Bool {
+ return ValueEncoderError{Name: "BooleanEncodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val}
+ }
+ return vw.WriteBoolean(val.Bool())
+}
+
+func fitsIn32Bits(i int64) bool {
+ return math.MinInt32 <= i && i <= math.MaxInt32
+}
+
+// IntEncodeValue is the ValueEncoderFunc for int types.
+func (dve DefaultValueEncoders) IntEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ switch val.Kind() {
+ case reflect.Int8, reflect.Int16, reflect.Int32:
+ return vw.WriteInt32(int32(val.Int()))
+ case reflect.Int:
+ i64 := val.Int()
+ if fitsIn32Bits(i64) {
+ return vw.WriteInt32(int32(i64))
+ }
+ return vw.WriteInt64(i64)
+ case reflect.Int64:
+ i64 := val.Int()
+ if ec.MinSize && fitsIn32Bits(i64) {
+ return vw.WriteInt32(int32(i64))
+ }
+ return vw.WriteInt64(i64)
+ }
+
+ return ValueEncoderError{
+ Name: "IntEncodeValue",
+ Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
+ Received: val,
+ }
+}
+
+// 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 bsonrw.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.
+func (dve DefaultValueEncoders) FloatEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ switch val.Kind() {
+ case reflect.Float32, reflect.Float64:
+ return vw.WriteDouble(val.Float())
+ }
+
+ 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(ectx EncodeContext, vw bsonrw.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 primitive.ObjectID.
+func (dve DefaultValueEncoders) ObjectIDEncodeValue(ec EncodeContext, vw bsonrw.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().(primitive.ObjectID))
+}
+
+// Decimal128EncodeValue is the ValueEncoderFunc for primitive.Decimal128.
+func (dve DefaultValueEncoders) Decimal128EncodeValue(ec EncodeContext, vw bsonrw.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().(primitive.Decimal128))
+}
+
+// JSONNumberEncodeValue is the ValueEncoderFunc for json.Number.
+func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tJSONNumber {
+ return ValueEncoderError{Name: "JSONNumberEncodeValue", Types: []reflect.Type{tJSONNumber}, Received: val}
+ }
+ jsnum := val.Interface().(json.Number)
+
+ // Attempt int first, then float64
+ if i64, err := jsnum.Int64(); err == nil {
+ return dve.IntEncodeValue(ec, vw, reflect.ValueOf(i64))
+ }
+
+ f64, err := jsnum.Float64()
+ if err != nil {
+ return err
+ }
+
+ return dve.FloatEncodeValue(ec, vw, reflect.ValueOf(f64))
+}
+
+// URLEncodeValue is the ValueEncoderFunc for url.URL.
+func (dve DefaultValueEncoders) URLEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tURL {
+ return ValueEncoderError{Name: "URLEncodeValue", Types: []reflect.Type{tURL}, Received: val}
+ }
+ u := val.Interface().(url.URL)
+ 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(ec EncodeContext, vw bsonrw.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 := primitive.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(ec EncodeContext, vw bsonrw.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 bsonrw.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 bsonrw.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 && lookupErr != errInvalidValue {
+ return lookupErr
+ }
+
+ vw, err := dw.WriteDocumentElement(key.String())
+ if err != nil {
+ return err
+ }
+
+ if 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.
+func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Kind() != reflect.Array {
+ return ValueEncoderError{Name: "ArrayEncodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val}
+ }
+
+ // If we have a []primitive.E we want to treat it as a document instead of as an array.
+ if val.Type().Elem() == tE {
+ dw, err := vw.WriteDocument()
+ if err != nil {
+ return err
+ }
+
+ for idx := 0; idx < val.Len(); idx++ {
+ e := val.Index(idx).Interface().(primitive.E)
+ err = encodeElement(ec, dw, e)
+ if err != nil {
+ return err
+ }
+ }
+
+ return dw.WriteDocumentEnd()
+ }
+
+ // If we have a []byte we want to treat it as a binary instead of as an array.
+ if val.Type().Elem() == tByte {
+ var byteSlice []byte
+ for idx := 0; idx < val.Len(); idx++ {
+ byteSlice = append(byteSlice, val.Index(idx).Interface().(byte))
+ }
+ return vw.WriteBinary(byteSlice)
+ }
+
+ 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))
+ if lookupErr != nil && lookupErr != errInvalidValue {
+ return lookupErr
+ }
+
+ vw, err := aw.WriteArrayElement()
+ if err != nil {
+ return err
+ }
+
+ if 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 bsonrw.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 []primitive.E we want to treat it as a document instead of as an array.
+ if val.Type().ConvertibleTo(tD) {
+ d := val.Convert(tD).Interface().(primitive.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))
+ if lookupErr != nil && lookupErr != errInvalidValue {
+ return lookupErr
+ }
+
+ vw, err := aw.WriteArrayElement()
+ if err != nil {
+ return err
+ }
+
+ if 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()
+}
+
+func (dve DefaultValueEncoders) lookupElementEncoder(ec EncodeContext, origEncoder ValueEncoder, currVal reflect.Value) (ValueEncoder, reflect.Value, error) {
+ if origEncoder != nil || (currVal.Kind() != reflect.Interface) {
+ return origEncoder, currVal, nil
+ }
+ currVal = currVal.Elem()
+ if !currVal.IsValid() {
+ return nil, currVal, errInvalidValue
+ }
+ currEncoder, err := ec.LookupEncoder(currVal.Type())
+
+ 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 bsonrw.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.
+func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ // Either val or a pointer to val must implement ValueMarshaler
+ switch {
+ case !val.IsValid():
+ return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val}
+ case val.Type().Implements(tValueMarshaler):
+ // If ValueMarshaler is implemented on a concrete type, make sure that val isn't a nil pointer
+ if isImplementationNil(val, tValueMarshaler) {
+ return vw.WriteNull()
+ }
+ case reflect.PtrTo(val.Type()).Implements(tValueMarshaler) && val.CanAddr():
+ val = val.Addr()
+ default:
+ return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val}
+ }
+
+ fn := val.Convert(tValueMarshaler).MethodByName("MarshalBSONValue")
+ returns := fn.Call(nil)
+ if !returns[2].IsNil() {
+ return returns[2].Interface().(error)
+ }
+ t, data := returns[0].Interface().(bsontype.Type), returns[1].Interface().([]byte)
+ return bsonrw.Copier{}.CopyValueFromBytes(vw, t, data)
+}
+
+// MarshalerEncodeValue is the ValueEncoderFunc for Marshaler implementations.
+func (dve DefaultValueEncoders) MarshalerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ // Either val or a pointer to val must implement Marshaler
+ switch {
+ case !val.IsValid():
+ return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val}
+ case val.Type().Implements(tMarshaler):
+ // If Marshaler is implemented on a concrete type, make sure that val isn't a nil pointer
+ if isImplementationNil(val, tMarshaler) {
+ return vw.WriteNull()
+ }
+ case reflect.PtrTo(val.Type()).Implements(tMarshaler) && val.CanAddr():
+ val = val.Addr()
+ default:
+ return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val}
+ }
+
+ fn := val.Convert(tMarshaler).MethodByName("MarshalBSON")
+ returns := fn.Call(nil)
+ if !returns[1].IsNil() {
+ return returns[1].Interface().(error)
+ }
+ data := returns[0].Interface().([]byte)
+ return bsonrw.Copier{}.CopyValueFromBytes(vw, bsontype.EmbeddedDocument, data)
+}
+
+// ProxyEncodeValue is the ValueEncoderFunc for Proxy implementations.
+func (dve DefaultValueEncoders) ProxyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ // Either val or a pointer to val must implement Proxy
+ switch {
+ case !val.IsValid():
+ return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val}
+ case val.Type().Implements(tProxy):
+ // If Proxy is implemented on a concrete type, make sure that val isn't a nil pointer
+ if isImplementationNil(val, tProxy) {
+ return vw.WriteNull()
+ }
+ case reflect.PtrTo(val.Type()).Implements(tProxy) && val.CanAddr():
+ val = val.Addr()
+ default:
+ return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val}
+ }
+
+ fn := val.Convert(tProxy).MethodByName("ProxyBSON")
+ returns := fn.Call(nil)
+ if !returns[1].IsNil() {
+ return returns[1].Interface().(error)
+ }
+ data := returns[0]
+ var encoder ValueEncoder
+ var err error
+ if data.Elem().IsValid() {
+ encoder, err = ec.LookupEncoder(data.Elem().Type())
+ } else {
+ encoder, err = ec.LookupEncoder(nil)
+ }
+ if err != nil {
+ return err
+ }
+ return encoder.EncodeValue(ec, vw, data.Elem())
+}
+
+// JavaScriptEncodeValue is the ValueEncoderFunc for the primitive.JavaScript type.
+func (DefaultValueEncoders) JavaScriptEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tJavaScript {
+ return ValueEncoderError{Name: "JavaScriptEncodeValue", Types: []reflect.Type{tJavaScript}, Received: val}
+ }
+
+ return vw.WriteJavascript(val.String())
+}
+
+// SymbolEncodeValue is the ValueEncoderFunc for the primitive.Symbol type.
+func (DefaultValueEncoders) SymbolEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tSymbol {
+ return ValueEncoderError{Name: "SymbolEncodeValue", Types: []reflect.Type{tSymbol}, Received: val}
+ }
+
+ return vw.WriteSymbol(val.String())
+}
+
+// BinaryEncodeValue is the ValueEncoderFunc for Binary.
+func (DefaultValueEncoders) BinaryEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tBinary {
+ return ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val}
+ }
+ b := val.Interface().(primitive.Binary)
+
+ return vw.WriteBinaryWithSubtype(b.Data, b.Subtype)
+}
+
+// UndefinedEncodeValue is the ValueEncoderFunc for Undefined.
+func (DefaultValueEncoders) UndefinedEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tUndefined {
+ return ValueEncoderError{Name: "UndefinedEncodeValue", Types: []reflect.Type{tUndefined}, Received: val}
+ }
+
+ return vw.WriteUndefined()
+}
+
+// DateTimeEncodeValue is the ValueEncoderFunc for DateTime.
+func (DefaultValueEncoders) DateTimeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tDateTime {
+ return ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: val}
+ }
+
+ return vw.WriteDateTime(val.Int())
+}
+
+// NullEncodeValue is the ValueEncoderFunc for Null.
+func (DefaultValueEncoders) NullEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tNull {
+ return ValueEncoderError{Name: "NullEncodeValue", Types: []reflect.Type{tNull}, Received: val}
+ }
+
+ return vw.WriteNull()
+}
+
+// RegexEncodeValue is the ValueEncoderFunc for Regex.
+func (DefaultValueEncoders) RegexEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tRegex {
+ return ValueEncoderError{Name: "RegexEncodeValue", Types: []reflect.Type{tRegex}, Received: val}
+ }
+
+ regex := val.Interface().(primitive.Regex)
+
+ return vw.WriteRegex(regex.Pattern, regex.Options)
+}
+
+// DBPointerEncodeValue is the ValueEncoderFunc for DBPointer.
+func (DefaultValueEncoders) DBPointerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tDBPointer {
+ return ValueEncoderError{Name: "DBPointerEncodeValue", Types: []reflect.Type{tDBPointer}, Received: val}
+ }
+
+ dbp := val.Interface().(primitive.DBPointer)
+
+ return vw.WriteDBPointer(dbp.DB, dbp.Pointer)
+}
+
+// TimestampEncodeValue is the ValueEncoderFunc for Timestamp.
+func (DefaultValueEncoders) TimestampEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tTimestamp {
+ return ValueEncoderError{Name: "TimestampEncodeValue", Types: []reflect.Type{tTimestamp}, Received: val}
+ }
+
+ ts := val.Interface().(primitive.Timestamp)
+
+ return vw.WriteTimestamp(ts.T, ts.I)
+}
+
+// MinKeyEncodeValue is the ValueEncoderFunc for MinKey.
+func (DefaultValueEncoders) MinKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tMinKey {
+ return ValueEncoderError{Name: "MinKeyEncodeValue", Types: []reflect.Type{tMinKey}, Received: val}
+ }
+
+ return vw.WriteMinKey()
+}
+
+// MaxKeyEncodeValue is the ValueEncoderFunc for MaxKey.
+func (DefaultValueEncoders) MaxKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tMaxKey {
+ return ValueEncoderError{Name: "MaxKeyEncodeValue", Types: []reflect.Type{tMaxKey}, Received: val}
+ }
+
+ return vw.WriteMaxKey()
+}
+
+// CoreDocumentEncodeValue is the ValueEncoderFunc for bsoncore.Document.
+func (DefaultValueEncoders) CoreDocumentEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tCoreDocument {
+ return ValueEncoderError{Name: "CoreDocumentEncodeValue", Types: []reflect.Type{tCoreDocument}, Received: val}
+ }
+
+ cdoc := val.Interface().(bsoncore.Document)
+
+ return bsonrw.Copier{}.CopyDocumentFromBytes(vw, cdoc)
+}
+
+// CodeWithScopeEncodeValue is the ValueEncoderFunc for CodeWithScope.
+func (dve DefaultValueEncoders) CodeWithScopeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tCodeWithScope {
+ return ValueEncoderError{Name: "CodeWithScopeEncodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val}
+ }
+
+ cws := val.Interface().(primitive.CodeWithScope)
+
+ dw, err := vw.WriteCodeWithScope(string(cws.Code))
+ if err != nil {
+ return err
+ }
+
+ sw := sliceWriterPool.Get().(*bsonrw.SliceWriter)
+ defer sliceWriterPool.Put(sw)
+ *sw = (*sw)[:0]
+
+ scopeVW := bvwPool.Get(sw)
+ defer bvwPool.Put(scopeVW)
+
+ encoder, err := ec.LookupEncoder(reflect.TypeOf(cws.Scope))
+ if err != nil {
+ return err
+ }
+
+ err = encoder.EncodeValue(ec, scopeVW, reflect.ValueOf(cws.Scope))
+ if err != nil {
+ return err
+ }
+
+ err = bsonrw.Copier{}.CopyBytesToDocumentWriter(dw, *sw)
+ if err != nil {
+ return err
+ }
+ return dw.WriteDocumentEnd()
+}
+
+// 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/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go
new file mode 100644
index 000000000..5f903ebea
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go
@@ -0,0 +1,90 @@
+// 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 bsoncodec provides a system for encoding values to BSON representations and decoding
+// values from BSON representations. This package considers both binary BSON and ExtendedJSON as
+// BSON representations. The types in this package enable a flexible system for handling this
+// encoding and decoding.
+//
+// The codec system is composed of two parts:
+//
+// 1) ValueEncoders and ValueDecoders that handle encoding and decoding Go values to and from BSON
+// representations.
+//
+// 2) A Registry that holds these ValueEncoders and ValueDecoders and provides methods for
+// retrieving them.
+//
+// # ValueEncoders and ValueDecoders
+//
+// The ValueEncoder interface is implemented by types that can encode a provided Go type to BSON.
+// The value to encode is provided as a reflect.Value and a bsonrw.ValueWriter is used within the
+// EncodeValue method to actually create the BSON representation. For convenience, ValueEncoderFunc
+// is provided to allow use of a function with the correct signature as a ValueEncoder. An
+// EncodeContext instance is provided to allow implementations to lookup further ValueEncoders and
+// to provide configuration information.
+//
+// The ValueDecoder interface is the inverse of the ValueEncoder. Implementations should ensure that
+// the value they receive is settable. Similar to ValueEncoderFunc, ValueDecoderFunc is provided to
+// allow the use of a function with the correct signature as a ValueDecoder. A DecodeContext
+// instance is provided and serves similar functionality to the EncodeContext.
+//
+// # Registry and RegistryBuilder
+//
+// A Registry is an immutable 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 be constructed using a
+// RegistryBuilder, which handles three main types of codecs:
+//
+// 1. Type encoders/decoders - These can be registered using the RegisterTypeEncoder and RegisterTypeDecoder methods.
+// The registered codec will be invoked when encoding/decoding a value whose type matches the registered type exactly.
+// If the registered type is an interface, the codec will be invoked when encoding or decoding values whose type is the
+// interface, but not for values with concrete types that implement the interface.
+//
+// 2. Hook encoders/decoders - These can be registered using the RegisterHookEncoder and RegisterHookDecoder methods.
+// These methods only accept interface types and the registered codecs will be invoked when encoding or decoding values
+// whose types implement the interface. An example of a hook defined by the driver is bson.Marshaler. The driver will
+// call the MarshalBSON method for any value whose type implements bson.Marshaler, regardless of the value's concrete
+// type.
+//
+// 3. Type map entries - This can be used to associate a BSON type with a Go type. These type associations are used when
+// decoding into a bson.D/bson.M or a struct field of type interface{}. For example, by default, BSON int32 and int64
+// values decode as Go int32 and int64 instances, respectively, when decoding into a bson.D. The following code would
+// change the behavior so these values decode as Go int instances instead:
+//
+// intType := reflect.TypeOf(int(0))
+// registryBuilder.RegisterTypeMapEntry(bsontype.Int32, intType).RegisterTypeMapEntry(bsontype.Int64, intType)
+//
+// 4. Kind encoder/decoders - These can be registered using the RegisterDefaultEncoder and RegisterDefaultDecoder
+// methods. The registered codec will be invoked when encoding or decoding values whose reflect.Kind matches the
+// registered reflect.Kind as long as the value's type doesn't match a registered type or hook encoder/decoder first.
+// These methods should be used to change the behavior for all values for a specific kind.
+//
+// # Registry Lookup Procedure
+//
+// When looking up an encoder in a Registry, the precedence rules are as follows:
+//
+// 1. A type encoder registered for the exact type of the value.
+//
+// 2. A hook encoder registered for an interface that is implemented by the value or by a pointer to the value. If the
+// value matches multiple hooks (e.g. the type implements bsoncodec.Marshaler and bsoncodec.ValueMarshaler), the first
+// one registered will be selected. Note that registries constructed using bson.NewRegistryBuilder have driver-defined
+// hooks registered for the bsoncodec.Marshaler, bsoncodec.ValueMarshaler, and bsoncodec.Proxy interfaces, so those
+// will take precedence over any new hooks.
+//
+// 3. A kind encoder registered for the value's kind.
+//
+// If all of these lookups fail to find an encoder, an error of type ErrNoEncoder is returned. The same precedence
+// rules apply for decoders, with the exception that an error of type ErrNoDecoder will be returned if no decoder is
+// found.
+//
+// # DefaultValueEncoders and DefaultValueDecoders
+//
+// The DefaultValueEncoders and DefaultValueDecoders types provide a full set of ValueEncoders and
+// ValueDecoders for handling a wide range of Go types, including all of the types within the
+// primitive package. To make registering these codecs easier, a helper method on each type is
+// provided. For the DefaultValueEncoders type the method is called RegisterDefaultEncoders and for
+// the DefaultValueDecoders type the method is called RegisterDefaultDecoders, this method also
+// handles registering type map entries for each BSON type.
+package bsoncodec
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go
new file mode 100644
index 000000000..eda417cff
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go
@@ -0,0 +1,147 @@
+// 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 bsoncodec
+
+import (
+ "reflect"
+
+ "go.mongodb.org/mongo-driver/bson/bsonoptions"
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+// EmptyInterfaceCodec is the Codec used for interface{} values.
+type EmptyInterfaceCodec struct {
+ DecodeBinaryAsSlice bool
+}
+
+var (
+ defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec()
+
+ _ ValueCodec = defaultEmptyInterfaceCodec
+ _ typeDecoder = defaultEmptyInterfaceCodec
+)
+
+// NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts.
+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 bsonrw.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())
+}
+
+func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, valueType bsontype.Type) (reflect.Type, error) {
+ isDocument := valueType == bsontype.Type(0) || valueType == bsontype.EmbeddedDocument
+ if isDocument {
+ if dc.defaultDocumentType != nil {
+ // If the bsontype is an embedded document and the DocumentType is set on the DecodeContext, then return
+ // that type.
+ return dc.defaultDocumentType, nil
+ }
+ if dc.Ancestor != nil {
+ // Using ancestor information rather than looking up the type map entry forces consistent decoding.
+ // If we're decoding into a bson.D, subdocuments should also be decoded as bson.D, even if a type map entry
+ // has been registered.
+ return dc.Ancestor, nil
+ }
+ }
+
+ rtype, err := dc.LookupTypeMapEntry(valueType)
+ if err == nil {
+ return rtype, nil
+ }
+
+ if isDocument {
+ // For documents, fallback to looking up a type map entry for bsontype.Type(0) or bsontype.EmbeddedDocument,
+ // depending on the original valueType.
+ var lookupType bsontype.Type
+ switch valueType {
+ case bsontype.Type(0):
+ lookupType = bsontype.EmbeddedDocument
+ case bsontype.EmbeddedDocument:
+ lookupType = bsontype.Type(0)
+ }
+
+ rtype, err = dc.LookupTypeMapEntry(lookupType)
+ if err == nil {
+ return rtype, nil
+ }
+ }
+
+ return nil, err
+}
+
+func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tEmpty {
+ return emptyValue, ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.Zero(t)}
+ }
+
+ rtype, err := eic.getEmptyInterfaceDecodeType(dc, vr.Type())
+ if err != nil {
+ switch vr.Type() {
+ case bsontype.Null:
+ return reflect.Zero(t), vr.ReadNull()
+ default:
+ return emptyValue, err
+ }
+ }
+
+ decoder, err := dc.LookupDecoder(rtype)
+ if err != nil {
+ return emptyValue, err
+ }
+
+ elem, err := decodeTypeOrValue(decoder, dc, vr, rtype)
+ if err != nil {
+ return emptyValue, err
+ }
+
+ if eic.DecodeBinaryAsSlice && rtype == tBinary {
+ binElem := elem.Interface().(primitive.Binary)
+ if binElem.Subtype == bsontype.BinaryGeneric || binElem.Subtype == bsontype.BinaryBinaryOld {
+ elem = reflect.ValueOf(binElem.Data)
+ }
+ }
+
+ return elem, nil
+}
+
+// DecodeValue is the ValueDecoderFunc for interface{}.
+func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tEmpty {
+ return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val}
+ }
+
+ elem, err := eic.decodeType(dc, vr, val.Type())
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go
new file mode 100644
index 000000000..e1fbef9c6
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go
@@ -0,0 +1,309 @@
+// 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 bsoncodec
+
+import (
+ "encoding"
+ "fmt"
+ "reflect"
+ "strconv"
+
+ "go.mongodb.org/mongo-driver/bson/bsonoptions"
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+)
+
+var defaultMapCodec = NewMapCodec()
+
+// MapCodec is the Codec used for map values.
+type MapCodec struct {
+ DecodeZerosMap bool
+ EncodeNilAsEmpty bool
+ EncodeKeysWithStringer bool
+}
+
+var _ ValueCodec = &MapCodec{}
+
+// KeyMarshaler is the interface implemented by an object that can marshal itself into a string key.
+// This applies to types used as map keys and is similar to encoding.TextMarshaler.
+type KeyMarshaler interface {
+ MarshalKey() (key string, err error)
+}
+
+// KeyUnmarshaler is the interface implemented by an object that can unmarshal a string representation
+// of itself. This applies to types used as map keys and is similar to encoding.TextUnmarshaler.
+//
+// UnmarshalKey must be able to decode the form generated by MarshalKey.
+// UnmarshalKey must copy the text if it wishes to retain the text
+// after returning.
+type KeyUnmarshaler interface {
+ UnmarshalKey(key string) error
+}
+
+// NewMapCodec returns a MapCodec with options opts.
+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 bsonrw.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 {
+ // 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,
+ // 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 mc.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 (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.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 {
+ keyStr, err := mc.encodeKey(key)
+ if err != nil {
+ return err
+ }
+
+ if collisionFn != nil && collisionFn(keyStr) {
+ 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))
+ if lookupErr != nil && lookupErr != errInvalidValue {
+ return lookupErr
+ }
+
+ vw, err := dw.WriteDocumentElement(keyStr)
+ if err != nil {
+ return err
+ }
+
+ if 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()
+}
+
+// DecodeValue is the ValueDecoder for map[string/decimal]* types.
+func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.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}
+ }
+
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Type(0), bsontype.EmbeddedDocument:
+ case bsontype.Null:
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadNull()
+ case bsontype.Undefined:
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadUndefined()
+ default:
+ return fmt.Errorf("cannot decode %v into a %s", vrType, val.Type())
+ }
+
+ dr, err := vr.ReadDocument()
+ if err != nil {
+ return err
+ }
+
+ if val.IsNil() {
+ val.Set(reflect.MakeMap(val.Type()))
+ }
+
+ if val.Len() > 0 && mc.DecodeZerosMap {
+ clearMap(val)
+ }
+
+ eType := val.Type().Elem()
+ decoder, err := dc.LookupDecoder(eType)
+ if err != nil {
+ return err
+ }
+ eTypeDecoder, _ := decoder.(typeDecoder)
+
+ if eType == tEmpty {
+ dc.Ancestor = val.Type()
+ }
+
+ keyType := val.Type().Key()
+
+ for {
+ key, vr, err := dr.ReadElement()
+ if err == bsonrw.ErrEOD {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ k, err := mc.decodeKey(key, keyType)
+ if err != nil {
+ return err
+ }
+
+ elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true)
+ if err != nil {
+ return newDecodeError(key, err)
+ }
+
+ val.SetMapIndex(k, elem)
+ }
+ return nil
+}
+
+func clearMap(m reflect.Value) {
+ var none reflect.Value
+ for _, k := range m.MapKeys() {
+ m.SetMapIndex(k, none)
+ }
+}
+
+func (mc *MapCodec) encodeKey(val reflect.Value) (string, error) {
+ if mc.EncodeKeysWithStringer {
+ return fmt.Sprint(val), nil
+ }
+
+ // keys of any string type are used directly
+ if val.Kind() == reflect.String {
+ return val.String(), nil
+ }
+ // KeyMarshalers are marshaled
+ if km, ok := val.Interface().(KeyMarshaler); ok {
+ if val.Kind() == reflect.Ptr && val.IsNil() {
+ return "", nil
+ }
+ buf, err := km.MarshalKey()
+ if err == nil {
+ return buf, nil
+ }
+ return "", err
+ }
+ // keys implement encoding.TextMarshaler are marshaled.
+ if km, ok := val.Interface().(encoding.TextMarshaler); ok {
+ if val.Kind() == reflect.Ptr && val.IsNil() {
+ return "", nil
+ }
+
+ buf, err := km.MarshalText()
+ if err != nil {
+ return "", err
+ }
+
+ return string(buf), nil
+ }
+
+ switch val.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return strconv.FormatInt(val.Int(), 10), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return strconv.FormatUint(val.Uint(), 10), nil
+ }
+ return "", fmt.Errorf("unsupported key type: %v", val.Type())
+}
+
+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) {
+ 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):
+ keyVal = reflect.New(keyType)
+ v := keyVal.Interface().(KeyUnmarshaler)
+ err = v.UnmarshalKey(key)
+ keyVal = keyVal.Elem()
+ // Try to decode encoding.TextUnmarshalers.
+ case reflect.PtrTo(keyType).Implements(textUnmarshalerType):
+ keyVal = reflect.New(keyType)
+ v := keyVal.Interface().(encoding.TextUnmarshaler)
+ err = v.UnmarshalText([]byte(key))
+ keyVal = keyVal.Elem()
+ // Otherwise, go to type specific behavior
+ default:
+ switch keyType.Kind() {
+ case reflect.String:
+ keyVal = reflect.ValueOf(key).Convert(keyType)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ n, parseErr := strconv.ParseInt(key, 10, 64)
+ if parseErr != nil || reflect.Zero(keyType).OverflowInt(n) {
+ err = fmt.Errorf("failed to unmarshal number key %v", key)
+ }
+ keyVal = reflect.ValueOf(n).Convert(keyType)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ n, parseErr := strconv.ParseUint(key, 10, 64)
+ if parseErr != nil || reflect.Zero(keyType).OverflowUint(n) {
+ err = fmt.Errorf("failed to unmarshal number key %v", key)
+ break
+ }
+ keyVal = reflect.ValueOf(n).Convert(keyType)
+ case reflect.Float32, reflect.Float64:
+ 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 %v", keyType.Kind(), err)
+ }
+ keyVal = reflect.ValueOf(parsed)
+ break
+ }
+ fallthrough
+ default:
+ return keyVal, fmt.Errorf("unsupported key type: %v", keyType)
+ }
+ }
+ return keyVal, err
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go
new file mode 100644
index 000000000..fbd9f0a9e
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go
@@ -0,0 +1,65 @@
+// 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 bsoncodec
+
+import "fmt"
+
+type mode int
+
+const (
+ _ mode = iota
+ mTopLevel
+ mDocument
+ mArray
+ mValue
+ mElement
+ mCodeWithScope
+ mSpacer
+)
+
+func (m mode) String() string {
+ var str string
+
+ switch m {
+ case mTopLevel:
+ str = "TopLevel"
+ case mDocument:
+ str = "DocumentMode"
+ case mArray:
+ str = "ArrayMode"
+ case mValue:
+ str = "ValueMode"
+ case mElement:
+ str = "ElementMode"
+ case mCodeWithScope:
+ str = "CodeWithScopeMode"
+ case mSpacer:
+ str = "CodeWithScopeSpacerFrame"
+ default:
+ str = "UnknownMode"
+ }
+
+ return str
+}
+
+// TransitionError is an error returned when an invalid progressing a
+// ValueReader or ValueWriter state machine occurs.
+type TransitionError struct {
+ parent mode
+ current mode
+ destination mode
+}
+
+func (te TransitionError) Error() string {
+ if te.destination == mode(0) {
+ return fmt.Sprintf("invalid state transition: cannot read/write value while in %s", te.current)
+ }
+ if te.parent == mode(0) {
+ return fmt.Sprintf("invalid state transition: %s -> %s", te.current, te.destination)
+ }
+ return fmt.Sprintf("invalid state transition: %s -> %s; parent %s", te.current, te.destination, te.parent)
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go
new file mode 100644
index 000000000..616a3e701
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go
@@ -0,0 +1,109 @@
+// 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 bsoncodec
+
+import (
+ "reflect"
+ "sync"
+
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+)
+
+var _ ValueEncoder = &PointerCodec{}
+var _ ValueDecoder = &PointerCodec{}
+
+// PointerCodec is the Codec used for pointers.
+type PointerCodec struct {
+ ecache map[reflect.Type]ValueEncoder
+ dcache map[reflect.Type]ValueDecoder
+ l sync.RWMutex
+}
+
+// NewPointerCodec returns a PointerCodec that has been initialized.
+func NewPointerCodec() *PointerCodec {
+ return &PointerCodec{
+ ecache: make(map[reflect.Type]ValueEncoder),
+ dcache: make(map[reflect.Type]ValueDecoder),
+ }
+}
+
+// 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 bsonrw.ValueWriter, val reflect.Value) error {
+ if val.Kind() != reflect.Ptr {
+ if !val.IsValid() {
+ return vw.WriteNull()
+ }
+ return ValueEncoderError{Name: "PointerCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val}
+ }
+
+ if val.IsNil() {
+ return vw.WriteNull()
+ }
+
+ pc.l.RLock()
+ enc, ok := pc.ecache[val.Type()]
+ pc.l.RUnlock()
+ if ok {
+ if enc == nil {
+ return ErrNoEncoder{Type: val.Type()}
+ }
+ return enc.EncodeValue(ec, vw, val.Elem())
+ }
+
+ enc, err := ec.LookupEncoder(val.Type().Elem())
+ pc.l.Lock()
+ pc.ecache[val.Type()] = enc
+ pc.l.Unlock()
+ if err != nil {
+ return err
+ }
+
+ return enc.EncodeValue(ec, vw, val.Elem())
+}
+
+// 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 bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Kind() != reflect.Ptr {
+ return ValueDecoderError{Name: "PointerCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val}
+ }
+
+ if vr.Type() == bsontype.Null {
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadNull()
+ }
+ if vr.Type() == bsontype.Undefined {
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadUndefined()
+ }
+
+ if val.IsNil() {
+ val.Set(reflect.New(val.Type().Elem()))
+ }
+
+ pc.l.RLock()
+ dec, ok := pc.dcache[val.Type()]
+ pc.l.RUnlock()
+ if ok {
+ if dec == nil {
+ return ErrNoDecoder{Type: val.Type()}
+ }
+ return dec.DecodeValue(dc, vr, val.Elem())
+ }
+
+ dec, err := dc.LookupDecoder(val.Type().Elem())
+ pc.l.Lock()
+ pc.dcache[val.Type()] = dec
+ pc.l.Unlock()
+ if err != nil {
+ return err
+ }
+
+ return dec.DecodeValue(dc, vr, val.Elem())
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go
new file mode 100644
index 000000000..4cf2b01ab
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go
@@ -0,0 +1,14 @@
+// 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 bsoncodec
+
+// Proxy is an interface implemented by types that cannot themselves be directly encoded. Types
+// that implement this interface with have ProxyBSON called during the encoding process and that
+// value will be encoded in place for the implementer.
+type Proxy interface {
+ ProxyBSON() (interface{}, error)
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go
new file mode 100644
index 000000000..80644023c
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go
@@ -0,0 +1,469 @@
+// 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 bsoncodec
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "sync"
+
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+)
+
+// ErrNilType is returned when nil is passed to either LookupEncoder or LookupDecoder.
+var ErrNilType = errors.New("cannot perform a decoder lookup on <nil>")
+
+// ErrNotPointer is returned when a non-pointer type is provided to LookupDecoder.
+var ErrNotPointer = errors.New("non-pointer provided to LookupDecoder")
+
+// ErrNoEncoder is returned when there wasn't an encoder available for a type.
+type ErrNoEncoder struct {
+ Type reflect.Type
+}
+
+func (ene ErrNoEncoder) Error() string {
+ if ene.Type == nil {
+ return "no encoder found for <nil>"
+ }
+ return "no encoder found for " + ene.Type.String()
+}
+
+// ErrNoDecoder is returned when there wasn't a decoder available for a type.
+type ErrNoDecoder struct {
+ Type reflect.Type
+}
+
+func (end ErrNoDecoder) Error() string {
+ return "no decoder found for " + end.Type.String()
+}
+
+// ErrNoTypeMapEntry is returned when there wasn't a type available for the provided BSON type.
+type ErrNoTypeMapEntry struct {
+ Type bsontype.Type
+}
+
+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.
+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.
+type RegistryBuilder struct {
+ typeEncoders map[reflect.Type]ValueEncoder
+ interfaceEncoders []interfaceValueEncoder
+ kindEncoders map[reflect.Kind]ValueEncoder
+
+ typeDecoders map[reflect.Type]ValueDecoder
+ interfaceDecoders []interfaceValueDecoder
+ kindDecoders map[reflect.Kind]ValueDecoder
+
+ typeMap map[bsontype.Type]reflect.Type
+}
+
+// A Registry is used to store and retrieve codecs for types and interfaces. This type is the main
+// typed passed around and Encoders and Decoders are constructed from it.
+type Registry struct {
+ typeEncoders map[reflect.Type]ValueEncoder
+ typeDecoders map[reflect.Type]ValueDecoder
+
+ interfaceEncoders []interfaceValueEncoder
+ interfaceDecoders []interfaceValueDecoder
+
+ kindEncoders map[reflect.Kind]ValueEncoder
+ kindDecoders map[reflect.Kind]ValueDecoder
+
+ typeMap map[bsontype.Type]reflect.Type
+
+ mu sync.RWMutex
+}
+
+// NewRegistryBuilder creates a new empty RegistryBuilder.
+func NewRegistryBuilder() *RegistryBuilder {
+ return &RegistryBuilder{
+ typeEncoders: make(map[reflect.Type]ValueEncoder),
+ typeDecoders: make(map[reflect.Type]ValueDecoder),
+
+ interfaceEncoders: make([]interfaceValueEncoder, 0),
+ interfaceDecoders: make([]interfaceValueDecoder, 0),
+
+ kindEncoders: make(map[reflect.Kind]ValueEncoder),
+ kindDecoders: make(map[reflect.Kind]ValueDecoder),
+
+ typeMap: make(map[bsontype.Type]reflect.Type),
+ }
+}
+
+func buildDefaultRegistry() *Registry {
+ rb := NewRegistryBuilder()
+ defaultValueEncoders.RegisterDefaultEncoders(rb)
+ defaultValueDecoders.RegisterDefaultDecoders(rb)
+ return rb.Build()
+}
+
+// RegisterCodec will register the provided ValueCodec for the provided type.
+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 marshalling a type that is that interface. It
+// will not be called when marshalling a non-interface type that implements the interface.
+func (rb *RegistryBuilder) RegisterTypeEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder {
+ rb.typeEncoders[t] = enc
+ return rb
+}
+
+// RegisterHookEncoder will register an encoder for the provided interface type t. This encoder will be called when
+// marshalling 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.
+func (rb *RegistryBuilder) RegisterHookEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder {
+ if t.Kind() != reflect.Interface {
+ panicStr := fmt.Sprintf("RegisterHookEncoder expects a type with kind reflect.Interface, "+
+ "got type %s with kind %s", t, t.Kind())
+ panic(panicStr)
+ }
+
+ for idx, encoder := range rb.interfaceEncoders {
+ if encoder.i == t {
+ rb.interfaceEncoders[idx].ve = enc
+ return rb
+ }
+ }
+
+ rb.interfaceEncoders = append(rb.interfaceEncoders, interfaceValueEncoder{i: t, ve: 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 unmarshalling into a type that is that interface.
+// It will not be called when unmarshalling into a non-interface type that implements the interface.
+func (rb *RegistryBuilder) RegisterTypeDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder {
+ rb.typeDecoders[t] = dec
+ return rb
+}
+
+// RegisterHookDecoder will register an decoder for the provided interface type t. This decoder will be called when
+// unmarshalling 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.
+func (rb *RegistryBuilder) RegisterHookDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder {
+ if t.Kind() != reflect.Interface {
+ panicStr := fmt.Sprintf("RegisterHookDecoder expects a type with kind reflect.Interface, "+
+ "got type %s with kind %s", t, t.Kind())
+ panic(panicStr)
+ }
+
+ for idx, decoder := range rb.interfaceDecoders {
+ if decoder.i == t {
+ rb.interfaceDecoders[idx].vd = dec
+ return rb
+ }
+ }
+
+ rb.interfaceDecoders = append(rb.interfaceDecoders, interfaceValueDecoder{i: t, vd: dec})
+ return rb
+}
+
+// RegisterEncoder registers the provided type and encoder pair.
+//
+// Deprecated: Use RegisterTypeEncoder or RegisterHookEncoder instead.
+func (rb *RegistryBuilder) RegisterEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder {
+ if t == tEmpty {
+ rb.typeEncoders[t] = enc
+ return rb
+ }
+ switch t.Kind() {
+ case reflect.Interface:
+ for idx, ir := range rb.interfaceEncoders {
+ if ir.i == t {
+ rb.interfaceEncoders[idx].ve = enc
+ return rb
+ }
+ }
+
+ rb.interfaceEncoders = append(rb.interfaceEncoders, interfaceValueEncoder{i: t, ve: enc})
+ default:
+ rb.typeEncoders[t] = enc
+ }
+ return rb
+}
+
+// RegisterDecoder registers the provided type and decoder pair.
+//
+// Deprecated: Use RegisterTypeDecoder or RegisterHookDecoder instead.
+func (rb *RegistryBuilder) RegisterDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder {
+ if t == nil {
+ rb.typeDecoders[nil] = dec
+ return rb
+ }
+ if t == tEmpty {
+ rb.typeDecoders[t] = dec
+ return rb
+ }
+ switch t.Kind() {
+ case reflect.Interface:
+ for idx, ir := range rb.interfaceDecoders {
+ if ir.i == t {
+ rb.interfaceDecoders[idx].vd = dec
+ return rb
+ }
+ }
+
+ rb.interfaceDecoders = append(rb.interfaceDecoders, interfaceValueDecoder{i: t, vd: dec})
+ default:
+ rb.typeDecoders[t] = dec
+ }
+ return rb
+}
+
+// RegisterDefaultEncoder will registr the provided ValueEncoder to the provided
+// kind.
+func (rb *RegistryBuilder) RegisterDefaultEncoder(kind reflect.Kind, enc ValueEncoder) *RegistryBuilder {
+ rb.kindEncoders[kind] = enc
+ return rb
+}
+
+// RegisterDefaultDecoder will register the provided ValueDecoder to the
+// provided kind.
+func (rb *RegistryBuilder) RegisterDefaultDecoder(kind reflect.Kind, dec ValueDecoder) *RegistryBuilder {
+ rb.kindDecoders[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 bsontype.EmbeddedDocument should be registered. For example, to force BSON documents
+// to decode to bson.Raw, use the following code:
+//
+// rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.Raw{}))
+func (rb *RegistryBuilder) RegisterTypeMapEntry(bt bsontype.Type, rt reflect.Type) *RegistryBuilder {
+ rb.typeMap[bt] = rt
+ return rb
+}
+
+// Build creates a Registry from the current state of this RegistryBuilder.
+func (rb *RegistryBuilder) Build() *Registry {
+ registry := new(Registry)
+
+ registry.typeEncoders = make(map[reflect.Type]ValueEncoder)
+ for t, enc := range rb.typeEncoders {
+ registry.typeEncoders[t] = enc
+ }
+
+ registry.typeDecoders = make(map[reflect.Type]ValueDecoder)
+ for t, dec := range rb.typeDecoders {
+ registry.typeDecoders[t] = dec
+ }
+
+ registry.interfaceEncoders = make([]interfaceValueEncoder, len(rb.interfaceEncoders))
+ copy(registry.interfaceEncoders, rb.interfaceEncoders)
+
+ registry.interfaceDecoders = make([]interfaceValueDecoder, len(rb.interfaceDecoders))
+ copy(registry.interfaceDecoders, rb.interfaceDecoders)
+
+ registry.kindEncoders = make(map[reflect.Kind]ValueEncoder)
+ for kind, enc := range rb.kindEncoders {
+ registry.kindEncoders[kind] = enc
+ }
+
+ registry.kindDecoders = make(map[reflect.Kind]ValueDecoder)
+ for kind, dec := range rb.kindDecoders {
+ registry.kindDecoders[kind] = dec
+ }
+
+ registry.typeMap = make(map[bsontype.Type]reflect.Type)
+ for bt, rt := range rb.typeMap {
+ registry.typeMap[bt] = rt
+ }
+
+ return registry
+}
+
+// LookupEncoder inspects the registry for an encoder for the given type. The lookup precedence works as follows:
+//
+// 1. An encoder registered for the exact type. If the given type represents an interface, an encoder registered using
+// RegisterTypeEncoder for the interface will be selected.
+//
+// 2. An encoder registered using RegisterHookEncoder for an interface implemented by the type or by a pointer to the
+// type.
+//
+// 3. An encoder registered for the reflect.Kind of the value.
+//
+// If no encoder is found, an error of type ErrNoEncoder is returned.
+func (r *Registry) LookupEncoder(t reflect.Type) (ValueEncoder, error) {
+ encodererr := ErrNoEncoder{Type: t}
+ r.mu.RLock()
+ enc, found := r.lookupTypeEncoder(t)
+ r.mu.RUnlock()
+ if found {
+ if enc == nil {
+ return nil, ErrNoEncoder{Type: t}
+ }
+ return enc, nil
+ }
+
+ enc, found = r.lookupInterfaceEncoder(t, true)
+ if found {
+ r.mu.Lock()
+ r.typeEncoders[t] = enc
+ r.mu.Unlock()
+ return enc, nil
+ }
+
+ if t == nil {
+ r.mu.Lock()
+ r.typeEncoders[t] = nil
+ r.mu.Unlock()
+ return nil, encodererr
+ }
+
+ enc, found = r.kindEncoders[t.Kind()]
+ if !found {
+ r.mu.Lock()
+ r.typeEncoders[t] = nil
+ r.mu.Unlock()
+ return nil, encodererr
+ }
+
+ r.mu.Lock()
+ r.typeEncoders[t] = enc
+ r.mu.Unlock()
+ return enc, nil
+}
+
+func (r *Registry) lookupTypeEncoder(t reflect.Type) (ValueEncoder, bool) {
+ enc, found := r.typeEncoders[t]
+ return enc, found
+}
+
+func (r *Registry) lookupInterfaceEncoder(t reflect.Type, allowAddr bool) (ValueEncoder, bool) {
+ if t == nil {
+ return nil, false
+ }
+ for _, ienc := range r.interfaceEncoders {
+ if t.Implements(ienc.i) {
+ return ienc.ve, true
+ }
+ if allowAddr && t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(ienc.i) {
+ // if *t implements an interface, this will catch if t implements an interface further ahead
+ // in interfaceEncoders
+ defaultEnc, found := r.lookupInterfaceEncoder(t, false)
+ if !found {
+ defaultEnc = r.kindEncoders[t.Kind()]
+ }
+ return newCondAddrEncoder(ienc.ve, defaultEnc), true
+ }
+ }
+ return nil, false
+}
+
+// LookupDecoder inspects the registry for an decoder for the given type. The lookup precedence works as follows:
+//
+// 1. A decoder registered for the exact type. If the given type represents an interface, a decoder registered using
+// RegisterTypeDecoder for the interface will be selected.
+//
+// 2. A decoder registered using RegisterHookDecoder for an interface implemented by the type or by a pointer to the
+// type.
+//
+// 3. A decoder registered for the reflect.Kind of the value.
+//
+// If no decoder is found, an error of type ErrNoDecoder is returned.
+func (r *Registry) LookupDecoder(t reflect.Type) (ValueDecoder, error) {
+ if t == nil {
+ return nil, ErrNilType
+ }
+ decodererr := ErrNoDecoder{Type: t}
+ r.mu.RLock()
+ dec, found := r.lookupTypeDecoder(t)
+ r.mu.RUnlock()
+ if found {
+ if dec == nil {
+ return nil, ErrNoDecoder{Type: t}
+ }
+ return dec, nil
+ }
+
+ dec, found = r.lookupInterfaceDecoder(t, true)
+ if found {
+ r.mu.Lock()
+ r.typeDecoders[t] = dec
+ r.mu.Unlock()
+ return dec, nil
+ }
+
+ dec, found = r.kindDecoders[t.Kind()]
+ if !found {
+ r.mu.Lock()
+ r.typeDecoders[t] = nil
+ r.mu.Unlock()
+ return nil, decodererr
+ }
+
+ r.mu.Lock()
+ r.typeDecoders[t] = dec
+ r.mu.Unlock()
+ return dec, nil
+}
+
+func (r *Registry) lookupTypeDecoder(t reflect.Type) (ValueDecoder, bool) {
+ dec, found := r.typeDecoders[t]
+ return dec, found
+}
+
+func (r *Registry) lookupInterfaceDecoder(t reflect.Type, allowAddr bool) (ValueDecoder, bool) {
+ for _, idec := range r.interfaceDecoders {
+ if t.Implements(idec.i) {
+ return idec.vd, true
+ }
+ if allowAddr && t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(idec.i) {
+ // if *t implements an interface, this will catch if t implements an interface further ahead
+ // in interfaceDecoders
+ defaultDec, found := r.lookupInterfaceDecoder(t, false)
+ if !found {
+ defaultDec = r.kindDecoders[t.Kind()]
+ }
+ return newCondAddrDecoder(idec.vd, defaultDec), true
+ }
+ }
+ return nil, false
+}
+
+// LookupTypeMapEntry inspects the registry's type map for a Go type for the corresponding BSON
+// type. If no type is found, ErrNoTypeMapEntry is returned.
+func (r *Registry) LookupTypeMapEntry(bt bsontype.Type) (reflect.Type, error) {
+ t, ok := r.typeMap[bt]
+ if !ok || t == nil {
+ return nil, ErrNoTypeMapEntry{Type: bt}
+ }
+ return t, nil
+}
+
+type interfaceValueEncoder struct {
+ i reflect.Type
+ ve ValueEncoder
+}
+
+type interfaceValueDecoder struct {
+ i reflect.Type
+ vd ValueDecoder
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go
new file mode 100644
index 000000000..3c1b6b860
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go
@@ -0,0 +1,199 @@
+// 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 bsoncodec
+
+import (
+ "fmt"
+ "reflect"
+
+ "go.mongodb.org/mongo-driver/bson/bsonoptions"
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+var defaultSliceCodec = NewSliceCodec()
+
+// SliceCodec is the Codec used for slice values.
+type SliceCodec struct {
+ EncodeNilAsEmpty bool
+}
+
+var _ ValueCodec = &MapCodec{}
+
+// NewSliceCodec returns a MapCodec with options opts.
+func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec {
+ sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...)
+
+ codec := SliceCodec{}
+ if sliceOpt.EncodeNilAsEmpty != nil {
+ codec.EncodeNilAsEmpty = *sliceOpt.EncodeNilAsEmpty
+ }
+ return &codec
+}
+
+// EncodeValue is the ValueEncoder for slice types.
+func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.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 {
+ return vw.WriteNull()
+ }
+
+ // If we have a []byte we want to treat it as a binary instead of as an array.
+ if val.Type().Elem() == tByte {
+ var byteSlice []byte
+ for idx := 0; idx < val.Len(); idx++ {
+ byteSlice = append(byteSlice, val.Index(idx).Interface().(byte))
+ }
+ return vw.WriteBinary(byteSlice)
+ }
+
+ // If we have a []primitive.E we want to treat it as a document instead of as an array.
+ if val.Type().ConvertibleTo(tD) {
+ d := val.Convert(tD).Interface().(primitive.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 := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx))
+ if lookupErr != nil && lookupErr != errInvalidValue {
+ return lookupErr
+ }
+
+ vw, err := aw.WriteArrayElement()
+ if err != nil {
+ return err
+ }
+
+ if 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()
+}
+
+// DecodeValue is the ValueDecoder for slice types.
+func (sc *SliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Kind() != reflect.Slice {
+ return ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val}
+ }
+
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Array:
+ case bsontype.Null:
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadNull()
+ case bsontype.Undefined:
+ val.Set(reflect.Zero(val.Type()))
+ return vr.ReadUndefined()
+ case bsontype.Type(0), bsontype.EmbeddedDocument:
+ if val.Type().Elem() != tE {
+ return fmt.Errorf("cannot decode document into %s", val.Type())
+ }
+ case bsontype.Binary:
+ if val.Type().Elem() != tByte {
+ return fmt.Errorf("SliceDecodeValue can only decode a binary into a byte array, got %v", vrType)
+ }
+ data, subtype, err := vr.ReadBinary()
+ if err != nil {
+ return err
+ }
+ if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
+ return fmt.Errorf("SliceDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype)
+ }
+
+ if val.IsNil() {
+ val.Set(reflect.MakeSlice(val.Type(), 0, len(data)))
+ }
+
+ val.SetLen(0)
+ for _, elem := range data {
+ val.Set(reflect.Append(val, reflect.ValueOf(elem)))
+ }
+ return nil
+ case bsontype.String:
+ if sliceType := val.Type().Elem(); sliceType != tByte {
+ return fmt.Errorf("SliceDecodeValue can only decode a string into a byte array, got %v", sliceType)
+ }
+ str, err := vr.ReadString()
+ if err != nil {
+ return err
+ }
+ byteStr := []byte(str)
+
+ if val.IsNil() {
+ val.Set(reflect.MakeSlice(val.Type(), 0, len(byteStr)))
+ }
+
+ val.SetLen(0)
+ for _, elem := range byteStr {
+ val.Set(reflect.Append(val, reflect.ValueOf(elem)))
+ }
+ return nil
+ default:
+ return fmt.Errorf("cannot decode %v into a slice", vrType)
+ }
+
+ var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error)
+ switch val.Type().Elem() {
+ case tE:
+ dc.Ancestor = val.Type()
+ elemsFunc = defaultValueDecoders.decodeD
+ default:
+ elemsFunc = defaultValueDecoders.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
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go
new file mode 100644
index 000000000..5332b7c3b
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go
@@ -0,0 +1,119 @@
+// 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 bsoncodec
+
+import (
+ "fmt"
+ "reflect"
+
+ "go.mongodb.org/mongo-driver/bson/bsonoptions"
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+)
+
+// StringCodec is the Codec used for struct values.
+type StringCodec struct {
+ DecodeObjectIDAsHex bool
+}
+
+var (
+ defaultStringCodec = NewStringCodec()
+
+ _ ValueCodec = defaultStringCodec
+ _ typeDecoder = defaultStringCodec
+)
+
+// NewStringCodec returns a StringCodec with options opts.
+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(ectx EncodeContext, vw bsonrw.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())
+}
+
+func (sc *StringCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t.Kind() != reflect.String {
+ return emptyValue, ValueDecoderError{
+ Name: "StringDecodeValue",
+ Kinds: []reflect.Kind{reflect.String},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var str string
+ var err error
+ switch vr.Type() {
+ case bsontype.String:
+ str, err = vr.ReadString()
+ if err != nil {
+ return emptyValue, err
+ }
+ case bsontype.ObjectID:
+ oid, err := vr.ReadObjectID()
+ if err != nil {
+ return emptyValue, err
+ }
+ if sc.DecodeObjectIDAsHex {
+ str = oid.Hex()
+ } else {
+ byteArray := [12]byte(oid)
+ str = string(byteArray[:])
+ }
+ case bsontype.Symbol:
+ str, err = vr.ReadSymbol()
+ if err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Binary:
+ data, subtype, err := vr.ReadBinary()
+ if err != nil {
+ return emptyValue, err
+ }
+ if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
+ return emptyValue, decodeBinaryError{subtype: subtype, typeName: "string"}
+ }
+ str = string(data)
+ case bsontype.Null:
+ if err = vr.ReadNull(); err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Undefined:
+ if err = vr.ReadUndefined(); err != nil {
+ return emptyValue, err
+ }
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a string type", vr.Type())
+ }
+
+ return reflect.ValueOf(str), nil
+}
+
+// DecodeValue is the ValueDecoder for string types.
+func (sc *StringCodec) DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Kind() != reflect.String {
+ return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val}
+ }
+
+ elem, err := sc.decodeType(dctx, vr, val.Type())
+ if err != nil {
+ return err
+ }
+
+ val.SetString(elem.String())
+ return nil
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go
new file mode 100644
index 000000000..be3f2081e
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go
@@ -0,0 +1,664 @@
+// 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 bsoncodec
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ "go.mongodb.org/mongo-driver/bson/bsonoptions"
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+)
+
+// DecodeError represents an error that occurs when unmarshalling BSON bytes into a native Go type.
+type DecodeError struct {
+ keys []string
+ wrapped error
+}
+
+// Unwrap returns the underlying error
+func (de *DecodeError) Unwrap() error {
+ return de.wrapped
+}
+
+// Error implements the error interface.
+func (de *DecodeError) Error() string {
+ // The keys are stored in reverse order because the de.keys slice is builtup while propagating the error up the
+ // stack of BSON keys, so we call de.Keys(), which reverses them.
+ keyPath := strings.Join(de.Keys(), ".")
+ return fmt.Sprintf("error decoding key %s: %v", keyPath, de.wrapped)
+}
+
+// Keys returns the BSON key path that caused an error as a slice of strings. The keys in the slice are in top-down
+// order. For example, if the document being unmarshalled was {a: {b: {c: 1}}} and the value for c was supposed to be
+// a string, the keys slice will be ["a", "b", "c"].
+func (de *DecodeError) Keys() []string {
+ reversedKeys := make([]string, 0, len(de.keys))
+ for idx := len(de.keys) - 1; idx >= 0; idx-- {
+ reversedKeys = append(reversedKeys, de.keys[idx])
+ }
+
+ return reversedKeys
+}
+
+// Zeroer allows custom struct types to implement a report of zero
+// state. All struct types that don't implement Zeroer or where IsZero
+// returns false are considered to be not zero.
+type Zeroer interface {
+ IsZero() bool
+}
+
+// StructCodec is the Codec used for struct values.
+type StructCodec struct {
+ cache map[reflect.Type]*structDescription
+ l sync.RWMutex
+ parser StructTagParser
+ DecodeZeroStruct bool
+ DecodeDeepZeroInline bool
+ EncodeOmitDefaultStruct bool
+ AllowUnexportedFields bool
+ OverwriteDuplicatedInlinedFields bool
+}
+
+var _ ValueEncoder = &StructCodec{}
+var _ ValueDecoder = &StructCodec{}
+
+// NewStructCodec returns a StructCodec that uses p for struct tag parsing.
+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{
+ cache: make(map[reflect.Type]*structDescription),
+ parser: p,
+ }
+
+ 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
+ }
+
+ return codec, nil
+}
+
+// EncodeValue handles encoding generic struct types.
+func (sc *StructCodec) EncodeValue(r EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Kind() != reflect.Struct {
+ return ValueEncoderError{Name: "StructCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val}
+ }
+
+ sd, err := sc.describeStruct(r.Registry, val.Type())
+ if err != nil {
+ return err
+ }
+
+ dw, err := vw.WriteDocument()
+ if err != nil {
+ return err
+ }
+ var rv reflect.Value
+ for _, desc := range sd.fl {
+ if desc.inline == nil {
+ rv = val.Field(desc.idx)
+ } else {
+ rv, err = fieldByIndexErr(val, desc.inline)
+ if err != nil {
+ continue
+ }
+ }
+
+ desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(r, desc.encoder, rv)
+
+ if err != nil && err != errInvalidValue {
+ return err
+ }
+
+ if err == errInvalidValue {
+ if desc.omitEmpty {
+ continue
+ }
+ vw2, err := dw.WriteDocumentElement(desc.name)
+ if err != nil {
+ return err
+ }
+ err = vw2.WriteNull()
+ if err != nil {
+ return err
+ }
+ continue
+ }
+
+ if desc.encoder == nil {
+ return ErrNoEncoder{Type: rv.Type()}
+ }
+
+ encoder := desc.encoder
+
+ var isZero bool
+ rvInterface := rv.Interface()
+ if cz, ok := encoder.(CodecZeroer); ok {
+ isZero = cz.IsTypeZero(rvInterface)
+ } else if rv.Kind() == reflect.Interface {
+ // sc.isZero will not treat an interface rv as an interface, so we need to check for the zero interface separately.
+ isZero = rv.IsNil()
+ } else {
+ isZero = sc.isZero(rvInterface)
+ }
+ if desc.omitEmpty && isZero {
+ continue
+ }
+
+ vw2, err := dw.WriteDocumentElement(desc.name)
+ if err != nil {
+ return err
+ }
+
+ ectx := EncodeContext{Registry: r.Registry, MinSize: desc.minSize}
+ err = encoder.EncodeValue(ectx, vw2, rv)
+ if err != nil {
+ return err
+ }
+ }
+
+ if sd.inlineMap >= 0 {
+ rv := val.Field(sd.inlineMap)
+ collisionFn := func(key string) bool {
+ _, exists := sd.fm[key]
+ return exists
+ }
+
+ return defaultMapCodec.mapEncodeValue(r, dw, rv, collisionFn)
+ }
+
+ return dw.WriteDocumentEnd()
+}
+
+func newDecodeError(key string, original error) error {
+ de, ok := original.(*DecodeError)
+ if !ok {
+ return &DecodeError{
+ keys: []string{key},
+ wrapped: original,
+ }
+ }
+
+ de.keys = append(de.keys, key)
+ return de
+}
+
+// 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(r DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Kind() != reflect.Struct {
+ return ValueDecoderError{Name: "StructCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val}
+ }
+
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Type(0), bsontype.EmbeddedDocument:
+ case bsontype.Null:
+ if err := vr.ReadNull(); err != nil {
+ return err
+ }
+
+ val.Set(reflect.Zero(val.Type()))
+ return nil
+ case bsontype.Undefined:
+ if err := vr.ReadUndefined(); err != nil {
+ return err
+ }
+
+ val.Set(reflect.Zero(val.Type()))
+ return nil
+ default:
+ return fmt.Errorf("cannot decode %v into a %s", vrType, val.Type())
+ }
+
+ sd, err := sc.describeStruct(r.Registry, val.Type())
+ if err != nil {
+ return err
+ }
+
+ if sc.DecodeZeroStruct {
+ val.Set(reflect.Zero(val.Type()))
+ }
+ if sc.DecodeDeepZeroInline && sd.inline {
+ val.Set(deepZero(val.Type()))
+ }
+
+ var decoder ValueDecoder
+ var inlineMap reflect.Value
+ if sd.inlineMap >= 0 {
+ inlineMap = val.Field(sd.inlineMap)
+ decoder, err = r.LookupDecoder(inlineMap.Type().Elem())
+ if err != nil {
+ return err
+ }
+ }
+
+ dr, err := vr.ReadDocument()
+ if err != nil {
+ return err
+ }
+
+ for {
+ name, vr, err := dr.ReadElement()
+ if err == bsonrw.ErrEOD {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ fd, exists := sd.fm[name]
+ if !exists {
+ // if the original name isn't found in the struct description, try again with the name in lowercase
+ // this could match if a BSON tag isn't specified because by default, describeStruct lowercases all field
+ // names
+ fd, exists = sd.fm[strings.ToLower(name)]
+ }
+
+ if !exists {
+ if sd.inlineMap < 0 {
+ // The encoding/json package requires a flag to return on error for non-existent fields.
+ // This functionality seems appropriate for the struct codec.
+ err = vr.Skip()
+ if err != nil {
+ return err
+ }
+ continue
+ }
+
+ if inlineMap.IsNil() {
+ inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+ }
+
+ elem := reflect.New(inlineMap.Type().Elem()).Elem()
+ r.Ancestor = inlineMap.Type()
+ err = decoder.DecodeValue(r, vr, elem)
+ if err != nil {
+ return err
+ }
+ inlineMap.SetMapIndex(reflect.ValueOf(name), elem)
+ continue
+ }
+
+ var field reflect.Value
+ if fd.inline == nil {
+ field = val.Field(fd.idx)
+ } else {
+ field, err = getInlineField(val, fd.inline)
+ if err != nil {
+ return err
+ }
+ }
+
+ if !field.CanSet() { // Being settable is a super set of being addressable.
+ innerErr := fmt.Errorf("field %v is not settable", field)
+ return newDecodeError(fd.name, innerErr)
+ }
+ if field.Kind() == reflect.Ptr && field.IsNil() {
+ field.Set(reflect.New(field.Type().Elem()))
+ }
+ field = field.Addr()
+
+ dctx := DecodeContext{Registry: r.Registry, Truncate: fd.truncate || r.Truncate}
+ if fd.decoder == nil {
+ return newDecodeError(fd.name, ErrNoDecoder{Type: field.Elem().Type()})
+ }
+
+ err = fd.decoder.DecodeValue(dctx, vr, field.Elem())
+ if err != nil {
+ return newDecodeError(fd.name, err)
+ }
+ }
+
+ return nil
+}
+
+func (sc *StructCodec) isZero(i interface{}) bool {
+ v := reflect.ValueOf(i)
+
+ // check the value validity
+ if !v.IsValid() {
+ return true
+ }
+
+ if z, ok := v.Interface().(Zeroer); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
+ return z.IsZero()
+ }
+
+ switch v.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ case reflect.Struct:
+ if sc.EncodeOmitDefaultStruct {
+ vt := v.Type()
+ if vt == tTime {
+ return v.Interface().(time.Time).IsZero()
+ }
+ for i := 0; i < v.NumField(); i++ {
+ if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous {
+ continue // Private field
+ }
+ fld := v.Field(i)
+ if !sc.isZero(fld.Interface()) {
+ return false
+ }
+ }
+ return true
+ }
+ }
+
+ return false
+}
+
+type structDescription struct {
+ fm map[string]fieldDescription
+ fl []fieldDescription
+ inlineMap int
+ inline bool
+}
+
+type fieldDescription struct {
+ name string // BSON key name
+ fieldName string // struct field name
+ idx int
+ omitEmpty bool
+ minSize bool
+ truncate bool
+ inline []int
+ encoder ValueEncoder
+ decoder ValueDecoder
+}
+
+type byIndex []fieldDescription
+
+func (bi byIndex) Len() int { return len(bi) }
+
+func (bi byIndex) Swap(i, j int) { bi[i], bi[j] = bi[j], bi[i] }
+
+func (bi byIndex) Less(i, j int) bool {
+ // If a field is inlined, its index in the top level struct is stored at inline[0]
+ iIdx, jIdx := bi[i].idx, bi[j].idx
+ if len(bi[i].inline) > 0 {
+ iIdx = bi[i].inline[0]
+ }
+ if len(bi[j].inline) > 0 {
+ jIdx = bi[j].inline[0]
+ }
+ if iIdx != jIdx {
+ return iIdx < jIdx
+ }
+ for k, biik := range bi[i].inline {
+ if k >= len(bi[j].inline) {
+ return false
+ }
+ if biik != bi[j].inline[k] {
+ return biik < bi[j].inline[k]
+ }
+ }
+ return len(bi[i].inline) < len(bi[j].inline)
+}
+
+func (sc *StructCodec) describeStruct(r *Registry, t reflect.Type) (*structDescription, error) {
+ // We need to analyze the struct, including getting the tags, collecting
+ // information about inlining, and create a map of the field name to the field.
+ sc.l.RLock()
+ ds, exists := sc.cache[t]
+ sc.l.RUnlock()
+ if exists {
+ return ds, nil
+ }
+
+ numFields := t.NumField()
+ sd := &structDescription{
+ fm: make(map[string]fieldDescription, numFields),
+ fl: make([]fieldDescription, 0, numFields),
+ inlineMap: -1,
+ }
+
+ var fields []fieldDescription
+ for i := 0; i < numFields; i++ {
+ sf := t.Field(i)
+ if sf.PkgPath != "" && (!sc.AllowUnexportedFields || !sf.Anonymous) {
+ // field is private or unexported fields aren't allowed, ignore
+ continue
+ }
+
+ sfType := sf.Type
+ encoder, err := r.LookupEncoder(sfType)
+ if err != nil {
+ encoder = nil
+ }
+ decoder, err := r.LookupDecoder(sfType)
+ if err != nil {
+ decoder = nil
+ }
+
+ description := fieldDescription{
+ fieldName: sf.Name,
+ idx: i,
+ encoder: encoder,
+ decoder: decoder,
+ }
+
+ stags, err := sc.parser.ParseStructTags(sf)
+ if err != nil {
+ return nil, err
+ }
+ if stags.Skip {
+ continue
+ }
+ description.name = stags.Name
+ description.omitEmpty = stags.OmitEmpty
+ description.minSize = stags.MinSize
+ description.truncate = stags.Truncate
+
+ if stags.Inline {
+ sd.inline = true
+ switch sfType.Kind() {
+ case reflect.Map:
+ if sd.inlineMap >= 0 {
+ return nil, errors.New("(struct " + t.String() + ") multiple inline maps")
+ }
+ if sfType.Key() != tString {
+ return nil, errors.New("(struct " + t.String() + ") inline map must have a string keys")
+ }
+ sd.inlineMap = description.idx
+ case reflect.Ptr:
+ sfType = sfType.Elem()
+ if sfType.Kind() != reflect.Struct {
+ return nil, fmt.Errorf("(struct %s) inline fields must be a struct, a struct pointer, or a map", t.String())
+ }
+ fallthrough
+ case reflect.Struct:
+ inlinesf, err := sc.describeStruct(r, sfType)
+ if err != nil {
+ return nil, err
+ }
+ for _, fd := range inlinesf.fl {
+ if fd.inline == nil {
+ fd.inline = []int{i, fd.idx}
+ } else {
+ fd.inline = append([]int{i}, fd.inline...)
+ }
+ fields = append(fields, fd)
+
+ }
+ default:
+ return nil, fmt.Errorf("(struct %s) inline fields must be a struct, a struct pointer, or a map", t.String())
+ }
+ continue
+ }
+ fields = append(fields, description)
+ }
+
+ // Sort fieldDescriptions by name and use dominance rules to determine which should be added for each name
+ sort.Slice(fields, func(i, j int) bool {
+ x := fields
+ // sort field by name, breaking ties with depth, then
+ // breaking ties with index sequence.
+ if x[i].name != x[j].name {
+ return x[i].name < x[j].name
+ }
+ if len(x[i].inline) != len(x[j].inline) {
+ return len(x[i].inline) < len(x[j].inline)
+ }
+ return byIndex(x).Less(i, j)
+ })
+
+ for advance, i := 0, 0; i < len(fields); i += advance {
+ // One iteration per name.
+ // Find the sequence of fields with the name of this first field.
+ fi := fields[i]
+ name := fi.name
+ for advance = 1; i+advance < len(fields); advance++ {
+ fj := fields[i+advance]
+ if fj.name != name {
+ break
+ }
+ }
+ if advance == 1 { // Only one field with this name
+ sd.fl = append(sd.fl, fi)
+ sd.fm[name] = fi
+ continue
+ }
+ dominant, ok := dominantField(fields[i : i+advance])
+ if !ok || !sc.OverwriteDuplicatedInlinedFields {
+ return nil, fmt.Errorf("struct %s has duplicated key %s", t.String(), name)
+ }
+ sd.fl = append(sd.fl, dominant)
+ sd.fm[name] = dominant
+ }
+
+ sort.Sort(byIndex(sd.fl))
+
+ sc.l.Lock()
+ sc.cache[t] = sd
+ sc.l.Unlock()
+
+ return sd, nil
+}
+
+// dominantField looks through the fields, all of which are known to
+// have the same name, to find the single field that dominates the
+// others using Go's inlining rules. If there are multiple top-level
+// fields, the boolean will be false: This condition is an error in Go
+// and we skip all the fields.
+func dominantField(fields []fieldDescription) (fieldDescription, bool) {
+ // The fields are sorted in increasing index-length order, then by presence of tag.
+ // That means that the first field is the dominant one. We need only check
+ // for error cases: two fields at top level.
+ if len(fields) > 1 &&
+ len(fields[0].inline) == len(fields[1].inline) {
+ return fieldDescription{}, false
+ }
+ return fields[0], true
+}
+
+func fieldByIndexErr(v reflect.Value, index []int) (result reflect.Value, err error) {
+ defer func() {
+ if recovered := recover(); recovered != nil {
+ switch r := recovered.(type) {
+ case string:
+ err = fmt.Errorf("%s", r)
+ case error:
+ err = r
+ }
+ }
+ }()
+
+ result = v.FieldByIndex(index)
+ return
+}
+
+func getInlineField(val reflect.Value, index []int) (reflect.Value, error) {
+ field, err := fieldByIndexErr(val, index)
+ if err == nil {
+ return field, nil
+ }
+
+ // if parent of this element doesn't exist, fix its parent
+ inlineParent := index[:len(index)-1]
+ var fParent reflect.Value
+ if fParent, err = fieldByIndexErr(val, inlineParent); err != nil {
+ fParent, err = getInlineField(val, inlineParent)
+ if err != nil {
+ return fParent, err
+ }
+ }
+ fParent.Set(reflect.New(fParent.Type().Elem()))
+
+ return fieldByIndexErr(val, index)
+}
+
+// DeepZero returns recursive zero object
+func deepZero(st reflect.Type) (result reflect.Value) {
+ result = reflect.Indirect(reflect.New(st))
+
+ if result.Kind() == reflect.Struct {
+ for i := 0; i < result.NumField(); i++ {
+ if f := result.Field(i); f.Kind() == reflect.Ptr {
+ if f.CanInterface() {
+ if ft := reflect.TypeOf(f.Interface()); ft.Elem().Kind() == reflect.Struct {
+ result.Field(i).Set(recursivePointerTo(deepZero(ft.Elem())))
+ }
+ }
+ }
+ }
+ }
+
+ return
+}
+
+// recursivePointerTo calls reflect.New(v.Type) but recursively for its fields inside
+func recursivePointerTo(v reflect.Value) reflect.Value {
+ v = reflect.Indirect(v)
+ result := reflect.New(v.Type())
+ if v.Kind() == reflect.Struct {
+ for i := 0; i < v.NumField(); i++ {
+ if f := v.Field(i); f.Kind() == reflect.Ptr {
+ if f.Elem().Kind() == reflect.Struct {
+ result.Elem().Field(i).Set(recursivePointerTo(f))
+ }
+ }
+ }
+ }
+
+ return result
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go
new file mode 100644
index 000000000..62708c5c7
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go
@@ -0,0 +1,139 @@
+// 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 bsoncodec
+
+import (
+ "reflect"
+ "strings"
+)
+
+// StructTagParser returns the struct tags for a given struct field.
+type StructTagParser interface {
+ ParseStructTags(reflect.StructField) (StructTags, error)
+}
+
+// StructTagParserFunc is an adapter that allows a generic function to be used
+// as a StructTagParser.
+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
+// the encoding and decoding process.
+//
+// In the case of a struct, the lowercased field name is used as the key for each exported
+// field but this behavior may be changed using a struct tag. The tag may also contain flags to
+// adjust the marshalling behavior for the field.
+//
+// The properties are defined below:
+//
+// OmitEmpty Only include the field if it's not set to the zero value for the type or to
+// empty slices or maps.
+//
+// MinSize Marshal an integer of a type larger than 32 bits value as an int32, if that's
+// feasible while preserving the numeric value.
+//
+// Truncate When unmarshaling a BSON double, it is permitted to lose precision to fit within
+// a float32.
+//
+// Inline Inline the field, which must be a struct or a map, causing all of its fields
+// or keys to be processed as if they were part of the outer struct. For maps,
+// keys must not conflict with the bson keys of other struct fields.
+//
+// Skip This struct field should be skipped. This is usually denoted by parsing a "-"
+// for the name.
+//
+// TODO(skriptble): Add tags for undefined as nil and for null as nil.
+type StructTags struct {
+ Name string
+ OmitEmpty bool
+ MinSize bool
+ Truncate bool
+ Inline bool
+ Skip bool
+}
+
+// DefaultStructTagParser is the StructTagParser used by the StructCodec by default.
+// It will handle the bson struct tag. See the documentation for StructTags to see
+// what each of the returned fields means.
+//
+// If there is no name in the struct tag fields, the struct field name is lowercased.
+// The tag formats accepted are:
+//
+// "[<key>][,<flag1>[,<flag2>]]"
+//
+// `(...) bson:"[<key>][,<flag1>[,<flag2>]]" (...)`
+//
+// An example:
+//
+// type T struct {
+// A bool
+// B int "myb"
+// C string "myc,omitempty"
+// D string `bson:",omitempty" json:"jsonkey"`
+// E int64 ",minsize"
+// F int64 "myf,omitempty,minsize"
+// }
+//
+// 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.
+var DefaultStructTagParser StructTagParserFunc = func(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 {
+ 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
+ }
+
+ for idx, str := range strings.Split(tag, ",") {
+ if idx == 0 && str != "" {
+ key = str
+ }
+ switch str {
+ case "omitempty":
+ st.OmitEmpty = true
+ case "minsize":
+ st.MinSize = true
+ case "truncate":
+ st.Truncate = true
+ case "inline":
+ st.Inline = true
+ }
+ }
+
+ 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.
+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)
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go
new file mode 100644
index 000000000..ec7e30f72
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go
@@ -0,0 +1,127 @@
+// 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 bsoncodec
+
+import (
+ "fmt"
+ "reflect"
+ "time"
+
+ "go.mongodb.org/mongo-driver/bson/bsonoptions"
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+const (
+ timeFormatString = "2006-01-02T15:04:05.999Z07:00"
+)
+
+// TimeCodec is the Codec used for time.Time values.
+type TimeCodec struct {
+ UseLocalTimeZone bool
+}
+
+var (
+ defaultTimeCodec = NewTimeCodec()
+
+ _ ValueCodec = defaultTimeCodec
+ _ typeDecoder = defaultTimeCodec
+)
+
+// NewTimeCodec returns a TimeCodec with options opts.
+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 bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ if t != tTime {
+ return emptyValue, ValueDecoderError{
+ Name: "TimeDecodeValue",
+ Types: []reflect.Type{tTime},
+ Received: reflect.Zero(t),
+ }
+ }
+
+ var timeVal time.Time
+ switch vrType := vr.Type(); vrType {
+ case bsontype.DateTime:
+ dt, err := vr.ReadDateTime()
+ if err != nil {
+ return emptyValue, err
+ }
+ timeVal = time.Unix(dt/1000, dt%1000*1000000)
+ case bsontype.String:
+ // assume strings are in the isoTimeFormat
+ timeStr, err := vr.ReadString()
+ if err != nil {
+ return emptyValue, err
+ }
+ timeVal, err = time.Parse(timeFormatString, timeStr)
+ if err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Int64:
+ i64, err := vr.ReadInt64()
+ if err != nil {
+ return emptyValue, err
+ }
+ timeVal = time.Unix(i64/1000, i64%1000*1000000)
+ case bsontype.Timestamp:
+ t, _, err := vr.ReadTimestamp()
+ if err != nil {
+ return emptyValue, err
+ }
+ timeVal = time.Unix(int64(t), 0)
+ case bsontype.Null:
+ if err := vr.ReadNull(); err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Undefined:
+ if err := vr.ReadUndefined(); err != nil {
+ return emptyValue, err
+ }
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into a time.Time", vrType)
+ }
+
+ if !tc.UseLocalTimeZone {
+ timeVal = timeVal.UTC()
+ }
+ return reflect.ValueOf(timeVal), nil
+}
+
+// DecodeValue is the ValueDecoderFunc for time.Time.
+func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tTime {
+ return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val}
+ }
+
+ elem, err := tc.decodeType(dc, vr, tTime)
+ if err != nil {
+ return err
+ }
+
+ val.Set(elem)
+ return nil
+}
+
+// EncodeValue is the ValueEncoderFunc for time.TIme.
+func (tc *TimeCodec) EncodeValue(ec EncodeContext, vw bsonrw.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 := primitive.NewDateTimeFromTime(tt)
+ return vw.WriteDateTime(int64(dt))
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go
new file mode 100644
index 000000000..07f4b70e6
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go
@@ -0,0 +1,57 @@
+// 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 bsoncodec
+
+import (
+ "encoding/json"
+ "net/url"
+ "reflect"
+ "time"
+
+ "go.mongodb.org/mongo-driver/bson/primitive"
+ "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
+)
+
+var tBool = reflect.TypeOf(false)
+var tFloat64 = reflect.TypeOf(float64(0))
+var tInt32 = reflect.TypeOf(int32(0))
+var tInt64 = reflect.TypeOf(int64(0))
+var tString = reflect.TypeOf("")
+var tTime = reflect.TypeOf(time.Time{})
+
+var tEmpty = reflect.TypeOf((*interface{})(nil)).Elem()
+var tByteSlice = reflect.TypeOf([]byte(nil))
+var tByte = reflect.TypeOf(byte(0x00))
+var tURL = reflect.TypeOf(url.URL{})
+var tJSONNumber = reflect.TypeOf(json.Number(""))
+
+var tValueMarshaler = reflect.TypeOf((*ValueMarshaler)(nil)).Elem()
+var tValueUnmarshaler = reflect.TypeOf((*ValueUnmarshaler)(nil)).Elem()
+var tMarshaler = reflect.TypeOf((*Marshaler)(nil)).Elem()
+var tUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+var tProxy = reflect.TypeOf((*Proxy)(nil)).Elem()
+
+var tBinary = reflect.TypeOf(primitive.Binary{})
+var tUndefined = reflect.TypeOf(primitive.Undefined{})
+var tOID = reflect.TypeOf(primitive.ObjectID{})
+var tDateTime = reflect.TypeOf(primitive.DateTime(0))
+var tNull = reflect.TypeOf(primitive.Null{})
+var tRegex = reflect.TypeOf(primitive.Regex{})
+var tCodeWithScope = reflect.TypeOf(primitive.CodeWithScope{})
+var tDBPointer = reflect.TypeOf(primitive.DBPointer{})
+var tJavaScript = reflect.TypeOf(primitive.JavaScript(""))
+var tSymbol = reflect.TypeOf(primitive.Symbol(""))
+var tTimestamp = reflect.TypeOf(primitive.Timestamp{})
+var tDecimal = reflect.TypeOf(primitive.Decimal128{})
+var tMinKey = reflect.TypeOf(primitive.MinKey{})
+var tMaxKey = reflect.TypeOf(primitive.MaxKey{})
+var tD = reflect.TypeOf(primitive.D{})
+var tA = reflect.TypeOf(primitive.A{})
+var tE = reflect.TypeOf(primitive.E{})
+
+var tCoreDocument = reflect.TypeOf(bsoncore.Document{})
+var tCoreArray = reflect.TypeOf(bsoncore.Array{})
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go
new file mode 100644
index 000000000..0b21ce999
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go
@@ -0,0 +1,173 @@
+// 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 bsoncodec
+
+import (
+ "fmt"
+ "math"
+ "reflect"
+
+ "go.mongodb.org/mongo-driver/bson/bsonoptions"
+ "go.mongodb.org/mongo-driver/bson/bsonrw"
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+)
+
+// UIntCodec is the Codec used for uint values.
+type UIntCodec struct {
+ EncodeToMinSize bool
+}
+
+var (
+ defaultUIntCodec = NewUIntCodec()
+
+ _ ValueCodec = defaultUIntCodec
+ _ typeDecoder = defaultUIntCodec
+)
+
+// NewUIntCodec returns a UIntCodec with options opts.
+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 bsonrw.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 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)
+
+ if u64 <= math.MaxInt32 && useMinSize {
+ 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,
+ }
+}
+
+func (uic *UIntCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
+ var i64 int64
+ var err error
+ switch vrType := vr.Type(); vrType {
+ case bsontype.Int32:
+ i32, err := vr.ReadInt32()
+ if err != nil {
+ return emptyValue, err
+ }
+ i64 = int64(i32)
+ case bsontype.Int64:
+ i64, err = vr.ReadInt64()
+ if err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Double:
+ f64, err := vr.ReadDouble()
+ if err != nil {
+ return emptyValue, err
+ }
+ if !dc.Truncate && math.Floor(f64) != f64 {
+ return emptyValue, errCannotTruncate
+ }
+ if f64 > float64(math.MaxInt64) {
+ return emptyValue, fmt.Errorf("%g overflows int64", f64)
+ }
+ i64 = int64(f64)
+ case bsontype.Boolean:
+ b, err := vr.ReadBoolean()
+ if err != nil {
+ return emptyValue, err
+ }
+ if b {
+ i64 = 1
+ }
+ case bsontype.Null:
+ if err = vr.ReadNull(); err != nil {
+ return emptyValue, err
+ }
+ case bsontype.Undefined:
+ if err = vr.ReadUndefined(); err != nil {
+ return emptyValue, err
+ }
+ default:
+ return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType)
+ }
+
+ switch t.Kind() {
+ case reflect.Uint8:
+ if i64 < 0 || i64 > math.MaxUint8 {
+ return emptyValue, fmt.Errorf("%d overflows uint8", i64)
+ }
+
+ return reflect.ValueOf(uint8(i64)), nil
+ case reflect.Uint16:
+ if i64 < 0 || i64 > math.MaxUint16 {
+ return emptyValue, fmt.Errorf("%d overflows uint16", i64)
+ }
+
+ return reflect.ValueOf(uint16(i64)), nil
+ case reflect.Uint32:
+ if i64 < 0 || i64 > math.MaxUint32 {
+ return emptyValue, fmt.Errorf("%d overflows uint32", i64)
+ }
+
+ return reflect.ValueOf(uint32(i64)), nil
+ case reflect.Uint64:
+ if i64 < 0 {
+ return emptyValue, fmt.Errorf("%d overflows uint64", i64)
+ }
+
+ return reflect.ValueOf(uint64(i64)), nil
+ case reflect.Uint:
+ if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint
+ return emptyValue, fmt.Errorf("%d overflows uint", i64)
+ }
+
+ return reflect.ValueOf(uint(i64)), nil
+ default:
+ return emptyValue, ValueDecoderError{
+ Name: "UintDecodeValue",
+ Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
+ Received: reflect.Zero(t),
+ }
+ }
+}
+
+// DecodeValue is the ValueDecoder for uint types.
+func (uic *UIntCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() {
+ return ValueDecoderError{
+ Name: "UintDecodeValue",
+ Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
+ Received: val,
+ }
+ }
+
+ elem, err := uic.decodeType(dc, vr, val.Type())
+ if err != nil {
+ return err
+ }
+
+ val.SetUint(elem.Uint())
+ return nil
+}