summaryrefslogtreecommitdiffstats
path: root/vendor/go.mongodb.org
diff options
context:
space:
mode:
author6543 <6543@obermui.de>2021-04-23 02:08:53 +0200
committerGitHub <noreply@github.com>2021-04-22 20:08:53 -0400
commit792b4dba2cc1b011e25f4a0c18fb648849cd885c (patch)
treefc5679ced43137a7b04ab1fb73dd2a4bd3ca9815 /vendor/go.mongodb.org
parent834fc74873e8047552e9181e130bd53d8e890eb0 (diff)
downloadgitea-792b4dba2cc1b011e25f4a0c18fb648849cd885c.tar.gz
gitea-792b4dba2cc1b011e25f4a0c18fb648849cd885c.zip
[Vendor] Update directly used dependencys (#15593)
* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3 * github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0 * github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2 * github.com/go-chi/cors v1.1.1 -> v1.2.0 * github.com/go-git/go-billy v5.0.0 -> v5.1.0 * github.com/go-git/go-git v5.2.0 -> v5.3.0 * github.com/go-ldap/ldap v3.2.4 -> v3.3.0 * github.com/go-redis/redis v8.6.0 -> v8.8.2 * github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0 * github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0 * github.com/lib/pq v1.9.0 -> v1.10.1 * github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7 * github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0 * github.com/issue9/identicon v1.0.1 -> v1.2.0 * github.com/klauspost/compress v1.11.8 -> v1.12.1 * github.com/mgechev/revive v1.0.3 -> v1.0.6 * github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8 * github.com/niklasfasching/go-org v1.4.0 -> v1.5.0 * github.com/olivere/elastic v7.0.22 -> v7.0.24 * github.com/pelletier/go-toml v1.8.1 -> v1.9.0 * github.com/prometheus/client_golang v1.9.0 -> v1.10.0 * github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0 * github.com/yuin/goldmark v1.3.3 -> v1.3.5 * github.com/6543/go-version v1.2.4 -> v1.3.1 * do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
Diffstat (limited to 'vendor/go.mongodb.org')
-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.go53
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go55
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go917
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go1
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go43
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go4
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go53
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go20
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go52
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go1
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go79
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go60
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go68
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go15
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/doc.go22
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go44
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go6
-rw-r--r--vendor/go.mongodb.org/mongo-driver/bson/raw_value.go16
-rw-r--r--vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go164
-rw-r--r--vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_arraybuilder.go201
-rw-r--r--vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_documentbuilder.go189
-rw-r--r--vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go28
-rw-r--r--vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go69
24 files changed, 1807 insertions, 403 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 0000000000..4e24f9eed6
--- /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
index 0ebc9a1564..2c861b5cd3 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go
@@ -15,6 +15,10 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
+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.
@@ -156,6 +160,55 @@ func (fn ValueDecoderFunc) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader,
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 {
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
index 8219748d0f..5a916cc159 100644
--- 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
@@ -15,14 +15,17 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
-var defaultByteSliceCodec = NewByteSliceCodec()
-
// ByteSliceCodec is the Codec used for []byte values.
type ByteSliceCodec struct {
EncodeNilAsEmpty bool
}
-var _ ValueCodec = &ByteSliceCodec{}
+var (
+ defaultByteSliceCodec = NewByteSliceCodec()
+
+ _ ValueCodec = defaultByteSliceCodec
+ _ typeDecoder = defaultByteSliceCodec
+)
// NewByteSliceCodec returns a StringCodec with options opts.
func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec {
@@ -45,10 +48,13 @@ func (bsc *ByteSliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter,
return vw.WriteBinary(val.Interface().([]byte))
}
-// 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}
+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
@@ -57,34 +63,49 @@ func (bsc *ByteSliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader,
case bsontype.String:
str, err := vr.ReadString()
if err != nil {
- return err
+ return emptyValue, err
}
data = []byte(str)
case bsontype.Symbol:
sym, err := vr.ReadSymbol()
if err != nil {
- return err
+ return emptyValue, err
}
data = []byte(sym)
case bsontype.Binary:
var subtype byte
data, subtype, err = vr.ReadBinary()
if err != nil {
- return err
+ return emptyValue, err
}
if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
- return fmt.Errorf("ByteSliceDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype)
+ return emptyValue, decodeBinaryError{subtype: subtype, typeName: "[]byte"}
}
case bsontype.Null:
- val.Set(reflect.Zero(val.Type()))
- return vr.ReadNull()
+ err = vr.ReadNull()
case bsontype.Undefined:
- val.Set(reflect.Zero(val.Type()))
- return vr.ReadUndefined()
+ err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a []byte", vrType)
+ 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(reflect.ValueOf(data))
+ val.Set(elem)
return nil
}
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
index a2e2d425a0..18919e3c40 100644
--- 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
@@ -22,7 +22,19 @@ import (
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
)
-var defaultValueDecoders DefaultValueDecoders
+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)
@@ -49,40 +61,45 @@ func (dvd DefaultValueDecoders) RegisterDefaultDecoders(rb *RegistryBuilder) {
panic(errors.New("argument to RegisterDefaultDecoders must not be nil"))
}
+ intDecoder := decodeAdapter{dvd.IntDecodeValue, dvd.intDecodeType}
+ floatDecoder := decodeAdapter{dvd.FloatDecodeValue, dvd.floatDecodeType}
+
rb.
- RegisterTypeDecoder(tBinary, ValueDecoderFunc(dvd.BinaryDecodeValue)).
- RegisterTypeDecoder(tUndefined, ValueDecoderFunc(dvd.UndefinedDecodeValue)).
- RegisterTypeDecoder(tDateTime, ValueDecoderFunc(dvd.DateTimeDecodeValue)).
- RegisterTypeDecoder(tNull, ValueDecoderFunc(dvd.NullDecodeValue)).
- RegisterTypeDecoder(tRegex, ValueDecoderFunc(dvd.RegexDecodeValue)).
- RegisterTypeDecoder(tDBPointer, ValueDecoderFunc(dvd.DBPointerDecodeValue)).
- RegisterTypeDecoder(tTimestamp, ValueDecoderFunc(dvd.TimestampDecodeValue)).
- RegisterTypeDecoder(tMinKey, ValueDecoderFunc(dvd.MinKeyDecodeValue)).
- RegisterTypeDecoder(tMaxKey, ValueDecoderFunc(dvd.MaxKeyDecodeValue)).
- RegisterTypeDecoder(tJavaScript, ValueDecoderFunc(dvd.JavaScriptDecodeValue)).
- RegisterTypeDecoder(tSymbol, ValueDecoderFunc(dvd.SymbolDecodeValue)).
+ 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(tOID, ValueDecoderFunc(dvd.ObjectIDDecodeValue)).
- RegisterTypeDecoder(tDecimal, ValueDecoderFunc(dvd.Decimal128DecodeValue)).
- RegisterTypeDecoder(tJSONNumber, ValueDecoderFunc(dvd.JSONNumberDecodeValue)).
- RegisterTypeDecoder(tURL, ValueDecoderFunc(dvd.URLDecodeValue)).
+ 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, ValueDecoderFunc(dvd.CodeWithScopeDecodeValue)).
- RegisterDefaultDecoder(reflect.Bool, ValueDecoderFunc(dvd.BooleanDecodeValue)).
- RegisterDefaultDecoder(reflect.Int, ValueDecoderFunc(dvd.IntDecodeValue)).
- RegisterDefaultDecoder(reflect.Int8, ValueDecoderFunc(dvd.IntDecodeValue)).
- RegisterDefaultDecoder(reflect.Int16, ValueDecoderFunc(dvd.IntDecodeValue)).
- RegisterDefaultDecoder(reflect.Int32, ValueDecoderFunc(dvd.IntDecodeValue)).
- RegisterDefaultDecoder(reflect.Int64, ValueDecoderFunc(dvd.IntDecodeValue)).
+ 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, ValueDecoderFunc(dvd.FloatDecodeValue)).
- RegisterDefaultDecoder(reflect.Float64, ValueDecoderFunc(dvd.FloatDecodeValue)).
+ RegisterDefaultDecoder(reflect.Float32, floatDecoder).
+ RegisterDefaultDecoder(reflect.Float64, floatDecoder).
RegisterDefaultDecoder(reflect.Array, ValueDecoderFunc(dvd.ArrayDecodeValue)).
RegisterDefaultDecoder(reflect.Map, defaultMapCodec).
RegisterDefaultDecoder(reflect.Slice, defaultSliceCodec).
@@ -114,10 +131,70 @@ func (dvd DefaultValueDecoders) RegisterDefaultDecoders(rb *RegistryBuilder) {
RegisterHookDecoder(tUnmarshaler, ValueDecoderFunc(dvd.UnmarshalerDecodeValue))
}
-// 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}
+// 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
@@ -126,116 +203,138 @@ func (dvd DefaultValueDecoders) BooleanDecodeValue(dctx DecodeContext, vr bsonrw
case bsontype.Int32:
i32, err := vr.ReadInt32()
if err != nil {
- return err
+ return emptyValue, err
}
b = (i32 != 0)
case bsontype.Int64:
i64, err := vr.ReadInt64()
if err != nil {
- return err
+ return emptyValue, err
}
b = (i64 != 0)
case bsontype.Double:
f64, err := vr.ReadDouble()
if err != nil {
- return err
+ return emptyValue, err
}
b = (f64 != 0)
case bsontype.Boolean:
b, err = vr.ReadBoolean()
- if err != nil {
- return err
- }
case bsontype.Null:
- if err = vr.ReadNull(); err != nil {
- return err
- }
+ err = vr.ReadNull()
case bsontype.Undefined:
- if err = vr.ReadUndefined(); err != nil {
- return err
- }
+ err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a boolean", vrType)
+ return emptyValue, fmt.Errorf("cannot decode %v into a boolean", vrType)
}
- val.SetBool(b)
- return nil
+ if err != nil {
+ return emptyValue, err
+ }
+
+ return reflect.ValueOf(b), nil
}
-// 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,
- }
+// 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 err
+ return emptyValue, err
}
i64 = int64(i32)
case bsontype.Int64:
i64, err = vr.ReadInt64()
if err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Double:
f64, err := vr.ReadDouble()
if err != nil {
- return err
+ return emptyValue, err
}
if !dc.Truncate && math.Floor(f64) != f64 {
- return errors.New("IntDecodeValue can only truncate float64 to an integer type when truncation is enabled")
+ return emptyValue, errCannotTruncate
}
if f64 > float64(math.MaxInt64) {
- return fmt.Errorf("%g overflows int64", f64)
+ return emptyValue, fmt.Errorf("%g overflows int64", f64)
}
i64 = int64(f64)
case bsontype.Boolean:
b, err := vr.ReadBoolean()
if err != nil {
- return err
+ return emptyValue, err
}
if b {
i64 = 1
}
case bsontype.Null:
if err = vr.ReadNull(); err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Undefined:
if err = vr.ReadUndefined(); err != nil {
- return err
+ return emptyValue, err
}
default:
- return fmt.Errorf("cannot decode %v into an integer type", vrType)
+ return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType)
}
- switch val.Kind() {
+ switch t.Kind() {
case reflect.Int8:
if i64 < math.MinInt8 || i64 > math.MaxInt8 {
- return fmt.Errorf("%d overflows int8", i64)
+ 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 fmt.Errorf("%d overflows int16", i64)
+ 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 fmt.Errorf("%d overflows int32", i64)
+ 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 fmt.Errorf("%d overflows int", i64)
+ 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},
@@ -243,7 +342,12 @@ func (dvd DefaultValueDecoders) IntDecodeValue(dc DecodeContext, vr bsonrw.Value
}
}
- val.SetInt(i64)
+ elem, err := dvd.intDecodeType(dc, vr, val.Type())
+ if err != nil {
+ return err
+ }
+
+ val.SetInt(elem.Int())
return nil
}
@@ -330,67 +434,81 @@ func (dvd DefaultValueDecoders) UintDecodeValue(dc DecodeContext, vr bsonrw.Valu
return nil
}
-// 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,
- }
- }
-
+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 err
+ return emptyValue, err
}
f = float64(i32)
case bsontype.Int64:
i64, err := vr.ReadInt64()
if err != nil {
- return err
+ return emptyValue, err
}
f = float64(i64)
case bsontype.Double:
f, err = vr.ReadDouble()
if err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Boolean:
b, err := vr.ReadBoolean()
if err != nil {
- return err
+ return emptyValue, err
}
if b {
f = 1
}
case bsontype.Null:
if err = vr.ReadNull(); err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Undefined:
if err = vr.ReadUndefined(); err != nil {
- return err
+ return emptyValue, err
}
default:
- return fmt.Errorf("cannot decode %v into a float32 or float64 type", vrType)
+ return emptyValue, fmt.Errorf("cannot decode %v into a float32 or float64 type", vrType)
}
- switch val.Kind() {
+ switch t.Kind() {
case reflect.Float32:
if !ec.Truncate && float64(float32(f)) != f {
- return errors.New("FloatDecodeValue can only convert float64 to float32 when truncation is allowed")
+ return emptyValue, errCannotTruncate
}
+
+ return reflect.ValueOf(float32(f)), nil
case reflect.Float64:
+ return reflect.ValueOf(f), nil
default:
- return ValueDecoderError{Name: "FloatDecodeValue", Kinds: []reflect.Kind{reflect.Float32, reflect.Float64}, Received: val}
+ return emptyValue, ValueDecoderError{
+ Name: "FloatDecodeValue",
+ Kinds: []reflect.Kind{reflect.Float32, reflect.Float64},
+ Received: reflect.Zero(t),
+ }
}
+}
- val.SetFloat(f)
+// 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
}
@@ -418,10 +536,13 @@ func (dvd DefaultValueDecoders) StringDecodeValue(dctx DecodeContext, vr bsonrw.
return nil
}
-// JavaScriptDecodeValue is the ValueDecoderFunc for the primitive.JavaScript type.
-func (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}
+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
@@ -434,20 +555,37 @@ func (DefaultValueDecoders) JavaScriptDecodeValue(dctx DecodeContext, vr bsonrw.
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a primitive.JavaScript", vrType)
+ 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(js)
+
+ val.SetString(elem.String())
return nil
}
-// SymbolDecodeValue is the ValueDecoderFunc for the primitive.Symbol type.
-func (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}
+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
@@ -455,43 +593,54 @@ func (DefaultValueDecoders) SymbolDecodeValue(dctx DecodeContext, vr bsonrw.Valu
switch vrType := vr.Type(); vrType {
case bsontype.String:
symbol, err = vr.ReadString()
- if err != nil {
- return err
- }
case bsontype.Symbol:
symbol, err = vr.ReadSymbol()
- if err != nil {
- return err
- }
case bsontype.Binary:
data, subtype, err := vr.ReadBinary()
if err != nil {
- return err
+ return emptyValue, err
}
+
if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
- return fmt.Errorf("SymbolDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype)
+ return emptyValue, decodeBinaryError{subtype: subtype, typeName: "primitive.Symbol"}
}
symbol = string(data)
case bsontype.Null:
- if err = vr.ReadNull(); err != nil {
- return err
- }
+ err = vr.ReadNull()
case bsontype.Undefined:
- if err = vr.ReadUndefined(); err != nil {
- return err
- }
+ err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a primitive.Symbol", vrType)
+ return emptyValue, fmt.Errorf("cannot decode %v into a primitive.Symbol", vrType)
+ }
+ if err != nil {
+ return emptyValue, err
}
- val.SetString(symbol)
+ 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
}
-// BinaryDecodeValue is the ValueDecoderFunc for Binary.
-func (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}
+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
@@ -505,20 +654,37 @@ func (DefaultValueDecoders) BinaryDecodeValue(dc DecodeContext, vr bsonrw.ValueR
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a Binary", vrType)
+ 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(reflect.ValueOf(primitive.Binary{Subtype: subtype, Data: data}))
+
+ val.Set(elem)
return nil
}
-// UndefinedDecodeValue is the ValueDecoderFunc for Undefined.
-func (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}
+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
@@ -528,20 +694,38 @@ func (DefaultValueDecoders) UndefinedDecodeValue(dc DecodeContext, vr bsonrw.Val
case bsontype.Null:
err = vr.ReadNull()
default:
- return fmt.Errorf("cannot decode %v into an Undefined", vr.Type())
+ 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(reflect.ValueOf(primitive.Undefined{}))
+
+ val.Set(elem)
return 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}
+// 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
@@ -550,38 +734,58 @@ func (dvd DefaultValueDecoders) ObjectIDDecodeValue(dc DecodeContext, vr bsonrw.
case bsontype.ObjectID:
oid, err = vr.ReadObjectID()
if err != nil {
- return err
+ return emptyValue, err
}
case bsontype.String:
str, err := vr.ReadString()
if err != nil {
- return err
+ return emptyValue, err
+ }
+ if oid, err = primitive.ObjectIDFromHex(str); err == nil {
+ break
}
if len(str) != 12 {
- return fmt.Errorf("an ObjectID string must be exactly 12 bytes long (got %v)", len(str))
+ 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 err
+ return emptyValue, err
}
case bsontype.Undefined:
if err = vr.ReadUndefined(); err != nil {
- return err
+ return emptyValue, err
}
default:
- return fmt.Errorf("cannot decode %v into an ObjectID", vrType)
+ 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(reflect.ValueOf(oid))
+ val.Set(elem)
return nil
}
-// DateTimeDecodeValue is the ValueDecoderFunc for DateTime.
-func (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}
+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
@@ -594,20 +798,37 @@ func (DefaultValueDecoders) DateTimeDecodeValue(dc DecodeContext, vr bsonrw.Valu
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a DateTime", vrType)
+ 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(reflect.ValueOf(primitive.DateTime(dt)))
+
+ val.Set(elem)
return nil
}
-// NullDecodeValue is the ValueDecoderFunc for Null.
-func (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}
+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
@@ -617,20 +838,37 @@ func (DefaultValueDecoders) NullDecodeValue(dc DecodeContext, vr bsonrw.ValueRea
case bsontype.Null:
err = vr.ReadNull()
default:
- return fmt.Errorf("cannot decode %v into a Null", vr.Type())
+ 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(reflect.ValueOf(primitive.Null{}))
+
+ val.Set(elem)
return nil
}
-// RegexDecodeValue is the ValueDecoderFunc for Regex.
-func (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}
+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
@@ -643,20 +881,37 @@ func (DefaultValueDecoders) RegexDecodeValue(dc DecodeContext, vr bsonrw.ValueRe
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a Regex", vrType)
+ 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(reflect.ValueOf(primitive.Regex{Pattern: pattern, Options: options}))
+
+ val.Set(elem)
return nil
}
-// DBPointerDecodeValue is the ValueDecoderFunc for DBPointer.
-func (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}
+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
@@ -670,20 +925,37 @@ func (DefaultValueDecoders) DBPointerDecodeValue(dc DecodeContext, vr bsonrw.Val
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a DBPointer", vrType)
+ 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(reflect.ValueOf(primitive.DBPointer{DB: ns, Pointer: pointer}))
+
+ val.Set(elem)
return nil
}
-// TimestampDecodeValue is the ValueDecoderFunc for Timestamp.
-func (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}
+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
@@ -696,20 +968,37 @@ func (DefaultValueDecoders) TimestampDecodeValue(dc DecodeContext, vr bsonrw.Val
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a Timestamp", vrType)
+ 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(reflect.ValueOf(primitive.Timestamp{T: t, I: incr}))
+
+ val.Set(elem)
return nil
}
-// MinKeyDecodeValue is the ValueDecoderFunc for MinKey.
-func (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}
+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
@@ -721,20 +1010,37 @@ func (DefaultValueDecoders) MinKeyDecodeValue(dc DecodeContext, vr bsonrw.ValueR
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a MinKey", vr.Type())
+ 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(reflect.ValueOf(primitive.MinKey{}))
+
+ val.Set(elem)
return nil
}
-// MaxKeyDecodeValue is the ValueDecoderFunc for MaxKey.
-func (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}
+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
@@ -746,20 +1052,37 @@ func (DefaultValueDecoders) MaxKeyDecodeValue(dc DecodeContext, vr bsonrw.ValueR
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a MaxKey", vr.Type())
+ 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(reflect.ValueOf(primitive.MaxKey{}))
+
+ val.Set(elem)
return 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}
+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
@@ -772,92 +1095,136 @@ func (dvd DefaultValueDecoders) Decimal128DecodeValue(dctx DecodeContext, vr bso
case bsontype.Undefined:
err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a primitive.Decimal128", vr.Type())
+ 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(reflect.ValueOf(d128))
- return err
+
+ val.Set(elem)
+ return 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}
+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 err
+ return emptyValue, err
}
- val.Set(reflect.ValueOf(json.Number(strconv.FormatFloat(f64, 'f', -1, 64))))
+ jsonNum = json.Number(strconv.FormatFloat(f64, 'f', -1, 64))
case bsontype.Int32:
i32, err := vr.ReadInt32()
if err != nil {
- return err
+ return emptyValue, err
}
- val.Set(reflect.ValueOf(json.Number(strconv.FormatInt(int64(i32), 10))))
+ jsonNum = json.Number(strconv.FormatInt(int64(i32), 10))
case bsontype.Int64:
i64, err := vr.ReadInt64()
if err != nil {
- return err
+ return emptyValue, err
}
- val.Set(reflect.ValueOf(json.Number(strconv.FormatInt(i64, 10))))
+ jsonNum = json.Number(strconv.FormatInt(i64, 10))
case bsontype.Null:
- if err := vr.ReadNull(); err != nil {
- return err
- }
- val.SetString("")
+ err = vr.ReadNull()
case bsontype.Undefined:
- if err := vr.ReadUndefined(); err != nil {
- return err
- }
- val.SetString("")
+ err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a json.Number", vrType)
+ 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
}
-// 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}
+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:
- str, err := vr.ReadString()
+ var str string // Declare str here to avoid shadowing err during the ReadString call.
+ str, err = vr.ReadString()
if err != nil {
- return err
+ return emptyValue, err
}
- parsedURL, err := url.Parse(str)
- if err != nil {
- return err
- }
- val.Set(reflect.ValueOf(parsedURL).Elem())
- return nil
+ urlPtr, err = url.Parse(str)
case bsontype.Null:
- if err := vr.ReadNull(); err != nil {
- return err
- }
- val.Set(reflect.ValueOf(url.URL{}))
- return nil
+ err = vr.ReadNull()
case bsontype.Undefined:
- if err := vr.ReadUndefined(); err != nil {
- return err
- }
- val.Set(reflect.ValueOf(url.URL{}))
- return nil
+ err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a *url.URL", vrType)
+ 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.
@@ -1216,6 +1583,7 @@ func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueR
if err != nil {
return nil, err
}
+ eTypeDecoder, _ := decoder.(typeDecoder)
idx := 0
for {
@@ -1227,9 +1595,7 @@ func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueR
return nil, err
}
- elem := reflect.New(eType).Elem()
-
- err = decoder.DecodeValue(dc, vr, elem)
+ elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true)
if err != nil {
return nil, newDecodeError(strconv.Itoa(idx), err)
}
@@ -1240,48 +1606,71 @@ func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueR
return elems, 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}
+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
}
- switch vrType := vr.Type(); vrType {
- case bsontype.CodeWithScope:
- code, dr, err := vr.ReadCodeWithScope()
- if err != nil {
- return err
- }
+ scope := reflect.New(tD).Elem()
+ elems, err := dvd.decodeElemsFromDocumentReader(dc, dr)
+ if err != nil {
+ return cws, err
+ }
- scope := reflect.New(tD).Elem()
- elems, err := dvd.decodeElemsFromDocumentReader(dc, dr)
- if err != nil {
- return err
- }
+ scope.Set(reflect.MakeSlice(tD, 0, len(elems)))
+ scope.Set(reflect.Append(scope, elems...))
- 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
+}
- val.Set(reflect.ValueOf(primitive.CodeWithScope{
- Code: primitive.JavaScript(code),
- Scope: scope.Interface().(primitive.D),
- }))
- return nil
- case bsontype.Null:
- if err := vr.ReadNull(); err != nil {
- return err
+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),
}
- val.Set(reflect.ValueOf(primitive.CodeWithScope{}))
- return nil
+ }
+
+ 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:
- if err := vr.ReadUndefined(); err != nil {
- return err
- }
- val.Set(reflect.ValueOf(primitive.CodeWithScope{}))
- return nil
+ err = vr.ReadUndefined()
default:
- return fmt.Errorf("cannot decode %v into a primitive.CodeWithScope", vrType)
+ 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) {
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
index 01ddbbb672..49a0c3f14b 100644
--- 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
@@ -70,6 +70,7 @@ func (dve DefaultValueEncoders) RegisterDefaultEncoders(rb *RegistryBuilder) {
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)).
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
index c215ec3849..a15636d0a8 100644
--- 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
@@ -15,14 +15,17 @@ import (
"go.mongodb.org/mongo-driver/bson/primitive"
)
-var defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec()
-
// EmptyInterfaceCodec is the Codec used for interface{} values.
type EmptyInterfaceCodec struct {
DecodeBinaryAsSlice bool
}
-var _ ValueCodec = &EmptyInterfaceCodec{}
+var (
+ defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec()
+
+ _ ValueCodec = defaultEmptyInterfaceCodec
+ _ typeDecoder = defaultEmptyInterfaceCodec
+)
// NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts.
func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec {
@@ -86,33 +89,31 @@ func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, val
return nil, err
}
-// 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}
+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:
- val.Set(reflect.Zero(val.Type()))
- return vr.ReadNull()
+ return reflect.Zero(t), vr.ReadNull()
default:
- return err
+ return emptyValue, err
}
}
decoder, err := dc.LookupDecoder(rtype)
if err != nil {
- return err
+ return emptyValue, err
}
- elem := reflect.New(rtype).Elem()
- err = decoder.DecodeValue(dc, vr, elem)
+ elem, err := decodeTypeOrValue(decoder, dc, vr, rtype)
if err != nil {
- return err
+ return emptyValue, err
}
+
if eic.DecodeBinaryAsSlice && rtype == tBinary {
binElem := elem.Interface().(primitive.Binary)
if binElem.Subtype == bsontype.BinaryGeneric || binElem.Subtype == bsontype.BinaryBinaryOld {
@@ -120,6 +121,20 @@ func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueRead
}
}
+ 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
index d641960c10..fbb8ef427c 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go
@@ -178,6 +178,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref
if err != nil {
return err
}
+ eTypeDecoder, _ := decoder.(typeDecoder)
if eType == tEmpty {
dc.Ancestor = val.Type()
@@ -199,8 +200,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref
return err
}
- elem := reflect.New(eType).Elem()
- err = decoder.DecodeValue(dc, vr, elem)
+ elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true)
if err != nil {
return newDecodeError(key, err)
}
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
index 910f2049a4..5332b7c3b5 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go
@@ -15,14 +15,17 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
-var defaultStringCodec = NewStringCodec()
-
// StringCodec is the Codec used for struct values.
type StringCodec struct {
DecodeObjectIDAsHex bool
}
-var _ ValueCodec = &StringCodec{}
+var (
+ defaultStringCodec = NewStringCodec()
+
+ _ ValueCodec = defaultStringCodec
+ _ typeDecoder = defaultStringCodec
+)
// NewStringCodec returns a StringCodec with options opts.
func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec {
@@ -43,23 +46,27 @@ func (sc *StringCodec) EncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, va
return vw.WriteString(val.String())
}
-// 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}
+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 err
+ return emptyValue, err
}
case bsontype.ObjectID:
oid, err := vr.ReadObjectID()
if err != nil {
- return err
+ return emptyValue, err
}
if sc.DecodeObjectIDAsHex {
str = oid.Hex()
@@ -70,29 +77,43 @@ func (sc *StringCodec) DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, va
case bsontype.Symbol:
str, err = vr.ReadSymbol()
if err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Binary:
data, subtype, err := vr.ReadBinary()
if err != nil {
- return err
+ return emptyValue, 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)
+ return emptyValue, decodeBinaryError{subtype: subtype, typeName: "string"}
}
str = string(data)
case bsontype.Null:
if err = vr.ReadNull(); err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Undefined:
if err = vr.ReadUndefined(); err != nil {
- return err
+ return emptyValue, err
}
default:
- return fmt.Errorf("cannot decode %v into a string type", vr.Type())
+ 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(str)
+ val.SetString(elem.String())
return nil
}
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
index 69d0ae4d06..6f406c1623 100644
--- 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
@@ -91,6 +91,10 @@ var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (S
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
@@ -117,3 +121,19 @@ var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (S
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
index a7df44db70..ec7e30f724 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go
@@ -21,14 +21,17 @@ const (
timeFormatString = "2006-01-02T15:04:05.999Z07:00"
)
-var defaultTimeCodec = NewTimeCodec()
-
// TimeCodec is the Codec used for time.Time values.
type TimeCodec struct {
UseLocalTimeZone bool
}
-var _ ValueCodec = &TimeCodec{}
+var (
+ defaultTimeCodec = NewTimeCodec()
+
+ _ ValueCodec = defaultTimeCodec
+ _ typeDecoder = defaultTimeCodec
+)
// NewTimeCodec returns a TimeCodec with options opts.
func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec {
@@ -41,10 +44,13 @@ func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec {
return &codec
}
-// 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}
+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
@@ -52,47 +58,61 @@ func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val re
case bsontype.DateTime:
dt, err := vr.ReadDateTime()
if err != nil {
- return err
+ 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 err
+ return emptyValue, err
}
timeVal, err = time.Parse(timeFormatString, timeStr)
if err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Int64:
i64, err := vr.ReadInt64()
if err != nil {
- return err
+ return emptyValue, err
}
timeVal = time.Unix(i64/1000, i64%1000*1000000)
case bsontype.Timestamp:
t, _, err := vr.ReadTimestamp()
if err != nil {
- return err
+ return emptyValue, err
}
timeVal = time.Unix(int64(t), 0)
case bsontype.Null:
if err := vr.ReadNull(); err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Undefined:
if err := vr.ReadUndefined(); err != nil {
- return err
+ return emptyValue, err
}
default:
- return fmt.Errorf("cannot decode %v into a time.Time", vrType)
+ return emptyValue, fmt.Errorf("cannot decode %v into a time.Time", vrType)
}
if !tc.UseLocalTimeZone {
timeVal = timeVal.UTC()
}
- val.Set(reflect.ValueOf(timeVal))
+ 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
}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go
index bbb6bb9cea..fb5b51084d 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go
@@ -79,3 +79,4 @@ 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
index 3c991264d1..0b21ce999c 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go
@@ -7,7 +7,6 @@
package bsoncodec
import (
- "errors"
"fmt"
"math"
"reflect"
@@ -17,14 +16,17 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
-var defaultUIntCodec = NewUIntCodec()
-
// UIntCodec is the Codec used for uint values.
type UIntCodec struct {
EncodeToMinSize bool
}
-var _ ValueCodec = &UIntCodec{}
+var (
+ defaultUIntCodec = NewUIntCodec()
+
+ _ ValueCodec = defaultUIntCodec
+ _ typeDecoder = defaultUIntCodec
+)
// NewUIntCodec returns a UIntCodec with options opts.
func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec {
@@ -64,84 +66,96 @@ func (uic *UIntCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val r
}
}
-// 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,
- }
- }
-
+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 err
+ return emptyValue, err
}
i64 = int64(i32)
case bsontype.Int64:
i64, err = vr.ReadInt64()
if err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Double:
f64, err := vr.ReadDouble()
if err != nil {
- return err
+ return emptyValue, err
}
if !dc.Truncate && math.Floor(f64) != f64 {
- return errors.New("UintDecodeValue can only truncate float64 to an integer type when truncation is enabled")
+ return emptyValue, errCannotTruncate
}
if f64 > float64(math.MaxInt64) {
- return fmt.Errorf("%g overflows int64", f64)
+ return emptyValue, fmt.Errorf("%g overflows int64", f64)
}
i64 = int64(f64)
case bsontype.Boolean:
b, err := vr.ReadBoolean()
if err != nil {
- return err
+ return emptyValue, err
}
if b {
i64 = 1
}
case bsontype.Null:
if err = vr.ReadNull(); err != nil {
- return err
+ return emptyValue, err
}
case bsontype.Undefined:
if err = vr.ReadUndefined(); err != nil {
- return err
+ return emptyValue, err
}
default:
- return fmt.Errorf("cannot decode %v into an integer type", vrType)
+ return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType)
}
- switch val.Kind() {
+ switch t.Kind() {
case reflect.Uint8:
if i64 < 0 || i64 > math.MaxUint8 {
- return fmt.Errorf("%d overflows uint8", i64)
+ return emptyValue, fmt.Errorf("%d overflows uint8", i64)
}
+
+ return reflect.ValueOf(uint8(i64)), nil
case reflect.Uint16:
if i64 < 0 || i64 > math.MaxUint16 {
- return fmt.Errorf("%d overflows uint16", i64)
+ return emptyValue, fmt.Errorf("%d overflows uint16", i64)
}
+
+ return reflect.ValueOf(uint16(i64)), nil
case reflect.Uint32:
if i64 < 0 || i64 > math.MaxUint32 {
- return fmt.Errorf("%d overflows uint32", i64)
+ return emptyValue, fmt.Errorf("%d overflows uint32", i64)
}
+
+ return reflect.ValueOf(uint32(i64)), nil
case reflect.Uint64:
if i64 < 0 {
- return fmt.Errorf("%d overflows uint64", i64)
+ 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 fmt.Errorf("%d overflows uint", i64)
+ 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},
@@ -149,6 +163,11 @@ func (uic *UIntCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val r
}
}
- val.SetUint(uint64(i64))
+ elem, err := uic.decodeType(dc, vr, val.Type())
+ if err != nil {
+ return err
+ }
+
+ val.SetUint(elem.Uint())
return nil
}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go
index 02e3a7e3d0..5cdf6460bc 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go
@@ -45,6 +45,22 @@ func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error {
return c.copyDocumentCore(dw, dr)
}
+// CopyArrayFromBytes copies the values from a BSON array represented as a
+// []byte to a ValueWriter.
+func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error {
+ aw, err := dst.WriteArray()
+ if err != nil {
+ return err
+ }
+
+ err = c.CopyBytesToArrayWriter(aw, src)
+ if err != nil {
+ return err
+ }
+
+ return aw.WriteArrayEnd()
+}
+
// CopyDocumentFromBytes copies the values from a BSON document represented as a
// []byte to a ValueWriter.
func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error {
@@ -61,9 +77,29 @@ func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error {
return dw.WriteDocumentEnd()
}
+type writeElementFn func(key string) (ValueWriter, error)
+
+// CopyBytesToArrayWriter copies the values from a BSON Array represented as a []byte to an
+// ArrayWriter.
+func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error {
+ wef := func(_ string) (ValueWriter, error) {
+ return dst.WriteArrayElement()
+ }
+
+ return c.copyBytesToValueWriter(src, wef)
+}
+
// CopyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a
// DocumentWriter.
func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error {
+ wef := func(key string) (ValueWriter, error) {
+ return dst.WriteDocumentElement(key)
+ }
+
+ return c.copyBytesToValueWriter(src, wef)
+}
+
+func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error {
// TODO(skriptble): Create errors types here. Anything thats a tag should be a property.
length, rem, ok := bsoncore.ReadLength(src)
if !ok {
@@ -93,15 +129,18 @@ func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error
if !ok {
return fmt.Errorf("invalid key found. remaining bytes=%v", rem)
}
- dvw, err := dst.WriteDocumentElement(key)
+
+ // write as either array element or document element using writeElementFn
+ vw, err := wef(key)
if err != nil {
return err
}
+
val, rem, ok = bsoncore.ReadValue(rem, t)
if !ok {
return fmt.Errorf("not enough bytes available to read type. bytes=%d type=%s", len(rem), t)
}
- err = c.CopyValueFromBytes(dvw, t, val.Data)
+ err = c.CopyValueFromBytes(vw, t, val.Data)
if err != nil {
return err
}
@@ -133,6 +172,23 @@ func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error)
return dst, err
}
+// AppendArrayBytes copies an array from the ValueReader to dst.
+func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) {
+ if br, ok := src.(BytesReader); ok {
+ _, dst, err := br.ReadValueBytes(dst)
+ return dst, err
+ }
+
+ vw := vwPool.Get().(*valueWriter)
+ defer vwPool.Put(vw)
+
+ vw.reset(dst)
+
+ err := c.copyArray(vw, src)
+ dst = vw.buf
+ return dst, err
+}
+
// CopyValueFromBytes will write the value represtend by t and src to dst.
func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) error {
if wvb, ok := dst.(BytesWriter); ok {
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go
index 3ff17c197d..8a690e37ce 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go
@@ -7,9 +7,12 @@
package bsonrw
import (
+ "encoding/base64"
+ "encoding/hex"
"errors"
"fmt"
"io"
+ "strings"
"go.mongodb.org/mongo-driver/bson/bsontype"
)
@@ -66,6 +69,7 @@ type extJSONParser struct {
maxDepth int
emptyObject bool
+ relaxedUUID bool
}
// newExtJSONParser returns a new extended JSON parser, ready to to begin
@@ -119,6 +123,12 @@ func (ejp *extJSONParser) peekType() (bsontype.Type, error) {
}
t = wrapperKeyBSONType(ejp.k)
+ // if $uuid is encountered, parse as binary subtype 4
+ if ejp.k == "$uuid" {
+ ejp.relaxedUUID = true
+ t = bsontype.Binary
+ }
+
switch t {
case bsontype.JavaScript:
// just saw $code, need to check for $scope at same level
@@ -273,6 +283,64 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) {
ejp.advanceState()
if t == bsontype.Binary && ejp.s == jpsSawValue {
+ // convert relaxed $uuid format
+ if ejp.relaxedUUID {
+ defer func() { ejp.relaxedUUID = false }()
+ uuid, err := ejp.v.parseSymbol()
+ if err != nil {
+ return nil, err
+ }
+
+ // RFC 4122 defines the length of a UUID as 36 and the hyphens in a UUID as appearing
+ // in the 8th, 13th, 18th, and 23rd characters.
+ //
+ // See https://tools.ietf.org/html/rfc4122#section-3
+ valid := len(uuid) == 36 &&
+ string(uuid[8]) == "-" &&
+ string(uuid[13]) == "-" &&
+ string(uuid[18]) == "-" &&
+ string(uuid[23]) == "-"
+ if !valid {
+ return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding length and hyphens")
+ }
+
+ // remove hyphens
+ uuidNoHyphens := strings.Replace(uuid, "-", "", -1)
+ if len(uuidNoHyphens) != 32 {
+ return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding length and hyphens")
+ }
+
+ // convert hex to bytes
+ bytes, err := hex.DecodeString(uuidNoHyphens)
+ if err != nil {
+ return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %v", err)
+ }
+
+ ejp.advanceState()
+ if ejp.s != jpsSawEndObject {
+ return nil, invalidJSONErrorForType("$uuid and value and then }", bsontype.Binary)
+ }
+
+ base64 := &extJSONValue{
+ t: bsontype.String,
+ v: base64.StdEncoding.EncodeToString(bytes),
+ }
+ subType := &extJSONValue{
+ t: bsontype.String,
+ v: "04",
+ }
+
+ v = &extJSONValue{
+ t: bsontype.EmbeddedDocument,
+ v: &extJSONObject{
+ keys: []string{"base64", "subType"},
+ values: []*extJSONValue{base64, subType},
+ },
+ }
+
+ break
+ }
+
// convert legacy $binary format
base64 := ejp.v
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go
index 3717198366..7b7d7ad3f2 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go
@@ -12,6 +12,7 @@ import (
"io"
"math"
"strconv"
+ "strings"
"sync"
"go.mongodb.org/mongo-driver/bson/bsontype"
@@ -247,7 +248,12 @@ func (vw *valueWriter) invalidTransitionError(destination mode, name string, mod
func (vw *valueWriter) writeElementHeader(t bsontype.Type, destination mode, callerName string, addmodes ...mode) error {
switch vw.stack[vw.frame].mode {
case mElement:
- vw.buf = bsoncore.AppendHeader(vw.buf, t, vw.stack[vw.frame].key)
+ key := vw.stack[vw.frame].key
+ if !isValidCString(key) {
+ return errors.New("BSON element key cannot contain null bytes")
+ }
+
+ vw.buf = bsoncore.AppendHeader(vw.buf, t, key)
case mValue:
// TODO: Do this with a cache of the first 1000 or so array keys.
vw.buf = bsoncore.AppendHeader(vw.buf, t, strconv.Itoa(vw.stack[vw.frame].arrkey))
@@ -430,6 +436,9 @@ func (vw *valueWriter) WriteObjectID(oid primitive.ObjectID) error {
}
func (vw *valueWriter) WriteRegex(pattern string, options string) error {
+ if !isValidCString(pattern) || !isValidCString(options) {
+ return errors.New("BSON regex values cannot contain null bytes")
+ }
if err := vw.writeElementHeader(bsontype.Regex, mode(0), "WriteRegex"); err != nil {
return err
}
@@ -602,3 +611,7 @@ func (vw *valueWriter) writeLength() error {
vw.buf[start+3] = byte(length >> 24)
return nil
}
+
+func isValidCString(cs string) bool {
+ return !strings.ContainsRune(cs, '\x00')
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/doc.go
index 5f411b6251..16341568dc 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/doc.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/doc.go
@@ -43,7 +43,7 @@
// 6. BSON embedded document unmarshals to the parent type (i.e. D for a D, M for an M).
// 7. BSON array unmarshals to a bson.A.
// 8. BSON ObjectId unmarshals to a primitive.ObjectID.
-// 9. BSON datetime unmarshals to a primitive.Datetime.
+// 9. BSON datetime unmarshals to a primitive.DateTime.
// 10. BSON binary unmarshals to a primitive.Binary.
// 11. BSON regular expression unmarshals to a primitive.Regex.
// 12. BSON JavaScript unmarshals to a primitive.JavaScript.
@@ -90,14 +90,26 @@
// unmarshalled into an interface{} field will be unmarshalled as a D.
//
// The encoding of each struct field can be customized by the "bson" struct tag.
-// The tag gives the name of the field, possibly followed by a comma-separated list of options.
+//
+// This tag behavior is configurable, and different struct tag behavior can be configured by initializing a new
+// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON tags
+// are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below:
+//
+// Example:
+// structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.JSONFallbackStructTagParser)
+//
+// The bson tag gives the name of the field, possibly followed by a comma-separated list of options.
// The name may be empty in order to specify options without overriding the default field name. The following options can be used
// to configure behavior:
//
// 1. omitempty: If the omitempty struct tag is specified on a field, the field will not be marshalled if it is set to
-// the zero value. By default, a struct field is only considered empty if the field's type implements the Zeroer
-// interface and the IsZero method returns true. Struct fields of types that do not implement Zeroer are always
-// marshalled as embedded documents. This tag should be used for all slice and map values.
+// the zero value. Fields with language primitive types such as integers, booleans, and strings are considered empty if
+// their value is equal to the zero value for the type (i.e. 0 for integers, false for booleans, and "" for strings).
+// Slices, maps, and arrays are considered empty if they are of length zero. Interfaces and pointers are considered
+// empty if their value is nil. By default, structs are only considered empty if the struct type implements the
+// bsoncodec.Zeroer interface and the IsZero method returns true. Struct fields whose types do not implement Zeroer are
+// never considered empty and will be marshalled as embedded documents.
+// NOTE: It is recommended that this tag be used for all slice and map fields.
//
// 2. minsize: If the minsize struct tag is specified on a field of type int64, uint, uint32, or uint64 and the value of
// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For other
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go
index fdd90d89c9..a57e1d6987 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go
@@ -10,6 +10,7 @@
package primitive
import (
+ "encoding/json"
"errors"
"fmt"
"math/big"
@@ -211,6 +212,49 @@ func (d Decimal128) IsZero() bool {
return d.h == 0 && d.l == 0
}
+// MarshalJSON returns Decimal128 as a string.
+func (d Decimal128) MarshalJSON() ([]byte, error) {
+ return json.Marshal(d.String())
+}
+
+// UnmarshalJSON creates a primitive.Decimal128 from a JSON string, an extended JSON $numberDecimal value, or the string
+// "null". If b is a JSON string or extended JSON value, d will have the value of that string, and if b is "null", d will
+// be unchanged.
+func (d *Decimal128) UnmarshalJSON(b []byte) error {
+ // Ignore "null" to keep parity with the standard library. Decoding a JSON null into a non-pointer Decimal128 field
+ // will leave the field unchanged. For pointer values, encoding/json will set the pointer to nil and will not
+ // enter the UnmarshalJSON hook.
+ if string(b) == "null" {
+ return nil
+ }
+
+ var res interface{}
+ err := json.Unmarshal(b, &res)
+ if err != nil {
+ return err
+ }
+ str, ok := res.(string)
+
+ // Extended JSON
+ if !ok {
+ m, ok := res.(map[string]interface{})
+ if !ok {
+ return errors.New("not an extended JSON Decimal128: expected document")
+ }
+ d128, ok := m["$numberDecimal"]
+ if !ok {
+ return errors.New("not an extended JSON Decimal128: expected key $numberDecimal")
+ }
+ str, ok = d128.(string)
+ if !ok {
+ return errors.New("not an extended JSON Decimal128: expected decimal to be string")
+ }
+ }
+
+ *d, err = ParseDecimal128(str)
+ return err
+}
+
func divmod(h, l uint64, div uint32) (qh, ql uint64, rem uint32) {
div64 := uint64(div)
a := h >> 32
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go
index a0eb5378cb..30aaafe6d9 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go
@@ -88,6 +88,12 @@ func ObjectIDFromHex(s string) (ObjectID, error) {
return oid, nil
}
+// IsValidObjectID returns true if the provided hex string represents a valid ObjectID and false if not.
+func IsValidObjectID(s string) bool {
+ _, err := ObjectIDFromHex(s)
+ return err == nil
+}
+
// MarshalJSON returns the ObjectID as a string
func (id ObjectID) MarshalJSON() ([]byte, error) {
return json.Marshal(id.Hex())
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go b/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go
index bd4c050398..75297f30fe 100644
--- a/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go
+++ b/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go
@@ -266,6 +266,14 @@ func (rv RawValue) Int32() int32 { return convertToCoreValue(rv).Int32() }
// panicking.
func (rv RawValue) Int32OK() (int32, bool) { return convertToCoreValue(rv).Int32OK() }
+// AsInt32 returns a BSON number as an int32. If the BSON type is not a numeric one, this method
+// will panic.
+func (rv RawValue) AsInt32() int32 { return convertToCoreValue(rv).AsInt32() }
+
+// AsInt32OK is the same as AsInt32, except that it returns a boolean instead of
+// panicking.
+func (rv RawValue) AsInt32OK() (int32, bool) { return convertToCoreValue(rv).AsInt32OK() }
+
// Timestamp returns the BSON timestamp value the Value represents. It panics if the value is a
// BSON type other than timestamp.
func (rv RawValue) Timestamp() (t, i uint32) { return convertToCoreValue(rv).Timestamp() }
@@ -282,6 +290,14 @@ func (rv RawValue) Int64() int64 { return convertToCoreValue(rv).Int64() }
// panicking.
func (rv RawValue) Int64OK() (int64, bool) { return convertToCoreValue(rv).Int64OK() }
+// AsInt64 returns a BSON number as an int64. If the BSON type is not a numeric one, this method
+// will panic.
+func (rv RawValue) AsInt64() int64 { return convertToCoreValue(rv).AsInt64() }
+
+// AsInt64OK is the same as AsInt64, except that it returns a boolean instead of
+// panicking.
+func (rv RawValue) AsInt64OK() (int64, bool) { return convertToCoreValue(rv).AsInt64OK() }
+
// Decimal128 returns the decimal the Value represents. It panics if the value is a BSON type other than
// decimal.
func (rv RawValue) Decimal128() primitive.Decimal128 { return convertToCoreValue(rv).Decimal128() }
diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go
new file mode 100644
index 0000000000..8ea60ba3c6
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/array.go
@@ -0,0 +1,164 @@
+// 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 bsoncore
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "strconv"
+)
+
+// NewArrayLengthError creates and returns an error for when the length of an array exceeds the
+// bytes available.
+func NewArrayLengthError(length, rem int) error {
+ return lengthError("array", length, rem)
+}
+
+// Array is a raw bytes representation of a BSON array.
+type Array []byte
+
+// NewArrayFromReader reads an array from r. This function will only validate the length is
+// correct and that the array ends with a null byte.
+func NewArrayFromReader(r io.Reader) (Array, error) {
+ return newBufferFromReader(r)
+}
+
+// Index searches for and retrieves the value at the given index. This method will panic if
+// the array is invalid or if the index is out of bounds.
+func (a Array) Index(index uint) Value {
+ value, err := a.IndexErr(index)
+ if err != nil {
+ panic(err)
+ }
+ return value
+}
+
+// IndexErr searches for and retrieves the value at the given index.
+func (a Array) IndexErr(index uint) (Value, error) {
+ elem, err := indexErr(a, index)
+ if err != nil {
+ return Value{}, err
+ }
+ return elem.Value(), err
+}
+
+// DebugString outputs a human readable version of Array. It will attempt to stringify the
+// valid components of the array even if the entire array is not valid.
+func (a Array) DebugString() string {
+ if len(a) < 5 {
+ return "<malformed>"
+ }
+ var buf bytes.Buffer
+ buf.WriteString("Array")
+ length, rem, _ := ReadLength(a) // We know we have enough bytes to read the length
+ buf.WriteByte('(')
+ buf.WriteString(strconv.Itoa(int(length)))
+ length -= 4
+ buf.WriteString(")[")
+ var elem Element
+ var ok bool
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ buf.WriteString(fmt.Sprintf("<malformed (%d)>", length))
+ break
+ }
+ fmt.Fprintf(&buf, "%s", elem.Value().DebugString())
+ if length != 1 {
+ buf.WriteByte(',')
+ }
+ }
+ buf.WriteByte(']')
+
+ return buf.String()
+}
+
+// String outputs an ExtendedJSON version of Array. If the Array is not valid, this method
+// returns an empty string.
+func (a Array) String() string {
+ if len(a) < 5 {
+ return ""
+ }
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+
+ length, rem, _ := ReadLength(a) // We know we have enough bytes to read the length
+
+ length -= 4
+
+ var elem Element
+ var ok bool
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return ""
+ }
+ fmt.Fprintf(&buf, "%s", elem.Value().String())
+ if length > 1 {
+ buf.WriteByte(',')
+ }
+ }
+ if length != 1 { // Missing final null byte or inaccurate length
+ return ""
+ }
+
+ buf.WriteByte(']')
+ return buf.String()
+}
+
+// Values returns this array as a slice of values. The returned slice will contain valid values.
+// If the array is not valid, the values up to the invalid point will be returned along with an
+// error.
+func (a Array) Values() ([]Value, error) {
+ return values(a)
+}
+
+// Validate validates the array and ensures the elements contained within are valid.
+func (a Array) Validate() error {
+ length, rem, ok := ReadLength(a)
+ if !ok {
+ return NewInsufficientBytesError(a, rem)
+ }
+ if int(length) > len(a) {
+ return NewArrayLengthError(int(length), len(a))
+ }
+ if a[length-1] != 0x00 {
+ return ErrMissingNull
+ }
+
+ length -= 4
+ var elem Element
+
+ var keyNum int64
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return NewInsufficientBytesError(a, rem)
+ }
+
+ // validate element
+ err := elem.Validate()
+ if err != nil {
+ return err
+ }
+
+ // validate keys increase numerically
+ if fmt.Sprint(keyNum) != elem.Key() {
+ return fmt.Errorf("array key %q is out of order or invalid", elem.Key())
+ }
+ keyNum++
+ }
+
+ if len(rem) < 1 || rem[0] != 0x00 {
+ return ErrMissingNull
+ }
+ return nil
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_arraybuilder.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_arraybuilder.go
new file mode 100644
index 0000000000..7e6937d896
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_arraybuilder.go
@@ -0,0 +1,201 @@
+// 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 bsoncore
+
+import (
+ "strconv"
+
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+// ArrayBuilder builds a bson array
+type ArrayBuilder struct {
+ arr []byte
+ indexes []int32
+ keys []int
+}
+
+// NewArrayBuilder creates a new ArrayBuilder
+func NewArrayBuilder() *ArrayBuilder {
+ return (&ArrayBuilder{}).startArray()
+}
+
+// startArray reserves the array's length and sets the index to where the length begins
+func (a *ArrayBuilder) startArray() *ArrayBuilder {
+ var index int32
+ index, a.arr = AppendArrayStart(a.arr)
+ a.indexes = append(a.indexes, index)
+ a.keys = append(a.keys, 0)
+ return a
+}
+
+// Build updates the length of the array and index to the beginning of the documents length
+// bytes, then returns the array (bson bytes)
+func (a *ArrayBuilder) Build() Array {
+ lastIndex := len(a.indexes) - 1
+ lastKey := len(a.keys) - 1
+ a.arr, _ = AppendArrayEnd(a.arr, a.indexes[lastIndex])
+ a.indexes = a.indexes[:lastIndex]
+ a.keys = a.keys[:lastKey]
+ return a.arr
+}
+
+// incrementKey() increments the value keys and returns the key to be used to a.appendArray* functions
+func (a *ArrayBuilder) incrementKey() string {
+ idx := len(a.keys) - 1
+ key := strconv.Itoa(a.keys[idx])
+ a.keys[idx]++
+ return key
+}
+
+// AppendInt32 will append i32 to ArrayBuilder.arr
+func (a *ArrayBuilder) AppendInt32(i32 int32) *ArrayBuilder {
+ a.arr = AppendInt32Element(a.arr, a.incrementKey(), i32)
+ return a
+}
+
+// AppendDocument will append doc to ArrayBuilder.arr
+func (a *ArrayBuilder) AppendDocument(doc []byte) *ArrayBuilder {
+ a.arr = AppendDocumentElement(a.arr, a.incrementKey(), doc)
+ return a
+}
+
+// AppendArray will append arr to ArrayBuilder.arr
+func (a *ArrayBuilder) AppendArray(arr []byte) *ArrayBuilder {
+ a.arr = AppendArrayElement(a.arr, a.incrementKey(), arr)
+ return a
+}
+
+// AppendDouble will append f to ArrayBuilder.doc
+func (a *ArrayBuilder) AppendDouble(f float64) *ArrayBuilder {
+ a.arr = AppendDoubleElement(a.arr, a.incrementKey(), f)
+ return a
+}
+
+// AppendString will append str to ArrayBuilder.doc
+func (a *ArrayBuilder) AppendString(str string) *ArrayBuilder {
+ a.arr = AppendStringElement(a.arr, a.incrementKey(), str)
+ return a
+}
+
+// AppendObjectID will append oid to ArrayBuilder.doc
+func (a *ArrayBuilder) AppendObjectID(oid primitive.ObjectID) *ArrayBuilder {
+ a.arr = AppendObjectIDElement(a.arr, a.incrementKey(), oid)
+ return a
+}
+
+// AppendBinary will append a BSON binary element using subtype, and
+// b to a.arr
+func (a *ArrayBuilder) AppendBinary(subtype byte, b []byte) *ArrayBuilder {
+ a.arr = AppendBinaryElement(a.arr, a.incrementKey(), subtype, b)
+ return a
+}
+
+// AppendUndefined will append a BSON undefined element using key to a.arr
+func (a *ArrayBuilder) AppendUndefined() *ArrayBuilder {
+ a.arr = AppendUndefinedElement(a.arr, a.incrementKey())
+ return a
+}
+
+// AppendBoolean will append a boolean element using b to a.arr
+func (a *ArrayBuilder) AppendBoolean(b bool) *ArrayBuilder {
+ a.arr = AppendBooleanElement(a.arr, a.incrementKey(), b)
+ return a
+}
+
+// AppendDateTime will append datetime element dt to a.arr
+func (a *ArrayBuilder) AppendDateTime(dt int64) *ArrayBuilder {
+ a.arr = AppendDateTimeElement(a.arr, a.incrementKey(), dt)
+ return a
+}
+
+// AppendNull will append a null element to a.arr
+func (a *ArrayBuilder) AppendNull() *ArrayBuilder {
+ a.arr = AppendNullElement(a.arr, a.incrementKey())
+ return a
+}
+
+// AppendRegex will append pattern and options to a.arr
+func (a *ArrayBuilder) AppendRegex(pattern, options string) *ArrayBuilder {
+ a.arr = AppendRegexElement(a.arr, a.incrementKey(), pattern, options)
+ return a
+}
+
+// AppendDBPointer will append ns and oid to a.arr
+func (a *ArrayBuilder) AppendDBPointer(ns string, oid primitive.ObjectID) *ArrayBuilder {
+ a.arr = AppendDBPointerElement(a.arr, a.incrementKey(), ns, oid)
+ return a
+}
+
+// AppendJavaScript will append js to a.arr
+func (a *ArrayBuilder) AppendJavaScript(js string) *ArrayBuilder {
+ a.arr = AppendJavaScriptElement(a.arr, a.incrementKey(), js)
+ return a
+}
+
+// AppendSymbol will append symbol to a.arr
+func (a *ArrayBuilder) AppendSymbol(symbol string) *ArrayBuilder {
+ a.arr = AppendSymbolElement(a.arr, a.incrementKey(), symbol)
+ return a
+}
+
+// AppendCodeWithScope will append code and scope to a.arr
+func (a *ArrayBuilder) AppendCodeWithScope(code string, scope Document) *ArrayBuilder {
+ a.arr = AppendCodeWithScopeElement(a.arr, a.incrementKey(), code, scope)
+ return a
+}
+
+// AppendTimestamp will append t and i to a.arr
+func (a *ArrayBuilder) AppendTimestamp(t, i uint32) *ArrayBuilder {
+ a.arr = AppendTimestampElement(a.arr, a.incrementKey(), t, i)
+ return a
+}
+
+// AppendInt64 will append i64 to a.arr
+func (a *ArrayBuilder) AppendInt64(i64 int64) *ArrayBuilder {
+ a.arr = AppendInt64Element(a.arr, a.incrementKey(), i64)
+ return a
+}
+
+// AppendDecimal128 will append d128 to a.arr
+func (a *ArrayBuilder) AppendDecimal128(d128 primitive.Decimal128) *ArrayBuilder {
+ a.arr = AppendDecimal128Element(a.arr, a.incrementKey(), d128)
+ return a
+}
+
+// AppendMaxKey will append a max key element to a.arr
+func (a *ArrayBuilder) AppendMaxKey() *ArrayBuilder {
+ a.arr = AppendMaxKeyElement(a.arr, a.incrementKey())
+ return a
+}
+
+// AppendMinKey will append a min key element to a.arr
+func (a *ArrayBuilder) AppendMinKey() *ArrayBuilder {
+ a.arr = AppendMinKeyElement(a.arr, a.incrementKey())
+ return a
+}
+
+// AppendValue appends a BSON value to the array.
+func (a *ArrayBuilder) AppendValue(val Value) *ArrayBuilder {
+ a.arr = AppendValueElement(a.arr, a.incrementKey(), val)
+ return a
+}
+
+// StartArray starts building an inline Array. After this document is completed,
+// the user must call a.FinishArray
+func (a *ArrayBuilder) StartArray() *ArrayBuilder {
+ a.arr = AppendHeader(a.arr, bsontype.Array, a.incrementKey())
+ a.startArray()
+ return a
+}
+
+// FinishArray builds the most recent array created
+func (a *ArrayBuilder) FinishArray() *ArrayBuilder {
+ a.arr = a.Build()
+ return a
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_documentbuilder.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_documentbuilder.go
new file mode 100644
index 0000000000..b0d45212db
--- /dev/null
+++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bson_documentbuilder.go
@@ -0,0 +1,189 @@
+// 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 bsoncore
+
+import (
+ "go.mongodb.org/mongo-driver/bson/bsontype"
+ "go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+// DocumentBuilder builds a bson document
+type DocumentBuilder struct {
+ doc []byte
+ indexes []int32
+}
+
+// startDocument reserves the document's length and set the index to where the length begins
+func (db *DocumentBuilder) startDocument() *DocumentBuilder {
+ var index int32
+ index, db.doc = AppendDocumentStart(db.doc)
+ db.indexes = append(db.indexes, index)
+ return db
+}
+
+// NewDocumentBuilder creates a new DocumentBuilder
+func NewDocumentBuilder() *DocumentBuilder {
+ return (&DocumentBuilder{}).startDocument()
+}
+
+// Build updates the length of the document and index to the beginning of the documents length
+// bytes, then returns the document (bson bytes)
+func (db *DocumentBuilder) Build() Document {
+ last := len(db.indexes) - 1
+ db.doc, _ = AppendDocumentEnd(db.doc, db.indexes[last])
+ db.indexes = db.indexes[:last]
+ return db.doc
+}
+
+// AppendInt32 will append an int32 element using key and i32 to DocumentBuilder.doc
+func (db *DocumentBuilder) AppendInt32(key string, i32 int32) *DocumentBuilder {
+ db.doc = AppendInt32Element(db.doc, key, i32)
+ return db
+}
+
+// AppendDocument will append a bson embeded document element using key
+// and doc to DocumentBuilder.doc
+func (db *DocumentBuilder) AppendDocument(key string, doc []byte) *DocumentBuilder {
+ db.doc = AppendDocumentElement(db.doc, key, doc)
+ return db
+}
+
+// AppendArray will append a bson array using key and arr to DocumentBuilder.doc
+func (db *DocumentBuilder) AppendArray(key string, arr []byte) *DocumentBuilder {
+ db.doc = AppendHeader(db.doc, bsontype.Array, key)
+ db.doc = AppendArray(db.doc, arr)
+ return db
+}
+
+// AppendDouble will append a double element using key and f to DocumentBuilder.doc
+func (db *DocumentBuilder) AppendDouble(key string, f float64) *DocumentBuilder {
+ db.doc = AppendDoubleElement(db.doc, key, f)
+ return db
+}
+
+// AppendString will append str to DocumentBuilder.doc with the given key
+func (db *DocumentBuilder) AppendString(key string, str string) *DocumentBuilder {
+ db.doc = AppendStringElement(db.doc, key, str)
+ return db
+}
+
+// AppendObjectID will append oid to DocumentBuilder.doc with the given key
+func (db *DocumentBuilder) AppendObjectID(key string, oid primitive.ObjectID) *DocumentBuilder {
+ db.doc = AppendObjectIDElement(db.doc, key, oid)
+ return db
+}
+
+// AppendBinary will append a BSON binary element using key, subtype, and
+// b to db.doc
+func (db *DocumentBuilder) AppendBinary(key string, subtype byte, b []byte) *DocumentBuilder {
+ db.doc = AppendBinaryElement(db.doc, key, subtype, b)
+ return db
+}
+
+// AppendUndefined will append a BSON undefined element using key to db.doc
+func (db *DocumentBuilder) AppendUndefined(key string) *DocumentBuilder {
+ db.doc = AppendUndefinedElement(db.doc, key)
+ return db
+}
+
+// AppendBoolean will append a boolean element using key and b to db.doc
+func (db *DocumentBuilder) AppendBoolean(key string, b bool) *DocumentBuilder {
+ db.doc = AppendBooleanElement(db.doc, key, b)
+ return db
+}
+
+// AppendDateTime will append a datetime element using key and dt to db.doc
+func (db *DocumentBuilder) AppendDateTime(key string, dt int64) *DocumentBuilder {
+ db.doc = AppendDateTimeElement(db.doc, key, dt)
+ return db
+}
+
+// AppendNull will append a null element using key to db.doc
+func (db *DocumentBuilder) AppendNull(key string) *DocumentBuilder {
+ db.doc = AppendNullElement(db.doc, key)
+ return db
+}
+
+// AppendRegex will append pattern and options using key to db.doc
+func (db *DocumentBuilder) AppendRegex(key, pattern, options string) *DocumentBuilder {
+ db.doc = AppendRegexElement(db.doc, key, pattern, options)
+ return db
+}
+
+// AppendDBPointer will append ns and oid to using key to db.doc
+func (db *DocumentBuilder) AppendDBPointer(key string, ns string, oid primitive.ObjectID) *DocumentBuilder {
+ db.doc = AppendDBPointerElement(db.doc, key, ns, oid)
+ return db
+}
+
+// AppendJavaScript will append js using the provided key to db.doc
+func (db *DocumentBuilder) AppendJavaScript(key, js string) *DocumentBuilder {
+ db.doc = AppendJavaScriptElement(db.doc, key, js)
+ return db
+}
+
+// AppendSymbol will append a BSON symbol element using key and symbol db.doc
+func (db *DocumentBuilder) AppendSymbol(key, symbol string) *DocumentBuilder {
+ db.doc = AppendSymbolElement(db.doc, key, symbol)
+ return db
+}
+
+// AppendCodeWithScope will append code and scope using key to db.doc
+func (db *DocumentBuilder) AppendCodeWithScope(key string, code string, scope Document) *DocumentBuilder {
+ db.doc = AppendCodeWithScopeElement(db.doc, key, code, scope)
+ return db
+}
+
+// AppendTimestamp will append t and i to db.doc using provided key
+func (db *DocumentBuilder) AppendTimestamp(key string, t, i uint32) *DocumentBuilder {
+ db.doc = AppendTimestampElement(db.doc, key, t, i)
+ return db
+}
+
+// AppendInt64 will append i64 to dst using key to db.doc
+func (db *DocumentBuilder) AppendInt64(key string, i64 int64) *DocumentBuilder {
+ db.doc = AppendInt64Element(db.doc, key, i64)
+ return db
+}
+
+// AppendDecimal128 will append d128 to db.doc using provided key
+func (db *DocumentBuilder) AppendDecimal128(key string, d128 primitive.Decimal128) *DocumentBuilder {
+ db.doc = AppendDecimal128Element(db.doc, key, d128)
+ return db
+}
+
+// AppendMaxKey will append a max key element using key to db.doc
+func (db *DocumentBuilder) AppendMaxKey(key string) *DocumentBuilder {
+ db.doc = AppendMaxKeyElement(db.doc, key)
+ return db
+}
+
+// AppendMinKey will append a min key element using key to db.doc
+func (db *DocumentBuilder) AppendMinKey(key string) *DocumentBuilder {
+ db.doc = AppendMinKeyElement(db.doc, key)
+ return db
+}
+
+// AppendValue will append a BSON element with the provided key and value to the document.
+func (db *DocumentBuilder) AppendValue(key string, val Value) *DocumentBuilder {
+ db.doc = AppendValueElement(db.doc, key, val)
+ return db
+}
+
+// StartDocument starts building an inline document element with the provided key
+// After this document is completed, the user must call finishDocument
+func (db *DocumentBuilder) StartDocument(key string) *DocumentBuilder {
+ db.doc = AppendHeader(db.doc, bsontype.EmbeddedDocument, key)
+ db = db.startDocument()
+ return db
+}
+
+// FinishDocument builds the most recent document created
+func (db *DocumentBuilder) FinishDocument() *DocumentBuilder {
+ db.doc = db.Build()
+ return db
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go
index f7997fbbb7..97ef1b85d5 100644
--- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go
+++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/bsoncore.go
@@ -30,17 +30,21 @@ import (
"fmt"
"math"
"strconv"
+ "strings"
"time"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/bson/primitive"
)
-// EmptyDocumentLength is the length of a document that has been started/ended but has no elements.
-const EmptyDocumentLength = 5
-
-// nullTerminator is a string version of the 0 byte that is appended at the end of cstrings.
-const nullTerminator = string(byte(0))
+const (
+ // EmptyDocumentLength is the length of a document that has been started/ended but has no elements.
+ EmptyDocumentLength = 5
+ // nullTerminator is a string version of the 0 byte that is appended at the end of cstrings.
+ nullTerminator = string(byte(0))
+ invalidKeyPanicMsg = "BSON element keys cannot contain null bytes"
+ invalidRegexPanicMsg = "BSON regex values cannot contain null bytes"
+)
// AppendType will append t to dst and return the extended buffer.
func AppendType(dst []byte, t bsontype.Type) []byte { return append(dst, byte(t)) }
@@ -51,6 +55,10 @@ func AppendKey(dst []byte, key string) []byte { return append(dst, key+nullTermi
// AppendHeader will append Type t and key to dst and return the extended
// buffer.
func AppendHeader(dst []byte, t bsontype.Type, key string) []byte {
+ if !isValidCString(key) {
+ panic(invalidKeyPanicMsg)
+ }
+
dst = AppendType(dst, t)
dst = append(dst, key...)
return append(dst, 0x00)
@@ -430,6 +438,10 @@ func AppendNullElement(dst []byte, key string) []byte { return AppendHeader(dst,
// AppendRegex will append pattern and options to dst and return the extended buffer.
func AppendRegex(dst []byte, pattern, options string) []byte {
+ if !isValidCString(pattern) || !isValidCString(options) {
+ panic(invalidRegexPanicMsg)
+ }
+
return append(dst, pattern+nullTerminator+options+nullTerminator...)
}
@@ -818,7 +830,7 @@ func readstring(src []byte) (string, []byte, bool) {
if !ok {
return "", src, false
}
- if len(src[4:]) < int(l) {
+ if len(src[4:]) < int(l) || l == 0 {
return "", src, false
}
@@ -844,3 +856,7 @@ func appendBinarySubtype2(dst []byte, subtype byte, b []byte) []byte {
dst = appendLength(dst, int32(len(b)))
return append(dst, b...)
}
+
+func isValidCString(cs string) bool {
+ return !strings.ContainsRune(cs, '\x00')
+}
diff --git a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go
index d397cde299..b77c593ede 100644
--- a/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go
+++ b/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/document.go
@@ -17,17 +17,20 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
-// DocumentValidationError is an error type returned when attempting to validate a document.
-type DocumentValidationError string
+// ValidationError is an error type returned when attempting to validate a document or array.
+type ValidationError string
-func (dve DocumentValidationError) Error() string { return string(dve) }
+func (ve ValidationError) Error() string { return string(ve) }
// NewDocumentLengthError creates and returns an error for when the length of a document exceeds the
// bytes available.
func NewDocumentLengthError(length, rem int) error {
- return DocumentValidationError(
- fmt.Sprintf("document length exceeds available bytes. length=%d remainingBytes=%d", length, rem),
- )
+ return lengthError("document", length, rem)
+}
+
+func lengthError(bufferType string, length, rem int) error {
+ return ValidationError(fmt.Sprintf("%v length exceeds available bytes. length=%d remainingBytes=%d",
+ bufferType, length, rem))
}
// InsufficientBytesError indicates that there were not enough bytes to read the next component.
@@ -94,15 +97,16 @@ func (idte InvalidDepthTraversalError) Error() string {
)
}
-// ErrMissingNull is returned when a document's last byte is not null.
-const ErrMissingNull DocumentValidationError = "document end is missing null byte"
+// ErrMissingNull is returned when a document or array's last byte is not null.
+const ErrMissingNull ValidationError = "document or array end is missing null byte"
+
+// ErrInvalidLength indicates that a length in a binary representation of a BSON document or array
+// is invalid.
+const ErrInvalidLength ValidationError = "document or array length is invalid"
// ErrNilReader indicates that an operation was attempted on a nil io.Reader.
var ErrNilReader = errors.New("nil reader")
-// ErrInvalidLength indicates that a length in a binary representation of a BSON document is invalid.
-var ErrInvalidLength = errors.New("document length is invalid")
-
// ErrEmptyKey indicates that no key was provided to a Lookup method.
var ErrEmptyKey = errors.New("empty key provided")
@@ -115,12 +119,13 @@ var ErrOutOfBounds = errors.New("out of bounds")
// Document is a raw bytes representation of a BSON document.
type Document []byte
-// Array is a raw bytes representation of a BSON array.
-type Array = Document
-
// NewDocumentFromReader reads a document from r. This function will only validate the length is
// correct and that the document ends with a null byte.
func NewDocumentFromReader(r io.Reader) (Document, error) {
+ return newBufferFromReader(r)
+}
+
+func newBufferFromReader(r io.Reader) ([]byte, error) {
if r == nil {
return nil, ErrNilReader
}
@@ -137,20 +142,20 @@ func NewDocumentFromReader(r io.Reader) (Document, error) {
if length < 0 {
return nil, ErrInvalidLength
}
- document := make([]byte, length)
+ buffer := make([]byte, length)
- copy(document, lengthBytes[:])
+ copy(buffer, lengthBytes[:])
- _, err = io.ReadFull(r, document[4:])
+ _, err = io.ReadFull(r, buffer[4:])
if err != nil {
return nil, err
}
- if document[length-1] != 0x00 {
+ if buffer[length-1] != 0x00 {
return nil, ErrMissingNull
}
- return document, nil
+ return buffer, nil
}
// Lookup searches the document, potentially recursively, for the given key. If there are multiple
@@ -221,9 +226,13 @@ func (d Document) Index(index uint) Element {
// IndexErr searches for and retrieves the element at the given index.
func (d Document) IndexErr(index uint) (Element, error) {
- length, rem, ok := ReadLength(d)
+ return indexErr(d, index)
+}
+
+func indexErr(b []byte, index uint) (Element, error) {
+ length, rem, ok := ReadLength(b)
if !ok {
- return nil, NewInsufficientBytesError(d, rem)
+ return nil, NewInsufficientBytesError(b, rem)
}
length -= 4
@@ -234,7 +243,7 @@ func (d Document) IndexErr(index uint) (Element, error) {
elem, rem, ok = ReadElement(rem)
length -= int32(len(elem))
if !ok {
- return nil, NewInsufficientBytesError(d, rem)
+ return nil, NewInsufficientBytesError(b, rem)
}
if current != index {
current++
@@ -338,9 +347,13 @@ func (d Document) Elements() ([]Element, error) {
// If the document is not valid, the values up to the invalid point will be returned along with an
// error.
func (d Document) Values() ([]Value, error) {
- length, rem, ok := ReadLength(d)
+ return values(d)
+}
+
+func values(b []byte) ([]Value, error) {
+ length, rem, ok := ReadLength(b)
if !ok {
- return nil, NewInsufficientBytesError(d, rem)
+ return nil, NewInsufficientBytesError(b, rem)
}
length -= 4
@@ -351,7 +364,7 @@ func (d Document) Values() ([]Value, error) {
elem, rem, ok = ReadElement(rem)
length -= int32(len(elem))
if !ok {
- return vals, NewInsufficientBytesError(d, rem)
+ return vals, NewInsufficientBytesError(b, rem)
}
if err := elem.Value().Validate(); err != nil {
return vals, err
@@ -368,7 +381,7 @@ func (d Document) Validate() error {
return NewInsufficientBytesError(d, rem)
}
if int(length) > len(d) {
- return d.lengtherror(int(length), len(d))
+ return NewDocumentLengthError(int(length), len(d))
}
if d[length-1] != 0x00 {
return ErrMissingNull
@@ -394,7 +407,3 @@ func (d Document) Validate() error {
}
return nil
}
-
-func (Document) lengtherror(length, rem int) error {
- return DocumentValidationError(fmt.Sprintf("document length exceeds available bytes. length=%d remainingBytes=%d", length, rem))
-}