diff options
| author | 2024-03-06 09:05:45 -0800 | |
|---|---|---|
| committer | 2024-03-06 18:05:45 +0100 | |
| commit | fc3741365c27f1d703e8a736af95b95ff811cc45 (patch) | |
| tree | 929f1d5e20d1469d63a3dfe81d38d89f9a073c5a /vendor/go.mongodb.org/mongo-driver/bson | |
| parent | [chore/bugfix] Little DB fixes (#2726) (diff) | |
| download | gotosocial-fc3741365c27f1d703e8a736af95b95ff811cc45.tar.xz | |
[bugfix] Fix Swagger spec and add test script (#2698)
* Add Swagger spec test script
* Fix Swagger spec errors not related to statuses with polls
* Add API tests that post a status with a poll
* Fix creating a status with a poll from form params
* Fix Swagger spec errors related to statuses with polls (this is the last error)
* Fix Swagger spec warnings not related to unused definitions
* Suppress a duplicate list update params definition that was somehow causing wrong param names
* Add Swagger test to CI
- updates Drone config
- vendorizes go-swagger
- fixes a file extension issue that caused the test script to generate JSON instead of YAML with the vendorized version
* Put `Sample: ` on its own line everywhere
* Remove unused id param from emojiCategoriesGet
* Add 5 more pairs of profile fields to account update API Swagger
* Remove Swagger prefix from dummy fields
It makes the generated code look weird
* Manually annotate params for statusCreate operation
* Fix all remaining Swagger spec warnings
- Change some models into operation parameters
- Ignore models that already correspond to manually documented operation parameters but can't be trivially changed (those with file fields)
* Documented that creating a status with scheduled_at isn't implemented yet
* sign drone.yml
* Fix filter API Swagger errors
* fixup! Fix filter API Swagger errors
---------
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Diffstat (limited to 'vendor/go.mongodb.org/mongo-driver/bson')
58 files changed, 13959 insertions, 0 deletions
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bson.go b/vendor/go.mongodb.org/mongo-driver/bson/bson.go new file mode 100644 index 000000000..a0d818582 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bson.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 +// +// Based on gopkg.in/mgo.v2/bson by Gustavo Niemeyer +// See THIRD-PARTY-NOTICES for original license terms. + +package bson // import "go.mongodb.org/mongo-driver/bson" + +import ( +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +// Zeroer allows custom struct types to implement a report of zero +// state. All struct types that don't implement Zeroer or where IsZero +// returns false are considered to be not zero. +type Zeroer interface { +	IsZero() bool +} + +// D is an ordered representation of a BSON document. This type should be used when the order of the elements matters, +// such as MongoDB command documents. If the order of the elements does not matter, an M should be used instead. +// +// A D should not be constructed with duplicate key names, as that can cause undefined server behavior. +// +// Example usage: +// +//	bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}} +type D = primitive.D + +// E represents a BSON element for a D. It is usually used inside a D. +type E = primitive.E + +// M is an unordered representation of a BSON document. This type should be used when the order of the elements does not +// matter. This type is handled as a regular map[string]interface{} when encoding and decoding. Elements will be +// serialized in an undefined, random order. If the order of the elements matters, a D should be used instead. +// +// Example usage: +// +//	bson.M{"foo": "bar", "hello": "world", "pi": 3.14159} +type M = primitive.M + +// An A is an ordered representation of a BSON array. +// +// Example usage: +// +//	bson.A{"bar", "world", 3.14159, bson.D{{"qux", 12345}}} +type A = primitive.A diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go new file mode 100644 index 000000000..4e24f9eed --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go @@ -0,0 +1,50 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"reflect" + +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +// ArrayCodec is the Codec used for bsoncore.Array values. +type ArrayCodec struct{} + +var defaultArrayCodec = NewArrayCodec() + +// NewArrayCodec returns an ArrayCodec. +func NewArrayCodec() *ArrayCodec { +	return &ArrayCodec{} +} + +// EncodeValue is the ValueEncoder for bsoncore.Array values. +func (ac *ArrayCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tCoreArray { +		return ValueEncoderError{Name: "CoreArrayEncodeValue", Types: []reflect.Type{tCoreArray}, Received: val} +	} + +	arr := val.Interface().(bsoncore.Array) +	return bsonrw.Copier{}.CopyArrayFromBytes(vw, arr) +} + +// DecodeValue is the ValueDecoder for bsoncore.Array values. +func (ac *ArrayCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tCoreArray { +		return ValueDecoderError{Name: "CoreArrayDecodeValue", Types: []reflect.Type{tCoreArray}, Received: val} +	} + +	if val.IsNil() { +		val.Set(reflect.MakeSlice(val.Type(), 0, 0)) +	} + +	val.SetLen(0) +	arr, err := bsonrw.Copier{}.AppendArrayBytes(val.Interface().(bsoncore.Array), vr) +	val.Set(reflect.ValueOf(arr)) +	return err +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go new file mode 100644 index 000000000..098ed69f9 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/bsoncodec.go @@ -0,0 +1,238 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec // import "go.mongodb.org/mongo-driver/bson/bsoncodec" + +import ( +	"fmt" +	"reflect" +	"strings" + +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +var ( +	emptyValue = reflect.Value{} +) + +// Marshaler is an interface implemented by types that can marshal themselves +// into a BSON document represented as bytes. The bytes returned must be a valid +// BSON document if the error is nil. +type Marshaler interface { +	MarshalBSON() ([]byte, error) +} + +// ValueMarshaler is an interface implemented by types that can marshal +// themselves into a BSON value as bytes. The type must be the valid type for +// the bytes returned. The bytes and byte type together must be valid if the +// error is nil. +type ValueMarshaler interface { +	MarshalBSONValue() (bsontype.Type, []byte, error) +} + +// Unmarshaler is an interface implemented by types that can unmarshal a BSON +// document representation of themselves. The BSON bytes can be assumed to be +// valid. UnmarshalBSON must copy the BSON bytes if it wishes to retain the data +// after returning. +type Unmarshaler interface { +	UnmarshalBSON([]byte) error +} + +// ValueUnmarshaler is an interface implemented by types that can unmarshal a +// BSON value representation of themselves. The BSON bytes and type can be +// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it +// wishes to retain the data after returning. +type ValueUnmarshaler interface { +	UnmarshalBSONValue(bsontype.Type, []byte) error +} + +// ValueEncoderError is an error returned from a ValueEncoder when the provided value can't be +// encoded by the ValueEncoder. +type ValueEncoderError struct { +	Name     string +	Types    []reflect.Type +	Kinds    []reflect.Kind +	Received reflect.Value +} + +func (vee ValueEncoderError) Error() string { +	typeKinds := make([]string, 0, len(vee.Types)+len(vee.Kinds)) +	for _, t := range vee.Types { +		typeKinds = append(typeKinds, t.String()) +	} +	for _, k := range vee.Kinds { +		if k == reflect.Map { +			typeKinds = append(typeKinds, "map[string]*") +			continue +		} +		typeKinds = append(typeKinds, k.String()) +	} +	received := vee.Received.Kind().String() +	if vee.Received.IsValid() { +		received = vee.Received.Type().String() +	} +	return fmt.Sprintf("%s can only encode valid %s, but got %s", vee.Name, strings.Join(typeKinds, ", "), received) +} + +// ValueDecoderError is an error returned from a ValueDecoder when the provided value can't be +// decoded by the ValueDecoder. +type ValueDecoderError struct { +	Name     string +	Types    []reflect.Type +	Kinds    []reflect.Kind +	Received reflect.Value +} + +func (vde ValueDecoderError) Error() string { +	typeKinds := make([]string, 0, len(vde.Types)+len(vde.Kinds)) +	for _, t := range vde.Types { +		typeKinds = append(typeKinds, t.String()) +	} +	for _, k := range vde.Kinds { +		if k == reflect.Map { +			typeKinds = append(typeKinds, "map[string]*") +			continue +		} +		typeKinds = append(typeKinds, k.String()) +	} +	received := vde.Received.Kind().String() +	if vde.Received.IsValid() { +		received = vde.Received.Type().String() +	} +	return fmt.Sprintf("%s can only decode valid and settable %s, but got %s", vde.Name, strings.Join(typeKinds, ", "), received) +} + +// EncodeContext is the contextual information required for a Codec to encode a +// value. +type EncodeContext struct { +	*Registry +	MinSize bool +} + +// DecodeContext is the contextual information required for a Codec to decode a +// value. +type DecodeContext struct { +	*Registry +	Truncate bool + +	// Ancestor is the type of a containing document. This is mainly used to determine what type +	// should be used when decoding an embedded document into an empty interface. For example, if +	// Ancestor is a bson.M, BSON embedded document values being decoded into an empty interface +	// will be decoded into a bson.M. +	// +	// Deprecated: Use DefaultDocumentM or DefaultDocumentD instead. +	Ancestor reflect.Type + +	// defaultDocumentType specifies the Go type to decode top-level and nested BSON documents into. In particular, the +	// usage for this field is restricted to data typed as "interface{}" or "map[string]interface{}". If DocumentType is +	// set to a type that a BSON document cannot be unmarshaled into (e.g. "string"), unmarshalling will result in an +	// error. DocumentType overrides the Ancestor field. +	defaultDocumentType reflect.Type +} + +// DefaultDocumentM will decode empty documents using the primitive.M type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (dc *DecodeContext) DefaultDocumentM() { +	dc.defaultDocumentType = reflect.TypeOf(primitive.M{}) +} + +// DefaultDocumentD will decode empty documents using the primitive.D type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (dc *DecodeContext) DefaultDocumentD() { +	dc.defaultDocumentType = reflect.TypeOf(primitive.D{}) +} + +// ValueCodec is the interface that groups the methods to encode and decode +// values. +type ValueCodec interface { +	ValueEncoder +	ValueDecoder +} + +// ValueEncoder is the interface implemented by types that can handle the encoding of a value. +type ValueEncoder interface { +	EncodeValue(EncodeContext, bsonrw.ValueWriter, reflect.Value) error +} + +// ValueEncoderFunc is an adapter function that allows a function with the correct signature to be +// used as a ValueEncoder. +type ValueEncoderFunc func(EncodeContext, bsonrw.ValueWriter, reflect.Value) error + +// EncodeValue implements the ValueEncoder interface. +func (fn ValueEncoderFunc) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	return fn(ec, vw, val) +} + +// ValueDecoder is the interface implemented by types that can handle the decoding of a value. +type ValueDecoder interface { +	DecodeValue(DecodeContext, bsonrw.ValueReader, reflect.Value) error +} + +// ValueDecoderFunc is an adapter function that allows a function with the correct signature to be +// used as a ValueDecoder. +type ValueDecoderFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) error + +// DecodeValue implements the ValueDecoder interface. +func (fn ValueDecoderFunc) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	return fn(dc, vr, val) +} + +// typeDecoder is the interface implemented by types that can handle the decoding of a value given its type. +type typeDecoder interface { +	decodeType(DecodeContext, bsonrw.ValueReader, reflect.Type) (reflect.Value, error) +} + +// typeDecoderFunc is an adapter function that allows a function with the correct signature to be used as a typeDecoder. +type typeDecoderFunc func(DecodeContext, bsonrw.ValueReader, reflect.Type) (reflect.Value, error) + +func (fn typeDecoderFunc) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	return fn(dc, vr, t) +} + +// decodeAdapter allows two functions with the correct signatures to be used as both a ValueDecoder and typeDecoder. +type decodeAdapter struct { +	ValueDecoderFunc +	typeDecoderFunc +} + +var _ ValueDecoder = decodeAdapter{} +var _ typeDecoder = decodeAdapter{} + +// decodeTypeOrValue calls decoder.decodeType is decoder is a typeDecoder. Otherwise, it allocates a new element of type +// t and calls decoder.DecodeValue on it. +func decodeTypeOrValue(decoder ValueDecoder, dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	td, _ := decoder.(typeDecoder) +	return decodeTypeOrValueWithInfo(decoder, td, dc, vr, t, true) +} + +func decodeTypeOrValueWithInfo(vd ValueDecoder, td typeDecoder, dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type, convert bool) (reflect.Value, error) { +	if td != nil { +		val, err := td.decodeType(dc, vr, t) +		if err == nil && convert && val.Type() != t { +			// This conversion step is necessary for slices and maps. If a user declares variables like: +			// +			// type myBool bool +			// var m map[string]myBool +			// +			// and tries to decode BSON bytes into the map, the decoding will fail if this conversion is not present +			// because we'll try to assign a value of type bool to one of type myBool. +			val = val.Convert(t) +		} +		return val, err +	} + +	val := reflect.New(t).Elem() +	err := vd.DecodeValue(dc, vr, val) +	return val, err +} + +// CodecZeroer is the interface implemented by Codecs that can also determine if +// a value of the type that would be encoded is zero. +type CodecZeroer interface { +	IsTypeZero(interface{}) bool +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go new file mode 100644 index 000000000..5a916cc15 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go @@ -0,0 +1,111 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"fmt" +	"reflect" + +	"go.mongodb.org/mongo-driver/bson/bsonoptions" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +// ByteSliceCodec is the Codec used for []byte values. +type ByteSliceCodec struct { +	EncodeNilAsEmpty bool +} + +var ( +	defaultByteSliceCodec = NewByteSliceCodec() + +	_ ValueCodec  = defaultByteSliceCodec +	_ typeDecoder = defaultByteSliceCodec +) + +// NewByteSliceCodec returns a StringCodec with options opts. +func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec { +	byteSliceOpt := bsonoptions.MergeByteSliceCodecOptions(opts...) +	codec := ByteSliceCodec{} +	if byteSliceOpt.EncodeNilAsEmpty != nil { +		codec.EncodeNilAsEmpty = *byteSliceOpt.EncodeNilAsEmpty +	} +	return &codec +} + +// EncodeValue is the ValueEncoder for []byte. +func (bsc *ByteSliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tByteSlice { +		return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val} +	} +	if val.IsNil() && !bsc.EncodeNilAsEmpty { +		return vw.WriteNull() +	} +	return vw.WriteBinary(val.Interface().([]byte)) +} + +func (bsc *ByteSliceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tByteSlice { +		return emptyValue, ValueDecoderError{ +			Name:     "ByteSliceDecodeValue", +			Types:    []reflect.Type{tByteSlice}, +			Received: reflect.Zero(t), +		} +	} + +	var data []byte +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.String: +		str, err := vr.ReadString() +		if err != nil { +			return emptyValue, err +		} +		data = []byte(str) +	case bsontype.Symbol: +		sym, err := vr.ReadSymbol() +		if err != nil { +			return emptyValue, err +		} +		data = []byte(sym) +	case bsontype.Binary: +		var subtype byte +		data, subtype, err = vr.ReadBinary() +		if err != nil { +			return emptyValue, err +		} +		if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { +			return emptyValue, decodeBinaryError{subtype: subtype, typeName: "[]byte"} +		} +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a []byte", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(data), nil +} + +// DecodeValue is the ValueDecoder for []byte. +func (bsc *ByteSliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tByteSlice { +		return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val} +	} + +	elem, err := bsc.decodeType(dc, vr, tByteSlice) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go new file mode 100644 index 000000000..cb8180f25 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/cond_addr_codec.go @@ -0,0 +1,63 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"reflect" + +	"go.mongodb.org/mongo-driver/bson/bsonrw" +) + +// condAddrEncoder is the encoder used when a pointer to the encoding value has an encoder. +type condAddrEncoder struct { +	canAddrEnc ValueEncoder +	elseEnc    ValueEncoder +} + +var _ ValueEncoder = (*condAddrEncoder)(nil) + +// newCondAddrEncoder returns an condAddrEncoder. +func newCondAddrEncoder(canAddrEnc, elseEnc ValueEncoder) *condAddrEncoder { +	encoder := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc} +	return &encoder +} + +// EncodeValue is the ValueEncoderFunc for a value that may be addressable. +func (cae *condAddrEncoder) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if val.CanAddr() { +		return cae.canAddrEnc.EncodeValue(ec, vw, val) +	} +	if cae.elseEnc != nil { +		return cae.elseEnc.EncodeValue(ec, vw, val) +	} +	return ErrNoEncoder{Type: val.Type()} +} + +// condAddrDecoder is the decoder used when a pointer to the value has a decoder. +type condAddrDecoder struct { +	canAddrDec ValueDecoder +	elseDec    ValueDecoder +} + +var _ ValueDecoder = (*condAddrDecoder)(nil) + +// newCondAddrDecoder returns an CondAddrDecoder. +func newCondAddrDecoder(canAddrDec, elseDec ValueDecoder) *condAddrDecoder { +	decoder := condAddrDecoder{canAddrDec: canAddrDec, elseDec: elseDec} +	return &decoder +} + +// DecodeValue is the ValueDecoderFunc for a value that may be addressable. +func (cad *condAddrDecoder) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if val.CanAddr() { +		return cad.canAddrDec.DecodeValue(dc, vr, val) +	} +	if cad.elseDec != nil { +		return cad.elseDec.DecodeValue(dc, vr, val) +	} +	return ErrNoDecoder{Type: val.Type()} +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go new file mode 100644 index 000000000..e95cab585 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go @@ -0,0 +1,1729 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"encoding/json" +	"errors" +	"fmt" +	"math" +	"net/url" +	"reflect" +	"strconv" +	"time" + +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +var ( +	defaultValueDecoders DefaultValueDecoders +	errCannotTruncate    = errors.New("float64 can only be truncated to an integer type when truncation is enabled") +) + +type decodeBinaryError struct { +	subtype  byte +	typeName string +} + +func (d decodeBinaryError) Error() string { +	return fmt.Sprintf("only binary values with subtype 0x00 or 0x02 can be decoded into %s, but got subtype %v", d.typeName, d.subtype) +} + +func newDefaultStructCodec() *StructCodec { +	codec, err := NewStructCodec(DefaultStructTagParser) +	if err != nil { +		// This function is called from the codec registration path, so errors can't be propagated. If there's an error +		// constructing the StructCodec, we panic to avoid losing it. +		panic(fmt.Errorf("error creating default StructCodec: %v", err)) +	} +	return codec +} + +// DefaultValueDecoders is a namespace type for the default ValueDecoders used +// when creating a registry. +type DefaultValueDecoders struct{} + +// RegisterDefaultDecoders will register the decoder methods attached to DefaultValueDecoders with +// the provided RegistryBuilder. +// +// There is no support for decoding map[string]interface{} because there is no decoder for +// interface{}, so users must either register this decoder themselves or use the +// EmptyInterfaceDecoder available in the bson package. +func (dvd DefaultValueDecoders) RegisterDefaultDecoders(rb *RegistryBuilder) { +	if rb == nil { +		panic(errors.New("argument to RegisterDefaultDecoders must not be nil")) +	} + +	intDecoder := decodeAdapter{dvd.IntDecodeValue, dvd.intDecodeType} +	floatDecoder := decodeAdapter{dvd.FloatDecodeValue, dvd.floatDecodeType} + +	rb. +		RegisterTypeDecoder(tD, ValueDecoderFunc(dvd.DDecodeValue)). +		RegisterTypeDecoder(tBinary, decodeAdapter{dvd.BinaryDecodeValue, dvd.binaryDecodeType}). +		RegisterTypeDecoder(tUndefined, decodeAdapter{dvd.UndefinedDecodeValue, dvd.undefinedDecodeType}). +		RegisterTypeDecoder(tDateTime, decodeAdapter{dvd.DateTimeDecodeValue, dvd.dateTimeDecodeType}). +		RegisterTypeDecoder(tNull, decodeAdapter{dvd.NullDecodeValue, dvd.nullDecodeType}). +		RegisterTypeDecoder(tRegex, decodeAdapter{dvd.RegexDecodeValue, dvd.regexDecodeType}). +		RegisterTypeDecoder(tDBPointer, decodeAdapter{dvd.DBPointerDecodeValue, dvd.dBPointerDecodeType}). +		RegisterTypeDecoder(tTimestamp, decodeAdapter{dvd.TimestampDecodeValue, dvd.timestampDecodeType}). +		RegisterTypeDecoder(tMinKey, decodeAdapter{dvd.MinKeyDecodeValue, dvd.minKeyDecodeType}). +		RegisterTypeDecoder(tMaxKey, decodeAdapter{dvd.MaxKeyDecodeValue, dvd.maxKeyDecodeType}). +		RegisterTypeDecoder(tJavaScript, decodeAdapter{dvd.JavaScriptDecodeValue, dvd.javaScriptDecodeType}). +		RegisterTypeDecoder(tSymbol, decodeAdapter{dvd.SymbolDecodeValue, dvd.symbolDecodeType}). +		RegisterTypeDecoder(tByteSlice, defaultByteSliceCodec). +		RegisterTypeDecoder(tTime, defaultTimeCodec). +		RegisterTypeDecoder(tEmpty, defaultEmptyInterfaceCodec). +		RegisterTypeDecoder(tCoreArray, defaultArrayCodec). +		RegisterTypeDecoder(tOID, decodeAdapter{dvd.ObjectIDDecodeValue, dvd.objectIDDecodeType}). +		RegisterTypeDecoder(tDecimal, decodeAdapter{dvd.Decimal128DecodeValue, dvd.decimal128DecodeType}). +		RegisterTypeDecoder(tJSONNumber, decodeAdapter{dvd.JSONNumberDecodeValue, dvd.jsonNumberDecodeType}). +		RegisterTypeDecoder(tURL, decodeAdapter{dvd.URLDecodeValue, dvd.urlDecodeType}). +		RegisterTypeDecoder(tCoreDocument, ValueDecoderFunc(dvd.CoreDocumentDecodeValue)). +		RegisterTypeDecoder(tCodeWithScope, decodeAdapter{dvd.CodeWithScopeDecodeValue, dvd.codeWithScopeDecodeType}). +		RegisterDefaultDecoder(reflect.Bool, decodeAdapter{dvd.BooleanDecodeValue, dvd.booleanDecodeType}). +		RegisterDefaultDecoder(reflect.Int, intDecoder). +		RegisterDefaultDecoder(reflect.Int8, intDecoder). +		RegisterDefaultDecoder(reflect.Int16, intDecoder). +		RegisterDefaultDecoder(reflect.Int32, intDecoder). +		RegisterDefaultDecoder(reflect.Int64, intDecoder). +		RegisterDefaultDecoder(reflect.Uint, defaultUIntCodec). +		RegisterDefaultDecoder(reflect.Uint8, defaultUIntCodec). +		RegisterDefaultDecoder(reflect.Uint16, defaultUIntCodec). +		RegisterDefaultDecoder(reflect.Uint32, defaultUIntCodec). +		RegisterDefaultDecoder(reflect.Uint64, defaultUIntCodec). +		RegisterDefaultDecoder(reflect.Float32, floatDecoder). +		RegisterDefaultDecoder(reflect.Float64, floatDecoder). +		RegisterDefaultDecoder(reflect.Array, ValueDecoderFunc(dvd.ArrayDecodeValue)). +		RegisterDefaultDecoder(reflect.Map, defaultMapCodec). +		RegisterDefaultDecoder(reflect.Slice, defaultSliceCodec). +		RegisterDefaultDecoder(reflect.String, defaultStringCodec). +		RegisterDefaultDecoder(reflect.Struct, newDefaultStructCodec()). +		RegisterDefaultDecoder(reflect.Ptr, NewPointerCodec()). +		RegisterTypeMapEntry(bsontype.Double, tFloat64). +		RegisterTypeMapEntry(bsontype.String, tString). +		RegisterTypeMapEntry(bsontype.Array, tA). +		RegisterTypeMapEntry(bsontype.Binary, tBinary). +		RegisterTypeMapEntry(bsontype.Undefined, tUndefined). +		RegisterTypeMapEntry(bsontype.ObjectID, tOID). +		RegisterTypeMapEntry(bsontype.Boolean, tBool). +		RegisterTypeMapEntry(bsontype.DateTime, tDateTime). +		RegisterTypeMapEntry(bsontype.Regex, tRegex). +		RegisterTypeMapEntry(bsontype.DBPointer, tDBPointer). +		RegisterTypeMapEntry(bsontype.JavaScript, tJavaScript). +		RegisterTypeMapEntry(bsontype.Symbol, tSymbol). +		RegisterTypeMapEntry(bsontype.CodeWithScope, tCodeWithScope). +		RegisterTypeMapEntry(bsontype.Int32, tInt32). +		RegisterTypeMapEntry(bsontype.Int64, tInt64). +		RegisterTypeMapEntry(bsontype.Timestamp, tTimestamp). +		RegisterTypeMapEntry(bsontype.Decimal128, tDecimal). +		RegisterTypeMapEntry(bsontype.MinKey, tMinKey). +		RegisterTypeMapEntry(bsontype.MaxKey, tMaxKey). +		RegisterTypeMapEntry(bsontype.Type(0), tD). +		RegisterTypeMapEntry(bsontype.EmbeddedDocument, tD). +		RegisterHookDecoder(tValueUnmarshaler, ValueDecoderFunc(dvd.ValueUnmarshalerDecodeValue)). +		RegisterHookDecoder(tUnmarshaler, ValueDecoderFunc(dvd.UnmarshalerDecodeValue)) +} + +// DDecodeValue is the ValueDecoderFunc for primitive.D instances. +func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.IsValid() || !val.CanSet() || val.Type() != tD { +		return ValueDecoderError{Name: "DDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} +	} + +	switch vrType := vr.Type(); vrType { +	case bsontype.Type(0), bsontype.EmbeddedDocument: +		dc.Ancestor = tD +	case bsontype.Null: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadNull() +	default: +		return fmt.Errorf("cannot decode %v into a primitive.D", vrType) +	} + +	dr, err := vr.ReadDocument() +	if err != nil { +		return err +	} + +	decoder, err := dc.LookupDecoder(tEmpty) +	if err != nil { +		return err +	} +	tEmptyTypeDecoder, _ := decoder.(typeDecoder) + +	// Use the elements in the provided value if it's non nil. Otherwise, allocate a new D instance. +	var elems primitive.D +	if !val.IsNil() { +		val.SetLen(0) +		elems = val.Interface().(primitive.D) +	} else { +		elems = make(primitive.D, 0) +	} + +	for { +		key, elemVr, err := dr.ReadElement() +		if err == bsonrw.ErrEOD { +			break +		} else if err != nil { +			return err +		} + +		// Pass false for convert because we don't need to call reflect.Value.Convert for tEmpty. +		elem, err := decodeTypeOrValueWithInfo(decoder, tEmptyTypeDecoder, dc, elemVr, tEmpty, false) +		if err != nil { +			return err +		} + +		elems = append(elems, primitive.E{Key: key, Value: elem.Interface()}) +	} + +	val.Set(reflect.ValueOf(elems)) +	return nil +} + +func (dvd DefaultValueDecoders) booleanDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t.Kind() != reflect.Bool { +		return emptyValue, ValueDecoderError{ +			Name:     "BooleanDecodeValue", +			Kinds:    []reflect.Kind{reflect.Bool}, +			Received: reflect.Zero(t), +		} +	} + +	var b bool +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Int32: +		i32, err := vr.ReadInt32() +		if err != nil { +			return emptyValue, err +		} +		b = (i32 != 0) +	case bsontype.Int64: +		i64, err := vr.ReadInt64() +		if err != nil { +			return emptyValue, err +		} +		b = (i64 != 0) +	case bsontype.Double: +		f64, err := vr.ReadDouble() +		if err != nil { +			return emptyValue, err +		} +		b = (f64 != 0) +	case bsontype.Boolean: +		b, err = vr.ReadBoolean() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a boolean", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(b), nil +} + +// BooleanDecodeValue is the ValueDecoderFunc for bool types. +func (dvd DefaultValueDecoders) BooleanDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.IsValid() || !val.CanSet() || val.Kind() != reflect.Bool { +		return ValueDecoderError{Name: "BooleanDecodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val} +	} + +	elem, err := dvd.booleanDecodeType(dctx, vr, val.Type()) +	if err != nil { +		return err +	} + +	val.SetBool(elem.Bool()) +	return nil +} + +func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	var i64 int64 +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Int32: +		i32, err := vr.ReadInt32() +		if err != nil { +			return emptyValue, err +		} +		i64 = int64(i32) +	case bsontype.Int64: +		i64, err = vr.ReadInt64() +		if err != nil { +			return emptyValue, err +		} +	case bsontype.Double: +		f64, err := vr.ReadDouble() +		if err != nil { +			return emptyValue, err +		} +		if !dc.Truncate && math.Floor(f64) != f64 { +			return emptyValue, errCannotTruncate +		} +		if f64 > float64(math.MaxInt64) { +			return emptyValue, fmt.Errorf("%g overflows int64", f64) +		} +		i64 = int64(f64) +	case bsontype.Boolean: +		b, err := vr.ReadBoolean() +		if err != nil { +			return emptyValue, err +		} +		if b { +			i64 = 1 +		} +	case bsontype.Null: +		if err = vr.ReadNull(); err != nil { +			return emptyValue, err +		} +	case bsontype.Undefined: +		if err = vr.ReadUndefined(); err != nil { +			return emptyValue, err +		} +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType) +	} + +	switch t.Kind() { +	case reflect.Int8: +		if i64 < math.MinInt8 || i64 > math.MaxInt8 { +			return emptyValue, fmt.Errorf("%d overflows int8", i64) +		} + +		return reflect.ValueOf(int8(i64)), nil +	case reflect.Int16: +		if i64 < math.MinInt16 || i64 > math.MaxInt16 { +			return emptyValue, fmt.Errorf("%d overflows int16", i64) +		} + +		return reflect.ValueOf(int16(i64)), nil +	case reflect.Int32: +		if i64 < math.MinInt32 || i64 > math.MaxInt32 { +			return emptyValue, fmt.Errorf("%d overflows int32", i64) +		} + +		return reflect.ValueOf(int32(i64)), nil +	case reflect.Int64: +		return reflect.ValueOf(i64), nil +	case reflect.Int: +		if int64(int(i64)) != i64 { // Can we fit this inside of an int +			return emptyValue, fmt.Errorf("%d overflows int", i64) +		} + +		return reflect.ValueOf(int(i64)), nil +	default: +		return emptyValue, ValueDecoderError{ +			Name:     "IntDecodeValue", +			Kinds:    []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int}, +			Received: reflect.Zero(t), +		} +	} +} + +// IntDecodeValue is the ValueDecoderFunc for int types. +func (dvd DefaultValueDecoders) IntDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() { +		return ValueDecoderError{ +			Name:     "IntDecodeValue", +			Kinds:    []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int}, +			Received: val, +		} +	} + +	elem, err := dvd.intDecodeType(dc, vr, val.Type()) +	if err != nil { +		return err +	} + +	val.SetInt(elem.Int()) +	return nil +} + +// UintDecodeValue is the ValueDecoderFunc for uint types. +// +// Deprecated: UintDecodeValue is not registered by default. Use UintCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) UintDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	var i64 int64 +	var err error +	switch vr.Type() { +	case bsontype.Int32: +		i32, err := vr.ReadInt32() +		if err != nil { +			return err +		} +		i64 = int64(i32) +	case bsontype.Int64: +		i64, err = vr.ReadInt64() +		if err != nil { +			return err +		} +	case bsontype.Double: +		f64, err := vr.ReadDouble() +		if err != nil { +			return err +		} +		if !dc.Truncate && math.Floor(f64) != f64 { +			return errors.New("UintDecodeValue can only truncate float64 to an integer type when truncation is enabled") +		} +		if f64 > float64(math.MaxInt64) { +			return fmt.Errorf("%g overflows int64", f64) +		} +		i64 = int64(f64) +	case bsontype.Boolean: +		b, err := vr.ReadBoolean() +		if err != nil { +			return err +		} +		if b { +			i64 = 1 +		} +	default: +		return fmt.Errorf("cannot decode %v into an integer type", vr.Type()) +	} + +	if !val.CanSet() { +		return ValueDecoderError{ +			Name:     "UintDecodeValue", +			Kinds:    []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, +			Received: val, +		} +	} + +	switch val.Kind() { +	case reflect.Uint8: +		if i64 < 0 || i64 > math.MaxUint8 { +			return fmt.Errorf("%d overflows uint8", i64) +		} +	case reflect.Uint16: +		if i64 < 0 || i64 > math.MaxUint16 { +			return fmt.Errorf("%d overflows uint16", i64) +		} +	case reflect.Uint32: +		if i64 < 0 || i64 > math.MaxUint32 { +			return fmt.Errorf("%d overflows uint32", i64) +		} +	case reflect.Uint64: +		if i64 < 0 { +			return fmt.Errorf("%d overflows uint64", i64) +		} +	case reflect.Uint: +		if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint +			return fmt.Errorf("%d overflows uint", i64) +		} +	default: +		return ValueDecoderError{ +			Name:     "UintDecodeValue", +			Kinds:    []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, +			Received: val, +		} +	} + +	val.SetUint(uint64(i64)) +	return nil +} + +func (dvd DefaultValueDecoders) floatDecodeType(ec DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	var f float64 +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Int32: +		i32, err := vr.ReadInt32() +		if err != nil { +			return emptyValue, err +		} +		f = float64(i32) +	case bsontype.Int64: +		i64, err := vr.ReadInt64() +		if err != nil { +			return emptyValue, err +		} +		f = float64(i64) +	case bsontype.Double: +		f, err = vr.ReadDouble() +		if err != nil { +			return emptyValue, err +		} +	case bsontype.Boolean: +		b, err := vr.ReadBoolean() +		if err != nil { +			return emptyValue, err +		} +		if b { +			f = 1 +		} +	case bsontype.Null: +		if err = vr.ReadNull(); err != nil { +			return emptyValue, err +		} +	case bsontype.Undefined: +		if err = vr.ReadUndefined(); err != nil { +			return emptyValue, err +		} +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a float32 or float64 type", vrType) +	} + +	switch t.Kind() { +	case reflect.Float32: +		if !ec.Truncate && float64(float32(f)) != f { +			return emptyValue, errCannotTruncate +		} + +		return reflect.ValueOf(float32(f)), nil +	case reflect.Float64: +		return reflect.ValueOf(f), nil +	default: +		return emptyValue, ValueDecoderError{ +			Name:     "FloatDecodeValue", +			Kinds:    []reflect.Kind{reflect.Float32, reflect.Float64}, +			Received: reflect.Zero(t), +		} +	} +} + +// FloatDecodeValue is the ValueDecoderFunc for float types. +func (dvd DefaultValueDecoders) FloatDecodeValue(ec DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() { +		return ValueDecoderError{ +			Name:     "FloatDecodeValue", +			Kinds:    []reflect.Kind{reflect.Float32, reflect.Float64}, +			Received: val, +		} +	} + +	elem, err := dvd.floatDecodeType(ec, vr, val.Type()) +	if err != nil { +		return err +	} + +	val.SetFloat(elem.Float()) +	return nil +} + +// StringDecodeValue is the ValueDecoderFunc for string types. +// +// Deprecated: StringDecodeValue is not registered by default. Use StringCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) StringDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	var str string +	var err error +	switch vr.Type() { +	// TODO(GODRIVER-577): Handle JavaScript and Symbol BSON types when allowed. +	case bsontype.String: +		str, err = vr.ReadString() +		if err != nil { +			return err +		} +	default: +		return fmt.Errorf("cannot decode %v into a string type", vr.Type()) +	} +	if !val.CanSet() || val.Kind() != reflect.String { +		return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val} +	} + +	val.SetString(str) +	return nil +} + +func (DefaultValueDecoders) javaScriptDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tJavaScript { +		return emptyValue, ValueDecoderError{ +			Name:     "JavaScriptDecodeValue", +			Types:    []reflect.Type{tJavaScript}, +			Received: reflect.Zero(t), +		} +	} + +	var js string +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.JavaScript: +		js, err = vr.ReadJavascript() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a primitive.JavaScript", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.JavaScript(js)), nil +} + +// JavaScriptDecodeValue is the ValueDecoderFunc for the primitive.JavaScript type. +func (dvd DefaultValueDecoders) JavaScriptDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tJavaScript { +		return ValueDecoderError{Name: "JavaScriptDecodeValue", Types: []reflect.Type{tJavaScript}, Received: val} +	} + +	elem, err := dvd.javaScriptDecodeType(dctx, vr, tJavaScript) +	if err != nil { +		return err +	} + +	val.SetString(elem.String()) +	return nil +} + +func (DefaultValueDecoders) symbolDecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tSymbol { +		return emptyValue, ValueDecoderError{ +			Name:     "SymbolDecodeValue", +			Types:    []reflect.Type{tSymbol}, +			Received: reflect.Zero(t), +		} +	} + +	var symbol string +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.String: +		symbol, err = vr.ReadString() +	case bsontype.Symbol: +		symbol, err = vr.ReadSymbol() +	case bsontype.Binary: +		data, subtype, err := vr.ReadBinary() +		if err != nil { +			return emptyValue, err +		} + +		if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { +			return emptyValue, decodeBinaryError{subtype: subtype, typeName: "primitive.Symbol"} +		} +		symbol = string(data) +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a primitive.Symbol", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.Symbol(symbol)), nil +} + +// SymbolDecodeValue is the ValueDecoderFunc for the primitive.Symbol type. +func (dvd DefaultValueDecoders) SymbolDecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tSymbol { +		return ValueDecoderError{Name: "SymbolDecodeValue", Types: []reflect.Type{tSymbol}, Received: val} +	} + +	elem, err := dvd.symbolDecodeType(dctx, vr, tSymbol) +	if err != nil { +		return err +	} + +	val.SetString(elem.String()) +	return nil +} + +func (DefaultValueDecoders) binaryDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tBinary { +		return emptyValue, ValueDecoderError{ +			Name:     "BinaryDecodeValue", +			Types:    []reflect.Type{tBinary}, +			Received: reflect.Zero(t), +		} +	} + +	var data []byte +	var subtype byte +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Binary: +		data, subtype, err = vr.ReadBinary() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a Binary", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.Binary{Subtype: subtype, Data: data}), nil +} + +// BinaryDecodeValue is the ValueDecoderFunc for Binary. +func (dvd DefaultValueDecoders) BinaryDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tBinary { +		return ValueDecoderError{Name: "BinaryDecodeValue", Types: []reflect.Type{tBinary}, Received: val} +	} + +	elem, err := dvd.binaryDecodeType(dc, vr, tBinary) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (DefaultValueDecoders) undefinedDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tUndefined { +		return emptyValue, ValueDecoderError{ +			Name:     "UndefinedDecodeValue", +			Types:    []reflect.Type{tUndefined}, +			Received: reflect.Zero(t), +		} +	} + +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	case bsontype.Null: +		err = vr.ReadNull() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into an Undefined", vr.Type()) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.Undefined{}), nil +} + +// UndefinedDecodeValue is the ValueDecoderFunc for Undefined. +func (dvd DefaultValueDecoders) UndefinedDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tUndefined { +		return ValueDecoderError{Name: "UndefinedDecodeValue", Types: []reflect.Type{tUndefined}, Received: val} +	} + +	elem, err := dvd.undefinedDecodeType(dc, vr, tUndefined) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +// Accept both 12-byte string and pretty-printed 24-byte hex string formats. +func (dvd DefaultValueDecoders) objectIDDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tOID { +		return emptyValue, ValueDecoderError{ +			Name:     "ObjectIDDecodeValue", +			Types:    []reflect.Type{tOID}, +			Received: reflect.Zero(t), +		} +	} + +	var oid primitive.ObjectID +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.ObjectID: +		oid, err = vr.ReadObjectID() +		if err != nil { +			return emptyValue, err +		} +	case bsontype.String: +		str, err := vr.ReadString() +		if err != nil { +			return emptyValue, err +		} +		if oid, err = primitive.ObjectIDFromHex(str); err == nil { +			break +		} +		if len(str) != 12 { +			return emptyValue, fmt.Errorf("an ObjectID string must be exactly 12 bytes long (got %v)", len(str)) +		} +		byteArr := []byte(str) +		copy(oid[:], byteArr) +	case bsontype.Null: +		if err = vr.ReadNull(); err != nil { +			return emptyValue, err +		} +	case bsontype.Undefined: +		if err = vr.ReadUndefined(); err != nil { +			return emptyValue, err +		} +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into an ObjectID", vrType) +	} + +	return reflect.ValueOf(oid), nil +} + +// ObjectIDDecodeValue is the ValueDecoderFunc for primitive.ObjectID. +func (dvd DefaultValueDecoders) ObjectIDDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tOID { +		return ValueDecoderError{Name: "ObjectIDDecodeValue", Types: []reflect.Type{tOID}, Received: val} +	} + +	elem, err := dvd.objectIDDecodeType(dc, vr, tOID) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (DefaultValueDecoders) dateTimeDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tDateTime { +		return emptyValue, ValueDecoderError{ +			Name:     "DateTimeDecodeValue", +			Types:    []reflect.Type{tDateTime}, +			Received: reflect.Zero(t), +		} +	} + +	var dt int64 +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.DateTime: +		dt, err = vr.ReadDateTime() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a DateTime", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.DateTime(dt)), nil +} + +// DateTimeDecodeValue is the ValueDecoderFunc for DateTime. +func (dvd DefaultValueDecoders) DateTimeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tDateTime { +		return ValueDecoderError{Name: "DateTimeDecodeValue", Types: []reflect.Type{tDateTime}, Received: val} +	} + +	elem, err := dvd.dateTimeDecodeType(dc, vr, tDateTime) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (DefaultValueDecoders) nullDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tNull { +		return emptyValue, ValueDecoderError{ +			Name:     "NullDecodeValue", +			Types:    []reflect.Type{tNull}, +			Received: reflect.Zero(t), +		} +	} + +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	case bsontype.Null: +		err = vr.ReadNull() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a Null", vr.Type()) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.Null{}), nil +} + +// NullDecodeValue is the ValueDecoderFunc for Null. +func (dvd DefaultValueDecoders) NullDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tNull { +		return ValueDecoderError{Name: "NullDecodeValue", Types: []reflect.Type{tNull}, Received: val} +	} + +	elem, err := dvd.nullDecodeType(dc, vr, tNull) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (DefaultValueDecoders) regexDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tRegex { +		return emptyValue, ValueDecoderError{ +			Name:     "RegexDecodeValue", +			Types:    []reflect.Type{tRegex}, +			Received: reflect.Zero(t), +		} +	} + +	var pattern, options string +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Regex: +		pattern, options, err = vr.ReadRegex() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a Regex", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.Regex{Pattern: pattern, Options: options}), nil +} + +// RegexDecodeValue is the ValueDecoderFunc for Regex. +func (dvd DefaultValueDecoders) RegexDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tRegex { +		return ValueDecoderError{Name: "RegexDecodeValue", Types: []reflect.Type{tRegex}, Received: val} +	} + +	elem, err := dvd.regexDecodeType(dc, vr, tRegex) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (DefaultValueDecoders) dBPointerDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tDBPointer { +		return emptyValue, ValueDecoderError{ +			Name:     "DBPointerDecodeValue", +			Types:    []reflect.Type{tDBPointer}, +			Received: reflect.Zero(t), +		} +	} + +	var ns string +	var pointer primitive.ObjectID +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.DBPointer: +		ns, pointer, err = vr.ReadDBPointer() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a DBPointer", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.DBPointer{DB: ns, Pointer: pointer}), nil +} + +// DBPointerDecodeValue is the ValueDecoderFunc for DBPointer. +func (dvd DefaultValueDecoders) DBPointerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tDBPointer { +		return ValueDecoderError{Name: "DBPointerDecodeValue", Types: []reflect.Type{tDBPointer}, Received: val} +	} + +	elem, err := dvd.dBPointerDecodeType(dc, vr, tDBPointer) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (DefaultValueDecoders) timestampDecodeType(dc DecodeContext, vr bsonrw.ValueReader, reflectType reflect.Type) (reflect.Value, error) { +	if reflectType != tTimestamp { +		return emptyValue, ValueDecoderError{ +			Name:     "TimestampDecodeValue", +			Types:    []reflect.Type{tTimestamp}, +			Received: reflect.Zero(reflectType), +		} +	} + +	var t, incr uint32 +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Timestamp: +		t, incr, err = vr.ReadTimestamp() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a Timestamp", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.Timestamp{T: t, I: incr}), nil +} + +// TimestampDecodeValue is the ValueDecoderFunc for Timestamp. +func (dvd DefaultValueDecoders) TimestampDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tTimestamp { +		return ValueDecoderError{Name: "TimestampDecodeValue", Types: []reflect.Type{tTimestamp}, Received: val} +	} + +	elem, err := dvd.timestampDecodeType(dc, vr, tTimestamp) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (DefaultValueDecoders) minKeyDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tMinKey { +		return emptyValue, ValueDecoderError{ +			Name:     "MinKeyDecodeValue", +			Types:    []reflect.Type{tMinKey}, +			Received: reflect.Zero(t), +		} +	} + +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.MinKey: +		err = vr.ReadMinKey() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a MinKey", vr.Type()) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.MinKey{}), nil +} + +// MinKeyDecodeValue is the ValueDecoderFunc for MinKey. +func (dvd DefaultValueDecoders) MinKeyDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tMinKey { +		return ValueDecoderError{Name: "MinKeyDecodeValue", Types: []reflect.Type{tMinKey}, Received: val} +	} + +	elem, err := dvd.minKeyDecodeType(dc, vr, tMinKey) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (DefaultValueDecoders) maxKeyDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tMaxKey { +		return emptyValue, ValueDecoderError{ +			Name:     "MaxKeyDecodeValue", +			Types:    []reflect.Type{tMaxKey}, +			Received: reflect.Zero(t), +		} +	} + +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.MaxKey: +		err = vr.ReadMaxKey() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a MaxKey", vr.Type()) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(primitive.MaxKey{}), nil +} + +// MaxKeyDecodeValue is the ValueDecoderFunc for MaxKey. +func (dvd DefaultValueDecoders) MaxKeyDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tMaxKey { +		return ValueDecoderError{Name: "MaxKeyDecodeValue", Types: []reflect.Type{tMaxKey}, Received: val} +	} + +	elem, err := dvd.maxKeyDecodeType(dc, vr, tMaxKey) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (dvd DefaultValueDecoders) decimal128DecodeType(dctx DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tDecimal { +		return emptyValue, ValueDecoderError{ +			Name:     "Decimal128DecodeValue", +			Types:    []reflect.Type{tDecimal}, +			Received: reflect.Zero(t), +		} +	} + +	var d128 primitive.Decimal128 +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Decimal128: +		d128, err = vr.ReadDecimal128() +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a primitive.Decimal128", vr.Type()) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(d128), nil +} + +// Decimal128DecodeValue is the ValueDecoderFunc for primitive.Decimal128. +func (dvd DefaultValueDecoders) Decimal128DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tDecimal { +		return ValueDecoderError{Name: "Decimal128DecodeValue", Types: []reflect.Type{tDecimal}, Received: val} +	} + +	elem, err := dvd.decimal128DecodeType(dctx, vr, tDecimal) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (dvd DefaultValueDecoders) jsonNumberDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tJSONNumber { +		return emptyValue, ValueDecoderError{ +			Name:     "JSONNumberDecodeValue", +			Types:    []reflect.Type{tJSONNumber}, +			Received: reflect.Zero(t), +		} +	} + +	var jsonNum json.Number +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Double: +		f64, err := vr.ReadDouble() +		if err != nil { +			return emptyValue, err +		} +		jsonNum = json.Number(strconv.FormatFloat(f64, 'f', -1, 64)) +	case bsontype.Int32: +		i32, err := vr.ReadInt32() +		if err != nil { +			return emptyValue, err +		} +		jsonNum = json.Number(strconv.FormatInt(int64(i32), 10)) +	case bsontype.Int64: +		i64, err := vr.ReadInt64() +		if err != nil { +			return emptyValue, err +		} +		jsonNum = json.Number(strconv.FormatInt(i64, 10)) +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a json.Number", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(jsonNum), nil +} + +// JSONNumberDecodeValue is the ValueDecoderFunc for json.Number. +func (dvd DefaultValueDecoders) JSONNumberDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tJSONNumber { +		return ValueDecoderError{Name: "JSONNumberDecodeValue", Types: []reflect.Type{tJSONNumber}, Received: val} +	} + +	elem, err := dvd.jsonNumberDecodeType(dc, vr, tJSONNumber) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (dvd DefaultValueDecoders) urlDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tURL { +		return emptyValue, ValueDecoderError{ +			Name:     "URLDecodeValue", +			Types:    []reflect.Type{tURL}, +			Received: reflect.Zero(t), +		} +	} + +	urlPtr := &url.URL{} +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.String: +		var str string // Declare str here to avoid shadowing err during the ReadString call. +		str, err = vr.ReadString() +		if err != nil { +			return emptyValue, err +		} + +		urlPtr, err = url.Parse(str) +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a *url.URL", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(urlPtr).Elem(), nil +} + +// URLDecodeValue is the ValueDecoderFunc for url.URL. +func (dvd DefaultValueDecoders) URLDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tURL { +		return ValueDecoderError{Name: "URLDecodeValue", Types: []reflect.Type{tURL}, Received: val} +	} + +	elem, err := dvd.urlDecodeType(dc, vr, tURL) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +// TimeDecodeValue is the ValueDecoderFunc for time.Time. +// +// Deprecated: TimeDecodeValue is not registered by default. Use TimeCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) TimeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if vr.Type() != bsontype.DateTime { +		return fmt.Errorf("cannot decode %v into a time.Time", vr.Type()) +	} + +	dt, err := vr.ReadDateTime() +	if err != nil { +		return err +	} + +	if !val.CanSet() || val.Type() != tTime { +		return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val} +	} + +	val.Set(reflect.ValueOf(time.Unix(dt/1000, dt%1000*1000000).UTC())) +	return nil +} + +// ByteSliceDecodeValue is the ValueDecoderFunc for []byte. +// +// Deprecated: ByteSliceDecodeValue is not registered by default. Use ByteSliceCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) ByteSliceDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if vr.Type() != bsontype.Binary && vr.Type() != bsontype.Null { +		return fmt.Errorf("cannot decode %v into a []byte", vr.Type()) +	} + +	if !val.CanSet() || val.Type() != tByteSlice { +		return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val} +	} + +	if vr.Type() == bsontype.Null { +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadNull() +	} + +	data, subtype, err := vr.ReadBinary() +	if err != nil { +		return err +	} +	if subtype != 0x00 { +		return fmt.Errorf("ByteSliceDecodeValue can only be used to decode subtype 0x00 for %s, got %v", bsontype.Binary, subtype) +	} + +	val.Set(reflect.ValueOf(data)) +	return nil +} + +// MapDecodeValue is the ValueDecoderFunc for map[string]* types. +// +// Deprecated: MapDecodeValue is not registered by default. Use MapCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) MapDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Kind() != reflect.Map || val.Type().Key().Kind() != reflect.String { +		return ValueDecoderError{Name: "MapDecodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} +	} + +	switch vr.Type() { +	case bsontype.Type(0), bsontype.EmbeddedDocument: +	case bsontype.Null: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadNull() +	default: +		return fmt.Errorf("cannot decode %v into a %s", vr.Type(), val.Type()) +	} + +	dr, err := vr.ReadDocument() +	if err != nil { +		return err +	} + +	if val.IsNil() { +		val.Set(reflect.MakeMap(val.Type())) +	} + +	eType := val.Type().Elem() +	decoder, err := dc.LookupDecoder(eType) +	if err != nil { +		return err +	} + +	if eType == tEmpty { +		dc.Ancestor = val.Type() +	} + +	keyType := val.Type().Key() +	for { +		key, vr, err := dr.ReadElement() +		if err == bsonrw.ErrEOD { +			break +		} +		if err != nil { +			return err +		} + +		elem := reflect.New(eType).Elem() + +		err = decoder.DecodeValue(dc, vr, elem) +		if err != nil { +			return err +		} + +		val.SetMapIndex(reflect.ValueOf(key).Convert(keyType), elem) +	} +	return nil +} + +// ArrayDecodeValue is the ValueDecoderFunc for array types. +func (dvd DefaultValueDecoders) ArrayDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.IsValid() || val.Kind() != reflect.Array { +		return ValueDecoderError{Name: "ArrayDecodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val} +	} + +	switch vrType := vr.Type(); vrType { +	case bsontype.Array: +	case bsontype.Type(0), bsontype.EmbeddedDocument: +		if val.Type().Elem() != tE { +			return fmt.Errorf("cannot decode document into %s", val.Type()) +		} +	case bsontype.Binary: +		if val.Type().Elem() != tByte { +			return fmt.Errorf("ArrayDecodeValue can only be used to decode binary into a byte array, got %v", vrType) +		} +		data, subtype, err := vr.ReadBinary() +		if err != nil { +			return err +		} +		if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { +			return fmt.Errorf("ArrayDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype) +		} + +		if len(data) > val.Len() { +			return fmt.Errorf("more elements returned in array than can fit inside %s", val.Type()) +		} + +		for idx, elem := range data { +			val.Index(idx).Set(reflect.ValueOf(elem)) +		} +		return nil +	case bsontype.Null: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadNull() +	case bsontype.Undefined: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadUndefined() +	default: +		return fmt.Errorf("cannot decode %v into an array", vrType) +	} + +	var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error) +	switch val.Type().Elem() { +	case tE: +		elemsFunc = dvd.decodeD +	default: +		elemsFunc = dvd.decodeDefault +	} + +	elems, err := elemsFunc(dc, vr, val) +	if err != nil { +		return err +	} + +	if len(elems) > val.Len() { +		return fmt.Errorf("more elements returned in array than can fit inside %s, got %v elements", val.Type(), len(elems)) +	} + +	for idx, elem := range elems { +		val.Index(idx).Set(elem) +	} + +	return nil +} + +// SliceDecodeValue is the ValueDecoderFunc for slice types. +// +// Deprecated: SliceDecodeValue is not registered by default. Use SliceCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) SliceDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Kind() != reflect.Slice { +		return ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} +	} + +	switch vr.Type() { +	case bsontype.Array: +	case bsontype.Null: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadNull() +	case bsontype.Type(0), bsontype.EmbeddedDocument: +		if val.Type().Elem() != tE { +			return fmt.Errorf("cannot decode document into %s", val.Type()) +		} +	default: +		return fmt.Errorf("cannot decode %v into a slice", vr.Type()) +	} + +	var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error) +	switch val.Type().Elem() { +	case tE: +		dc.Ancestor = val.Type() +		elemsFunc = dvd.decodeD +	default: +		elemsFunc = dvd.decodeDefault +	} + +	elems, err := elemsFunc(dc, vr, val) +	if err != nil { +		return err +	} + +	if val.IsNil() { +		val.Set(reflect.MakeSlice(val.Type(), 0, len(elems))) +	} + +	val.SetLen(0) +	val.Set(reflect.Append(val, elems...)) + +	return nil +} + +// ValueUnmarshalerDecodeValue is the ValueDecoderFunc for ValueUnmarshaler implementations. +func (dvd DefaultValueDecoders) ValueUnmarshalerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.IsValid() || (!val.Type().Implements(tValueUnmarshaler) && !reflect.PtrTo(val.Type()).Implements(tValueUnmarshaler)) { +		return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} +	} + +	if val.Kind() == reflect.Ptr && val.IsNil() { +		if !val.CanSet() { +			return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} +		} +		val.Set(reflect.New(val.Type().Elem())) +	} + +	if !val.Type().Implements(tValueUnmarshaler) { +		if !val.CanAddr() { +			return ValueDecoderError{Name: "ValueUnmarshalerDecodeValue", Types: []reflect.Type{tValueUnmarshaler}, Received: val} +		} +		val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. +	} + +	t, src, err := bsonrw.Copier{}.CopyValueToBytes(vr) +	if err != nil { +		return err +	} + +	fn := val.Convert(tValueUnmarshaler).MethodByName("UnmarshalBSONValue") +	errVal := fn.Call([]reflect.Value{reflect.ValueOf(t), reflect.ValueOf(src)})[0] +	if !errVal.IsNil() { +		return errVal.Interface().(error) +	} +	return nil +} + +// UnmarshalerDecodeValue is the ValueDecoderFunc for Unmarshaler implementations. +func (dvd DefaultValueDecoders) UnmarshalerDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.IsValid() || (!val.Type().Implements(tUnmarshaler) && !reflect.PtrTo(val.Type()).Implements(tUnmarshaler)) { +		return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} +	} + +	if val.Kind() == reflect.Ptr && val.IsNil() { +		if !val.CanSet() { +			return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} +		} +		val.Set(reflect.New(val.Type().Elem())) +	} + +	_, src, err := bsonrw.Copier{}.CopyValueToBytes(vr) +	if err != nil { +		return err +	} + +	// If the target Go value is a pointer and the BSON field value is empty, set the value to the +	// zero value of the pointer (nil) and don't call UnmarshalBSON. UnmarshalBSON has no way to +	// change the pointer value from within the function (only the value at the pointer address), +	// so it can't set the pointer to "nil" itself. Since the most common Go value for an empty BSON +	// field value is "nil", we set "nil" here and don't call UnmarshalBSON. This behavior matches +	// the behavior of the Go "encoding/json" unmarshaler when the target Go value is a pointer and +	// the JSON field value is "null". +	if val.Kind() == reflect.Ptr && len(src) == 0 { +		val.Set(reflect.Zero(val.Type())) +		return nil +	} + +	if !val.Type().Implements(tUnmarshaler) { +		if !val.CanAddr() { +			return ValueDecoderError{Name: "UnmarshalerDecodeValue", Types: []reflect.Type{tUnmarshaler}, Received: val} +		} +		val = val.Addr() // If the type doesn't implement the interface, a pointer to it must. +	} + +	fn := val.Convert(tUnmarshaler).MethodByName("UnmarshalBSON") +	errVal := fn.Call([]reflect.Value{reflect.ValueOf(src)})[0] +	if !errVal.IsNil() { +		return errVal.Interface().(error) +	} +	return nil +} + +// EmptyInterfaceDecodeValue is the ValueDecoderFunc for interface{}. +// +// Deprecated: EmptyInterfaceDecodeValue is not registered by default. Use EmptyInterfaceCodec.DecodeValue instead. +func (dvd DefaultValueDecoders) EmptyInterfaceDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tEmpty { +		return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val} +	} + +	rtype, err := dc.LookupTypeMapEntry(vr.Type()) +	if err != nil { +		switch vr.Type() { +		case bsontype.EmbeddedDocument: +			if dc.Ancestor != nil { +				rtype = dc.Ancestor +				break +			} +			rtype = tD +		case bsontype.Null: +			val.Set(reflect.Zero(val.Type())) +			return vr.ReadNull() +		default: +			return err +		} +	} + +	decoder, err := dc.LookupDecoder(rtype) +	if err != nil { +		return err +	} + +	elem := reflect.New(rtype).Elem() +	err = decoder.DecodeValue(dc, vr, elem) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +// CoreDocumentDecodeValue is the ValueDecoderFunc for bsoncore.Document. +func (DefaultValueDecoders) CoreDocumentDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tCoreDocument { +		return ValueDecoderError{Name: "CoreDocumentDecodeValue", Types: []reflect.Type{tCoreDocument}, Received: val} +	} + +	if val.IsNil() { +		val.Set(reflect.MakeSlice(val.Type(), 0, 0)) +	} + +	val.SetLen(0) + +	cdoc, err := bsonrw.Copier{}.AppendDocumentBytes(val.Interface().(bsoncore.Document), vr) +	val.Set(reflect.ValueOf(cdoc)) +	return err +} + +func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) ([]reflect.Value, error) { +	elems := make([]reflect.Value, 0) + +	ar, err := vr.ReadArray() +	if err != nil { +		return nil, err +	} + +	eType := val.Type().Elem() + +	decoder, err := dc.LookupDecoder(eType) +	if err != nil { +		return nil, err +	} +	eTypeDecoder, _ := decoder.(typeDecoder) + +	idx := 0 +	for { +		vr, err := ar.ReadValue() +		if err == bsonrw.ErrEOA { +			break +		} +		if err != nil { +			return nil, err +		} + +		elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true) +		if err != nil { +			return nil, newDecodeError(strconv.Itoa(idx), err) +		} +		elems = append(elems, elem) +		idx++ +	} + +	return elems, nil +} + +func (dvd DefaultValueDecoders) readCodeWithScope(dc DecodeContext, vr bsonrw.ValueReader) (primitive.CodeWithScope, error) { +	var cws primitive.CodeWithScope + +	code, dr, err := vr.ReadCodeWithScope() +	if err != nil { +		return cws, err +	} + +	scope := reflect.New(tD).Elem() +	elems, err := dvd.decodeElemsFromDocumentReader(dc, dr) +	if err != nil { +		return cws, err +	} + +	scope.Set(reflect.MakeSlice(tD, 0, len(elems))) +	scope.Set(reflect.Append(scope, elems...)) + +	cws = primitive.CodeWithScope{ +		Code:  primitive.JavaScript(code), +		Scope: scope.Interface().(primitive.D), +	} +	return cws, nil +} + +func (dvd DefaultValueDecoders) codeWithScopeDecodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tCodeWithScope { +		return emptyValue, ValueDecoderError{ +			Name:     "CodeWithScopeDecodeValue", +			Types:    []reflect.Type{tCodeWithScope}, +			Received: reflect.Zero(t), +		} +	} + +	var cws primitive.CodeWithScope +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.CodeWithScope: +		cws, err = dvd.readCodeWithScope(dc, vr) +	case bsontype.Null: +		err = vr.ReadNull() +	case bsontype.Undefined: +		err = vr.ReadUndefined() +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a primitive.CodeWithScope", vrType) +	} +	if err != nil { +		return emptyValue, err +	} + +	return reflect.ValueOf(cws), nil +} + +// CodeWithScopeDecodeValue is the ValueDecoderFunc for CodeWithScope. +func (dvd DefaultValueDecoders) CodeWithScopeDecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tCodeWithScope { +		return ValueDecoderError{Name: "CodeWithScopeDecodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val} +	} + +	elem, err := dvd.codeWithScopeDecodeType(dc, vr, tCodeWithScope) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +func (dvd DefaultValueDecoders) decodeD(dc DecodeContext, vr bsonrw.ValueReader, _ reflect.Value) ([]reflect.Value, error) { +	switch vr.Type() { +	case bsontype.Type(0), bsontype.EmbeddedDocument: +	default: +		return nil, fmt.Errorf("cannot decode %v into a D", vr.Type()) +	} + +	dr, err := vr.ReadDocument() +	if err != nil { +		return nil, err +	} + +	return dvd.decodeElemsFromDocumentReader(dc, dr) +} + +func (DefaultValueDecoders) decodeElemsFromDocumentReader(dc DecodeContext, dr bsonrw.DocumentReader) ([]reflect.Value, error) { +	decoder, err := dc.LookupDecoder(tEmpty) +	if err != nil { +		return nil, err +	} + +	elems := make([]reflect.Value, 0) +	for { +		key, vr, err := dr.ReadElement() +		if err == bsonrw.ErrEOD { +			break +		} +		if err != nil { +			return nil, err +		} + +		val := reflect.New(tEmpty).Elem() +		err = decoder.DecodeValue(dc, vr, val) +		if err != nil { +			return nil, newDecodeError(key, err) +		} + +		elems = append(elems, reflect.ValueOf(primitive.E{Key: key, Value: val.Interface()})) +	} + +	return elems, nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go new file mode 100644 index 000000000..6bdb43cb4 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go @@ -0,0 +1,766 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"encoding/json" +	"errors" +	"fmt" +	"math" +	"net/url" +	"reflect" +	"sync" +	"time" + +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +var defaultValueEncoders DefaultValueEncoders + +var bvwPool = bsonrw.NewBSONValueWriterPool() + +var errInvalidValue = errors.New("cannot encode invalid element") + +var sliceWriterPool = sync.Pool{ +	New: func() interface{} { +		sw := make(bsonrw.SliceWriter, 0) +		return &sw +	}, +} + +func encodeElement(ec EncodeContext, dw bsonrw.DocumentWriter, e primitive.E) error { +	vw, err := dw.WriteDocumentElement(e.Key) +	if err != nil { +		return err +	} + +	if e.Value == nil { +		return vw.WriteNull() +	} +	encoder, err := ec.LookupEncoder(reflect.TypeOf(e.Value)) +	if err != nil { +		return err +	} + +	err = encoder.EncodeValue(ec, vw, reflect.ValueOf(e.Value)) +	if err != nil { +		return err +	} +	return nil +} + +// DefaultValueEncoders is a namespace type for the default ValueEncoders used +// when creating a registry. +type DefaultValueEncoders struct{} + +// RegisterDefaultEncoders will register the encoder methods attached to DefaultValueEncoders with +// the provided RegistryBuilder. +func (dve DefaultValueEncoders) RegisterDefaultEncoders(rb *RegistryBuilder) { +	if rb == nil { +		panic(errors.New("argument to RegisterDefaultEncoders must not be nil")) +	} +	rb. +		RegisterTypeEncoder(tByteSlice, defaultByteSliceCodec). +		RegisterTypeEncoder(tTime, defaultTimeCodec). +		RegisterTypeEncoder(tEmpty, defaultEmptyInterfaceCodec). +		RegisterTypeEncoder(tCoreArray, defaultArrayCodec). +		RegisterTypeEncoder(tOID, ValueEncoderFunc(dve.ObjectIDEncodeValue)). +		RegisterTypeEncoder(tDecimal, ValueEncoderFunc(dve.Decimal128EncodeValue)). +		RegisterTypeEncoder(tJSONNumber, ValueEncoderFunc(dve.JSONNumberEncodeValue)). +		RegisterTypeEncoder(tURL, ValueEncoderFunc(dve.URLEncodeValue)). +		RegisterTypeEncoder(tJavaScript, ValueEncoderFunc(dve.JavaScriptEncodeValue)). +		RegisterTypeEncoder(tSymbol, ValueEncoderFunc(dve.SymbolEncodeValue)). +		RegisterTypeEncoder(tBinary, ValueEncoderFunc(dve.BinaryEncodeValue)). +		RegisterTypeEncoder(tUndefined, ValueEncoderFunc(dve.UndefinedEncodeValue)). +		RegisterTypeEncoder(tDateTime, ValueEncoderFunc(dve.DateTimeEncodeValue)). +		RegisterTypeEncoder(tNull, ValueEncoderFunc(dve.NullEncodeValue)). +		RegisterTypeEncoder(tRegex, ValueEncoderFunc(dve.RegexEncodeValue)). +		RegisterTypeEncoder(tDBPointer, ValueEncoderFunc(dve.DBPointerEncodeValue)). +		RegisterTypeEncoder(tTimestamp, ValueEncoderFunc(dve.TimestampEncodeValue)). +		RegisterTypeEncoder(tMinKey, ValueEncoderFunc(dve.MinKeyEncodeValue)). +		RegisterTypeEncoder(tMaxKey, ValueEncoderFunc(dve.MaxKeyEncodeValue)). +		RegisterTypeEncoder(tCoreDocument, ValueEncoderFunc(dve.CoreDocumentEncodeValue)). +		RegisterTypeEncoder(tCodeWithScope, ValueEncoderFunc(dve.CodeWithScopeEncodeValue)). +		RegisterDefaultEncoder(reflect.Bool, ValueEncoderFunc(dve.BooleanEncodeValue)). +		RegisterDefaultEncoder(reflect.Int, ValueEncoderFunc(dve.IntEncodeValue)). +		RegisterDefaultEncoder(reflect.Int8, ValueEncoderFunc(dve.IntEncodeValue)). +		RegisterDefaultEncoder(reflect.Int16, ValueEncoderFunc(dve.IntEncodeValue)). +		RegisterDefaultEncoder(reflect.Int32, ValueEncoderFunc(dve.IntEncodeValue)). +		RegisterDefaultEncoder(reflect.Int64, ValueEncoderFunc(dve.IntEncodeValue)). +		RegisterDefaultEncoder(reflect.Uint, defaultUIntCodec). +		RegisterDefaultEncoder(reflect.Uint8, defaultUIntCodec). +		RegisterDefaultEncoder(reflect.Uint16, defaultUIntCodec). +		RegisterDefaultEncoder(reflect.Uint32, defaultUIntCodec). +		RegisterDefaultEncoder(reflect.Uint64, defaultUIntCodec). +		RegisterDefaultEncoder(reflect.Float32, ValueEncoderFunc(dve.FloatEncodeValue)). +		RegisterDefaultEncoder(reflect.Float64, ValueEncoderFunc(dve.FloatEncodeValue)). +		RegisterDefaultEncoder(reflect.Array, ValueEncoderFunc(dve.ArrayEncodeValue)). +		RegisterDefaultEncoder(reflect.Map, defaultMapCodec). +		RegisterDefaultEncoder(reflect.Slice, defaultSliceCodec). +		RegisterDefaultEncoder(reflect.String, defaultStringCodec). +		RegisterDefaultEncoder(reflect.Struct, newDefaultStructCodec()). +		RegisterDefaultEncoder(reflect.Ptr, NewPointerCodec()). +		RegisterHookEncoder(tValueMarshaler, ValueEncoderFunc(dve.ValueMarshalerEncodeValue)). +		RegisterHookEncoder(tMarshaler, ValueEncoderFunc(dve.MarshalerEncodeValue)). +		RegisterHookEncoder(tProxy, ValueEncoderFunc(dve.ProxyEncodeValue)) +} + +// BooleanEncodeValue is the ValueEncoderFunc for bool types. +func (dve DefaultValueEncoders) BooleanEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Kind() != reflect.Bool { +		return ValueEncoderError{Name: "BooleanEncodeValue", Kinds: []reflect.Kind{reflect.Bool}, Received: val} +	} +	return vw.WriteBoolean(val.Bool()) +} + +func fitsIn32Bits(i int64) bool { +	return math.MinInt32 <= i && i <= math.MaxInt32 +} + +// IntEncodeValue is the ValueEncoderFunc for int types. +func (dve DefaultValueEncoders) IntEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	switch val.Kind() { +	case reflect.Int8, reflect.Int16, reflect.Int32: +		return vw.WriteInt32(int32(val.Int())) +	case reflect.Int: +		i64 := val.Int() +		if fitsIn32Bits(i64) { +			return vw.WriteInt32(int32(i64)) +		} +		return vw.WriteInt64(i64) +	case reflect.Int64: +		i64 := val.Int() +		if ec.MinSize && fitsIn32Bits(i64) { +			return vw.WriteInt32(int32(i64)) +		} +		return vw.WriteInt64(i64) +	} + +	return ValueEncoderError{ +		Name:     "IntEncodeValue", +		Kinds:    []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int}, +		Received: val, +	} +} + +// UintEncodeValue is the ValueEncoderFunc for uint types. +// +// Deprecated: UintEncodeValue is not registered by default. Use UintCodec.EncodeValue instead. +func (dve DefaultValueEncoders) UintEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	switch val.Kind() { +	case reflect.Uint8, reflect.Uint16: +		return vw.WriteInt32(int32(val.Uint())) +	case reflect.Uint, reflect.Uint32, reflect.Uint64: +		u64 := val.Uint() +		if ec.MinSize && u64 <= math.MaxInt32 { +			return vw.WriteInt32(int32(u64)) +		} +		if u64 > math.MaxInt64 { +			return fmt.Errorf("%d overflows int64", u64) +		} +		return vw.WriteInt64(int64(u64)) +	} + +	return ValueEncoderError{ +		Name:     "UintEncodeValue", +		Kinds:    []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, +		Received: val, +	} +} + +// FloatEncodeValue is the ValueEncoderFunc for float types. +func (dve DefaultValueEncoders) FloatEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	switch val.Kind() { +	case reflect.Float32, reflect.Float64: +		return vw.WriteDouble(val.Float()) +	} + +	return ValueEncoderError{Name: "FloatEncodeValue", Kinds: []reflect.Kind{reflect.Float32, reflect.Float64}, Received: val} +} + +// StringEncodeValue is the ValueEncoderFunc for string types. +// +// Deprecated: StringEncodeValue is not registered by default. Use StringCodec.EncodeValue instead. +func (dve DefaultValueEncoders) StringEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if val.Kind() != reflect.String { +		return ValueEncoderError{ +			Name:     "StringEncodeValue", +			Kinds:    []reflect.Kind{reflect.String}, +			Received: val, +		} +	} + +	return vw.WriteString(val.String()) +} + +// ObjectIDEncodeValue is the ValueEncoderFunc for primitive.ObjectID. +func (dve DefaultValueEncoders) ObjectIDEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tOID { +		return ValueEncoderError{Name: "ObjectIDEncodeValue", Types: []reflect.Type{tOID}, Received: val} +	} +	return vw.WriteObjectID(val.Interface().(primitive.ObjectID)) +} + +// Decimal128EncodeValue is the ValueEncoderFunc for primitive.Decimal128. +func (dve DefaultValueEncoders) Decimal128EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tDecimal { +		return ValueEncoderError{Name: "Decimal128EncodeValue", Types: []reflect.Type{tDecimal}, Received: val} +	} +	return vw.WriteDecimal128(val.Interface().(primitive.Decimal128)) +} + +// JSONNumberEncodeValue is the ValueEncoderFunc for json.Number. +func (dve DefaultValueEncoders) JSONNumberEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tJSONNumber { +		return ValueEncoderError{Name: "JSONNumberEncodeValue", Types: []reflect.Type{tJSONNumber}, Received: val} +	} +	jsnum := val.Interface().(json.Number) + +	// Attempt int first, then float64 +	if i64, err := jsnum.Int64(); err == nil { +		return dve.IntEncodeValue(ec, vw, reflect.ValueOf(i64)) +	} + +	f64, err := jsnum.Float64() +	if err != nil { +		return err +	} + +	return dve.FloatEncodeValue(ec, vw, reflect.ValueOf(f64)) +} + +// URLEncodeValue is the ValueEncoderFunc for url.URL. +func (dve DefaultValueEncoders) URLEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tURL { +		return ValueEncoderError{Name: "URLEncodeValue", Types: []reflect.Type{tURL}, Received: val} +	} +	u := val.Interface().(url.URL) +	return vw.WriteString(u.String()) +} + +// TimeEncodeValue is the ValueEncoderFunc for time.TIme. +// +// Deprecated: TimeEncodeValue is not registered by default. Use TimeCodec.EncodeValue instead. +func (dve DefaultValueEncoders) TimeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tTime { +		return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val} +	} +	tt := val.Interface().(time.Time) +	dt := primitive.NewDateTimeFromTime(tt) +	return vw.WriteDateTime(int64(dt)) +} + +// ByteSliceEncodeValue is the ValueEncoderFunc for []byte. +// +// Deprecated: ByteSliceEncodeValue is not registered by default. Use ByteSliceCodec.EncodeValue instead. +func (dve DefaultValueEncoders) ByteSliceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tByteSlice { +		return ValueEncoderError{Name: "ByteSliceEncodeValue", Types: []reflect.Type{tByteSlice}, Received: val} +	} +	if val.IsNil() { +		return vw.WriteNull() +	} +	return vw.WriteBinary(val.Interface().([]byte)) +} + +// MapEncodeValue is the ValueEncoderFunc for map[string]* types. +// +// Deprecated: MapEncodeValue is not registered by default. Use MapCodec.EncodeValue instead. +func (dve DefaultValueEncoders) MapEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Kind() != reflect.Map || val.Type().Key().Kind() != reflect.String { +		return ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} +	} + +	if val.IsNil() { +		// If we have a nill map but we can't WriteNull, that means we're probably trying to encode +		// to a TopLevel document. We can't currently tell if this is what actually happened, but if +		// there's a deeper underlying problem, the error will also be returned from WriteDocument, +		// so just continue. The operations on a map reflection value are valid, so we can call +		// MapKeys within mapEncodeValue without a problem. +		err := vw.WriteNull() +		if err == nil { +			return nil +		} +	} + +	dw, err := vw.WriteDocument() +	if err != nil { +		return err +	} + +	return dve.mapEncodeValue(ec, dw, val, nil) +} + +// mapEncodeValue handles encoding of the values of a map. The collisionFn returns +// true if the provided key exists, this is mainly used for inline maps in the +// struct codec. +func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, val reflect.Value, collisionFn func(string) bool) error { + +	elemType := val.Type().Elem() +	encoder, err := ec.LookupEncoder(elemType) +	if err != nil && elemType.Kind() != reflect.Interface { +		return err +	} + +	keys := val.MapKeys() +	for _, key := range keys { +		if collisionFn != nil && collisionFn(key.String()) { +			return fmt.Errorf("Key %s of inlined map conflicts with a struct field name", key) +		} + +		currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.MapIndex(key)) +		if lookupErr != nil && lookupErr != errInvalidValue { +			return lookupErr +		} + +		vw, err := dw.WriteDocumentElement(key.String()) +		if err != nil { +			return err +		} + +		if lookupErr == errInvalidValue { +			err = vw.WriteNull() +			if err != nil { +				return err +			} +			continue +		} + +		err = currEncoder.EncodeValue(ec, vw, currVal) +		if err != nil { +			return err +		} +	} + +	return dw.WriteDocumentEnd() +} + +// ArrayEncodeValue is the ValueEncoderFunc for array types. +func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Kind() != reflect.Array { +		return ValueEncoderError{Name: "ArrayEncodeValue", Kinds: []reflect.Kind{reflect.Array}, Received: val} +	} + +	// If we have a []primitive.E we want to treat it as a document instead of as an array. +	if val.Type().Elem() == tE { +		dw, err := vw.WriteDocument() +		if err != nil { +			return err +		} + +		for idx := 0; idx < val.Len(); idx++ { +			e := val.Index(idx).Interface().(primitive.E) +			err = encodeElement(ec, dw, e) +			if err != nil { +				return err +			} +		} + +		return dw.WriteDocumentEnd() +	} + +	// If we have a []byte we want to treat it as a binary instead of as an array. +	if val.Type().Elem() == tByte { +		var byteSlice []byte +		for idx := 0; idx < val.Len(); idx++ { +			byteSlice = append(byteSlice, val.Index(idx).Interface().(byte)) +		} +		return vw.WriteBinary(byteSlice) +	} + +	aw, err := vw.WriteArray() +	if err != nil { +		return err +	} + +	elemType := val.Type().Elem() +	encoder, err := ec.LookupEncoder(elemType) +	if err != nil && elemType.Kind() != reflect.Interface { +		return err +	} + +	for idx := 0; idx < val.Len(); idx++ { +		currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) +		if lookupErr != nil && lookupErr != errInvalidValue { +			return lookupErr +		} + +		vw, err := aw.WriteArrayElement() +		if err != nil { +			return err +		} + +		if lookupErr == errInvalidValue { +			err = vw.WriteNull() +			if err != nil { +				return err +			} +			continue +		} + +		err = currEncoder.EncodeValue(ec, vw, currVal) +		if err != nil { +			return err +		} +	} +	return aw.WriteArrayEnd() +} + +// SliceEncodeValue is the ValueEncoderFunc for slice types. +// +// Deprecated: SliceEncodeValue is not registered by default. Use SliceCodec.EncodeValue instead. +func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Kind() != reflect.Slice { +		return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} +	} + +	if val.IsNil() { +		return vw.WriteNull() +	} + +	// If we have a []primitive.E we want to treat it as a document instead of as an array. +	if val.Type().ConvertibleTo(tD) { +		d := val.Convert(tD).Interface().(primitive.D) + +		dw, err := vw.WriteDocument() +		if err != nil { +			return err +		} + +		for _, e := range d { +			err = encodeElement(ec, dw, e) +			if err != nil { +				return err +			} +		} + +		return dw.WriteDocumentEnd() +	} + +	aw, err := vw.WriteArray() +	if err != nil { +		return err +	} + +	elemType := val.Type().Elem() +	encoder, err := ec.LookupEncoder(elemType) +	if err != nil && elemType.Kind() != reflect.Interface { +		return err +	} + +	for idx := 0; idx < val.Len(); idx++ { +		currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) +		if lookupErr != nil && lookupErr != errInvalidValue { +			return lookupErr +		} + +		vw, err := aw.WriteArrayElement() +		if err != nil { +			return err +		} + +		if lookupErr == errInvalidValue { +			err = vw.WriteNull() +			if err != nil { +				return err +			} +			continue +		} + +		err = currEncoder.EncodeValue(ec, vw, currVal) +		if err != nil { +			return err +		} +	} +	return aw.WriteArrayEnd() +} + +func (dve DefaultValueEncoders) lookupElementEncoder(ec EncodeContext, origEncoder ValueEncoder, currVal reflect.Value) (ValueEncoder, reflect.Value, error) { +	if origEncoder != nil || (currVal.Kind() != reflect.Interface) { +		return origEncoder, currVal, nil +	} +	currVal = currVal.Elem() +	if !currVal.IsValid() { +		return nil, currVal, errInvalidValue +	} +	currEncoder, err := ec.LookupEncoder(currVal.Type()) + +	return currEncoder, currVal, err +} + +// EmptyInterfaceEncodeValue is the ValueEncoderFunc for interface{}. +// +// Deprecated: EmptyInterfaceEncodeValue is not registered by default. Use EmptyInterfaceCodec.EncodeValue instead. +func (dve DefaultValueEncoders) EmptyInterfaceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tEmpty { +		return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val} +	} + +	if val.IsNil() { +		return vw.WriteNull() +	} +	encoder, err := ec.LookupEncoder(val.Elem().Type()) +	if err != nil { +		return err +	} + +	return encoder.EncodeValue(ec, vw, val.Elem()) +} + +// ValueMarshalerEncodeValue is the ValueEncoderFunc for ValueMarshaler implementations. +func (dve DefaultValueEncoders) ValueMarshalerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	// Either val or a pointer to val must implement ValueMarshaler +	switch { +	case !val.IsValid(): +		return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val} +	case val.Type().Implements(tValueMarshaler): +		// If ValueMarshaler is implemented on a concrete type, make sure that val isn't a nil pointer +		if isImplementationNil(val, tValueMarshaler) { +			return vw.WriteNull() +		} +	case reflect.PtrTo(val.Type()).Implements(tValueMarshaler) && val.CanAddr(): +		val = val.Addr() +	default: +		return ValueEncoderError{Name: "ValueMarshalerEncodeValue", Types: []reflect.Type{tValueMarshaler}, Received: val} +	} + +	fn := val.Convert(tValueMarshaler).MethodByName("MarshalBSONValue") +	returns := fn.Call(nil) +	if !returns[2].IsNil() { +		return returns[2].Interface().(error) +	} +	t, data := returns[0].Interface().(bsontype.Type), returns[1].Interface().([]byte) +	return bsonrw.Copier{}.CopyValueFromBytes(vw, t, data) +} + +// MarshalerEncodeValue is the ValueEncoderFunc for Marshaler implementations. +func (dve DefaultValueEncoders) MarshalerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	// Either val or a pointer to val must implement Marshaler +	switch { +	case !val.IsValid(): +		return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val} +	case val.Type().Implements(tMarshaler): +		// If Marshaler is implemented on a concrete type, make sure that val isn't a nil pointer +		if isImplementationNil(val, tMarshaler) { +			return vw.WriteNull() +		} +	case reflect.PtrTo(val.Type()).Implements(tMarshaler) && val.CanAddr(): +		val = val.Addr() +	default: +		return ValueEncoderError{Name: "MarshalerEncodeValue", Types: []reflect.Type{tMarshaler}, Received: val} +	} + +	fn := val.Convert(tMarshaler).MethodByName("MarshalBSON") +	returns := fn.Call(nil) +	if !returns[1].IsNil() { +		return returns[1].Interface().(error) +	} +	data := returns[0].Interface().([]byte) +	return bsonrw.Copier{}.CopyValueFromBytes(vw, bsontype.EmbeddedDocument, data) +} + +// ProxyEncodeValue is the ValueEncoderFunc for Proxy implementations. +func (dve DefaultValueEncoders) ProxyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	// Either val or a pointer to val must implement Proxy +	switch { +	case !val.IsValid(): +		return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val} +	case val.Type().Implements(tProxy): +		// If Proxy is implemented on a concrete type, make sure that val isn't a nil pointer +		if isImplementationNil(val, tProxy) { +			return vw.WriteNull() +		} +	case reflect.PtrTo(val.Type()).Implements(tProxy) && val.CanAddr(): +		val = val.Addr() +	default: +		return ValueEncoderError{Name: "ProxyEncodeValue", Types: []reflect.Type{tProxy}, Received: val} +	} + +	fn := val.Convert(tProxy).MethodByName("ProxyBSON") +	returns := fn.Call(nil) +	if !returns[1].IsNil() { +		return returns[1].Interface().(error) +	} +	data := returns[0] +	var encoder ValueEncoder +	var err error +	if data.Elem().IsValid() { +		encoder, err = ec.LookupEncoder(data.Elem().Type()) +	} else { +		encoder, err = ec.LookupEncoder(nil) +	} +	if err != nil { +		return err +	} +	return encoder.EncodeValue(ec, vw, data.Elem()) +} + +// JavaScriptEncodeValue is the ValueEncoderFunc for the primitive.JavaScript type. +func (DefaultValueEncoders) JavaScriptEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tJavaScript { +		return ValueEncoderError{Name: "JavaScriptEncodeValue", Types: []reflect.Type{tJavaScript}, Received: val} +	} + +	return vw.WriteJavascript(val.String()) +} + +// SymbolEncodeValue is the ValueEncoderFunc for the primitive.Symbol type. +func (DefaultValueEncoders) SymbolEncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tSymbol { +		return ValueEncoderError{Name: "SymbolEncodeValue", Types: []reflect.Type{tSymbol}, Received: val} +	} + +	return vw.WriteSymbol(val.String()) +} + +// BinaryEncodeValue is the ValueEncoderFunc for Binary. +func (DefaultValueEncoders) BinaryEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tBinary { +		return ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val} +	} +	b := val.Interface().(primitive.Binary) + +	return vw.WriteBinaryWithSubtype(b.Data, b.Subtype) +} + +// UndefinedEncodeValue is the ValueEncoderFunc for Undefined. +func (DefaultValueEncoders) UndefinedEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tUndefined { +		return ValueEncoderError{Name: "UndefinedEncodeValue", Types: []reflect.Type{tUndefined}, Received: val} +	} + +	return vw.WriteUndefined() +} + +// DateTimeEncodeValue is the ValueEncoderFunc for DateTime. +func (DefaultValueEncoders) DateTimeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tDateTime { +		return ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: val} +	} + +	return vw.WriteDateTime(val.Int()) +} + +// NullEncodeValue is the ValueEncoderFunc for Null. +func (DefaultValueEncoders) NullEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tNull { +		return ValueEncoderError{Name: "NullEncodeValue", Types: []reflect.Type{tNull}, Received: val} +	} + +	return vw.WriteNull() +} + +// RegexEncodeValue is the ValueEncoderFunc for Regex. +func (DefaultValueEncoders) RegexEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tRegex { +		return ValueEncoderError{Name: "RegexEncodeValue", Types: []reflect.Type{tRegex}, Received: val} +	} + +	regex := val.Interface().(primitive.Regex) + +	return vw.WriteRegex(regex.Pattern, regex.Options) +} + +// DBPointerEncodeValue is the ValueEncoderFunc for DBPointer. +func (DefaultValueEncoders) DBPointerEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tDBPointer { +		return ValueEncoderError{Name: "DBPointerEncodeValue", Types: []reflect.Type{tDBPointer}, Received: val} +	} + +	dbp := val.Interface().(primitive.DBPointer) + +	return vw.WriteDBPointer(dbp.DB, dbp.Pointer) +} + +// TimestampEncodeValue is the ValueEncoderFunc for Timestamp. +func (DefaultValueEncoders) TimestampEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tTimestamp { +		return ValueEncoderError{Name: "TimestampEncodeValue", Types: []reflect.Type{tTimestamp}, Received: val} +	} + +	ts := val.Interface().(primitive.Timestamp) + +	return vw.WriteTimestamp(ts.T, ts.I) +} + +// MinKeyEncodeValue is the ValueEncoderFunc for MinKey. +func (DefaultValueEncoders) MinKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tMinKey { +		return ValueEncoderError{Name: "MinKeyEncodeValue", Types: []reflect.Type{tMinKey}, Received: val} +	} + +	return vw.WriteMinKey() +} + +// MaxKeyEncodeValue is the ValueEncoderFunc for MaxKey. +func (DefaultValueEncoders) MaxKeyEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tMaxKey { +		return ValueEncoderError{Name: "MaxKeyEncodeValue", Types: []reflect.Type{tMaxKey}, Received: val} +	} + +	return vw.WriteMaxKey() +} + +// CoreDocumentEncodeValue is the ValueEncoderFunc for bsoncore.Document. +func (DefaultValueEncoders) CoreDocumentEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tCoreDocument { +		return ValueEncoderError{Name: "CoreDocumentEncodeValue", Types: []reflect.Type{tCoreDocument}, Received: val} +	} + +	cdoc := val.Interface().(bsoncore.Document) + +	return bsonrw.Copier{}.CopyDocumentFromBytes(vw, cdoc) +} + +// CodeWithScopeEncodeValue is the ValueEncoderFunc for CodeWithScope. +func (dve DefaultValueEncoders) CodeWithScopeEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tCodeWithScope { +		return ValueEncoderError{Name: "CodeWithScopeEncodeValue", Types: []reflect.Type{tCodeWithScope}, Received: val} +	} + +	cws := val.Interface().(primitive.CodeWithScope) + +	dw, err := vw.WriteCodeWithScope(string(cws.Code)) +	if err != nil { +		return err +	} + +	sw := sliceWriterPool.Get().(*bsonrw.SliceWriter) +	defer sliceWriterPool.Put(sw) +	*sw = (*sw)[:0] + +	scopeVW := bvwPool.Get(sw) +	defer bvwPool.Put(scopeVW) + +	encoder, err := ec.LookupEncoder(reflect.TypeOf(cws.Scope)) +	if err != nil { +		return err +	} + +	err = encoder.EncodeValue(ec, scopeVW, reflect.ValueOf(cws.Scope)) +	if err != nil { +		return err +	} + +	err = bsonrw.Copier{}.CopyBytesToDocumentWriter(dw, *sw) +	if err != nil { +		return err +	} +	return dw.WriteDocumentEnd() +} + +// isImplementationNil returns if val is a nil pointer and inter is implemented on a concrete type +func isImplementationNil(val reflect.Value, inter reflect.Type) bool { +	vt := val.Type() +	for vt.Kind() == reflect.Ptr { +		vt = vt.Elem() +	} +	return vt.Implements(inter) && val.Kind() == reflect.Ptr && val.IsNil() +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go new file mode 100644 index 000000000..5f903ebea --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/doc.go @@ -0,0 +1,90 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package bsoncodec provides a system for encoding values to BSON representations and decoding +// values from BSON representations. This package considers both binary BSON and ExtendedJSON as +// BSON representations. The types in this package enable a flexible system for handling this +// encoding and decoding. +// +// The codec system is composed of two parts: +// +// 1) ValueEncoders and ValueDecoders that handle encoding and decoding Go values to and from BSON +// representations. +// +// 2) A Registry that holds these ValueEncoders and ValueDecoders and provides methods for +// retrieving them. +// +// # ValueEncoders and ValueDecoders +// +// The ValueEncoder interface is implemented by types that can encode a provided Go type to BSON. +// The value to encode is provided as a reflect.Value and a bsonrw.ValueWriter is used within the +// EncodeValue method to actually create the BSON representation. For convenience, ValueEncoderFunc +// is provided to allow use of a function with the correct signature as a ValueEncoder. An +// EncodeContext instance is provided to allow implementations to lookup further ValueEncoders and +// to provide configuration information. +// +// The ValueDecoder interface is the inverse of the ValueEncoder. Implementations should ensure that +// the value they receive is settable. Similar to ValueEncoderFunc, ValueDecoderFunc is provided to +// allow the use of a function with the correct signature as a ValueDecoder. A DecodeContext +// instance is provided and serves similar functionality to the EncodeContext. +// +// # Registry and RegistryBuilder +// +// A Registry is an immutable store for ValueEncoders, ValueDecoders, and a type map. See the Registry type +// documentation for examples of registering various custom encoders and decoders. A Registry can be constructed using a +// RegistryBuilder, which handles three main types of codecs: +// +// 1. Type encoders/decoders - These can be registered using the RegisterTypeEncoder and RegisterTypeDecoder methods. +// The registered codec will be invoked when encoding/decoding a value whose type matches the registered type exactly. +// If the registered type is an interface, the codec will be invoked when encoding or decoding values whose type is the +// interface, but not for values with concrete types that implement the interface. +// +// 2. Hook encoders/decoders - These can be registered using the RegisterHookEncoder and RegisterHookDecoder methods. +// These methods only accept interface types and the registered codecs will be invoked when encoding or decoding values +// whose types implement the interface. An example of a hook defined by the driver is bson.Marshaler. The driver will +// call the MarshalBSON method for any value whose type implements bson.Marshaler, regardless of the value's concrete +// type. +// +// 3. Type map entries - This can be used to associate a BSON type with a Go type. These type associations are used when +// decoding into a bson.D/bson.M or a struct field of type interface{}. For example, by default, BSON int32 and int64 +// values decode as Go int32 and int64 instances, respectively, when decoding into a bson.D. The following code would +// change the behavior so these values decode as Go int instances instead: +// +//	intType := reflect.TypeOf(int(0)) +//	registryBuilder.RegisterTypeMapEntry(bsontype.Int32, intType).RegisterTypeMapEntry(bsontype.Int64, intType) +// +// 4. Kind encoder/decoders - These can be registered using the RegisterDefaultEncoder and RegisterDefaultDecoder +// methods. The registered codec will be invoked when encoding or decoding values whose reflect.Kind matches the +// registered reflect.Kind as long as the value's type doesn't match a registered type or hook encoder/decoder first. +// These methods should be used to change the behavior for all values for a specific kind. +// +// # Registry Lookup Procedure +// +// When looking up an encoder in a Registry, the precedence rules are as follows: +// +// 1. A type encoder registered for the exact type of the value. +// +// 2. A hook encoder registered for an interface that is implemented by the value or by a pointer to the value. If the +// value matches multiple hooks (e.g. the type implements bsoncodec.Marshaler and bsoncodec.ValueMarshaler), the first +// one registered will be selected. Note that registries constructed using bson.NewRegistryBuilder have driver-defined +// hooks registered for the bsoncodec.Marshaler, bsoncodec.ValueMarshaler, and bsoncodec.Proxy interfaces, so those +// will take precedence over any new hooks. +// +// 3. A kind encoder registered for the value's kind. +// +// If all of these lookups fail to find an encoder, an error of type ErrNoEncoder is returned. The same precedence +// rules apply for decoders, with the exception that an error of type ErrNoDecoder will be returned if no decoder is +// found. +// +// # DefaultValueEncoders and DefaultValueDecoders +// +// The DefaultValueEncoders and DefaultValueDecoders types provide a full set of ValueEncoders and +// ValueDecoders for handling a wide range of Go types, including all of the types within the +// primitive package. To make registering these codecs easier, a helper method on each type is +// provided. For the DefaultValueEncoders type the method is called RegisterDefaultEncoders and for +// the DefaultValueDecoders type the method is called RegisterDefaultDecoders, this method also +// handles registering type map entries for each BSON type. +package bsoncodec diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go new file mode 100644 index 000000000..eda417cff --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go @@ -0,0 +1,147 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"reflect" + +	"go.mongodb.org/mongo-driver/bson/bsonoptions" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +// EmptyInterfaceCodec is the Codec used for interface{} values. +type EmptyInterfaceCodec struct { +	DecodeBinaryAsSlice bool +} + +var ( +	defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec() + +	_ ValueCodec  = defaultEmptyInterfaceCodec +	_ typeDecoder = defaultEmptyInterfaceCodec +) + +// NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts. +func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec { +	interfaceOpt := bsonoptions.MergeEmptyInterfaceCodecOptions(opts...) + +	codec := EmptyInterfaceCodec{} +	if interfaceOpt.DecodeBinaryAsSlice != nil { +		codec.DecodeBinaryAsSlice = *interfaceOpt.DecodeBinaryAsSlice +	} +	return &codec +} + +// EncodeValue is the ValueEncoderFunc for interface{}. +func (eic EmptyInterfaceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tEmpty { +		return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val} +	} + +	if val.IsNil() { +		return vw.WriteNull() +	} +	encoder, err := ec.LookupEncoder(val.Elem().Type()) +	if err != nil { +		return err +	} + +	return encoder.EncodeValue(ec, vw, val.Elem()) +} + +func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, valueType bsontype.Type) (reflect.Type, error) { +	isDocument := valueType == bsontype.Type(0) || valueType == bsontype.EmbeddedDocument +	if isDocument { +		if dc.defaultDocumentType != nil { +			// If the bsontype is an embedded document and the DocumentType is set on the DecodeContext, then return +			// that type. +			return dc.defaultDocumentType, nil +		} +		if dc.Ancestor != nil { +			// Using ancestor information rather than looking up the type map entry forces consistent decoding. +			// If we're decoding into a bson.D, subdocuments should also be decoded as bson.D, even if a type map entry +			// has been registered. +			return dc.Ancestor, nil +		} +	} + +	rtype, err := dc.LookupTypeMapEntry(valueType) +	if err == nil { +		return rtype, nil +	} + +	if isDocument { +		// For documents, fallback to looking up a type map entry for bsontype.Type(0) or bsontype.EmbeddedDocument, +		// depending on the original valueType. +		var lookupType bsontype.Type +		switch valueType { +		case bsontype.Type(0): +			lookupType = bsontype.EmbeddedDocument +		case bsontype.EmbeddedDocument: +			lookupType = bsontype.Type(0) +		} + +		rtype, err = dc.LookupTypeMapEntry(lookupType) +		if err == nil { +			return rtype, nil +		} +	} + +	return nil, err +} + +func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tEmpty { +		return emptyValue, ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.Zero(t)} +	} + +	rtype, err := eic.getEmptyInterfaceDecodeType(dc, vr.Type()) +	if err != nil { +		switch vr.Type() { +		case bsontype.Null: +			return reflect.Zero(t), vr.ReadNull() +		default: +			return emptyValue, err +		} +	} + +	decoder, err := dc.LookupDecoder(rtype) +	if err != nil { +		return emptyValue, err +	} + +	elem, err := decodeTypeOrValue(decoder, dc, vr, rtype) +	if err != nil { +		return emptyValue, err +	} + +	if eic.DecodeBinaryAsSlice && rtype == tBinary { +		binElem := elem.Interface().(primitive.Binary) +		if binElem.Subtype == bsontype.BinaryGeneric || binElem.Subtype == bsontype.BinaryBinaryOld { +			elem = reflect.ValueOf(binElem.Data) +		} +	} + +	return elem, nil +} + +// DecodeValue is the ValueDecoderFunc for interface{}. +func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tEmpty { +		return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val} +	} + +	elem, err := eic.decodeType(dc, vr, val.Type()) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go new file mode 100644 index 000000000..e1fbef9c6 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go @@ -0,0 +1,309 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"encoding" +	"fmt" +	"reflect" +	"strconv" + +	"go.mongodb.org/mongo-driver/bson/bsonoptions" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +var defaultMapCodec = NewMapCodec() + +// MapCodec is the Codec used for map values. +type MapCodec struct { +	DecodeZerosMap         bool +	EncodeNilAsEmpty       bool +	EncodeKeysWithStringer bool +} + +var _ ValueCodec = &MapCodec{} + +// KeyMarshaler is the interface implemented by an object that can marshal itself into a string key. +// This applies to types used as map keys and is similar to encoding.TextMarshaler. +type KeyMarshaler interface { +	MarshalKey() (key string, err error) +} + +// KeyUnmarshaler is the interface implemented by an object that can unmarshal a string representation +// of itself. This applies to types used as map keys and is similar to encoding.TextUnmarshaler. +// +// UnmarshalKey must be able to decode the form generated by MarshalKey. +// UnmarshalKey must copy the text if it wishes to retain the text +// after returning. +type KeyUnmarshaler interface { +	UnmarshalKey(key string) error +} + +// NewMapCodec returns a MapCodec with options opts. +func NewMapCodec(opts ...*bsonoptions.MapCodecOptions) *MapCodec { +	mapOpt := bsonoptions.MergeMapCodecOptions(opts...) + +	codec := MapCodec{} +	if mapOpt.DecodeZerosMap != nil { +		codec.DecodeZerosMap = *mapOpt.DecodeZerosMap +	} +	if mapOpt.EncodeNilAsEmpty != nil { +		codec.EncodeNilAsEmpty = *mapOpt.EncodeNilAsEmpty +	} +	if mapOpt.EncodeKeysWithStringer != nil { +		codec.EncodeKeysWithStringer = *mapOpt.EncodeKeysWithStringer +	} +	return &codec +} + +// EncodeValue is the ValueEncoder for map[*]* types. +func (mc *MapCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Kind() != reflect.Map { +		return ValueEncoderError{Name: "MapEncodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} +	} + +	if val.IsNil() && !mc.EncodeNilAsEmpty { +		// If we have a nil map but we can't WriteNull, that means we're probably trying to encode +		// to a TopLevel document. We can't currently tell if this is what actually happened, but if +		// there's a deeper underlying problem, the error will also be returned from WriteDocument, +		// so just continue. The operations on a map reflection value are valid, so we can call +		// MapKeys within mapEncodeValue without a problem. +		err := vw.WriteNull() +		if err == nil { +			return nil +		} +	} + +	dw, err := vw.WriteDocument() +	if err != nil { +		return err +	} + +	return mc.mapEncodeValue(ec, dw, val, nil) +} + +// mapEncodeValue handles encoding of the values of a map. The collisionFn returns +// true if the provided key exists, this is mainly used for inline maps in the +// struct codec. +func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, val reflect.Value, collisionFn func(string) bool) error { + +	elemType := val.Type().Elem() +	encoder, err := ec.LookupEncoder(elemType) +	if err != nil && elemType.Kind() != reflect.Interface { +		return err +	} + +	keys := val.MapKeys() +	for _, key := range keys { +		keyStr, err := mc.encodeKey(key) +		if err != nil { +			return err +		} + +		if collisionFn != nil && collisionFn(keyStr) { +			return fmt.Errorf("Key %s of inlined map conflicts with a struct field name", key) +		} + +		currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.MapIndex(key)) +		if lookupErr != nil && lookupErr != errInvalidValue { +			return lookupErr +		} + +		vw, err := dw.WriteDocumentElement(keyStr) +		if err != nil { +			return err +		} + +		if lookupErr == errInvalidValue { +			err = vw.WriteNull() +			if err != nil { +				return err +			} +			continue +		} + +		err = currEncoder.EncodeValue(ec, vw, currVal) +		if err != nil { +			return err +		} +	} + +	return dw.WriteDocumentEnd() +} + +// DecodeValue is the ValueDecoder for map[string/decimal]* types. +func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if val.Kind() != reflect.Map || (!val.CanSet() && val.IsNil()) { +		return ValueDecoderError{Name: "MapDecodeValue", Kinds: []reflect.Kind{reflect.Map}, Received: val} +	} + +	switch vrType := vr.Type(); vrType { +	case bsontype.Type(0), bsontype.EmbeddedDocument: +	case bsontype.Null: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadNull() +	case bsontype.Undefined: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadUndefined() +	default: +		return fmt.Errorf("cannot decode %v into a %s", vrType, val.Type()) +	} + +	dr, err := vr.ReadDocument() +	if err != nil { +		return err +	} + +	if val.IsNil() { +		val.Set(reflect.MakeMap(val.Type())) +	} + +	if val.Len() > 0 && mc.DecodeZerosMap { +		clearMap(val) +	} + +	eType := val.Type().Elem() +	decoder, err := dc.LookupDecoder(eType) +	if err != nil { +		return err +	} +	eTypeDecoder, _ := decoder.(typeDecoder) + +	if eType == tEmpty { +		dc.Ancestor = val.Type() +	} + +	keyType := val.Type().Key() + +	for { +		key, vr, err := dr.ReadElement() +		if err == bsonrw.ErrEOD { +			break +		} +		if err != nil { +			return err +		} + +		k, err := mc.decodeKey(key, keyType) +		if err != nil { +			return err +		} + +		elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true) +		if err != nil { +			return newDecodeError(key, err) +		} + +		val.SetMapIndex(k, elem) +	} +	return nil +} + +func clearMap(m reflect.Value) { +	var none reflect.Value +	for _, k := range m.MapKeys() { +		m.SetMapIndex(k, none) +	} +} + +func (mc *MapCodec) encodeKey(val reflect.Value) (string, error) { +	if mc.EncodeKeysWithStringer { +		return fmt.Sprint(val), nil +	} + +	// keys of any string type are used directly +	if val.Kind() == reflect.String { +		return val.String(), nil +	} +	// KeyMarshalers are marshaled +	if km, ok := val.Interface().(KeyMarshaler); ok { +		if val.Kind() == reflect.Ptr && val.IsNil() { +			return "", nil +		} +		buf, err := km.MarshalKey() +		if err == nil { +			return buf, nil +		} +		return "", err +	} +	// keys implement encoding.TextMarshaler are marshaled. +	if km, ok := val.Interface().(encoding.TextMarshaler); ok { +		if val.Kind() == reflect.Ptr && val.IsNil() { +			return "", nil +		} + +		buf, err := km.MarshalText() +		if err != nil { +			return "", err +		} + +		return string(buf), nil +	} + +	switch val.Kind() { +	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: +		return strconv.FormatInt(val.Int(), 10), nil +	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: +		return strconv.FormatUint(val.Uint(), 10), nil +	} +	return "", fmt.Errorf("unsupported key type: %v", val.Type()) +} + +var keyUnmarshalerType = reflect.TypeOf((*KeyUnmarshaler)(nil)).Elem() +var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + +func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, error) { +	keyVal := reflect.ValueOf(key) +	var err error +	switch { +	// First, if EncodeKeysWithStringer is not enabled, try to decode withKeyUnmarshaler +	case !mc.EncodeKeysWithStringer && reflect.PtrTo(keyType).Implements(keyUnmarshalerType): +		keyVal = reflect.New(keyType) +		v := keyVal.Interface().(KeyUnmarshaler) +		err = v.UnmarshalKey(key) +		keyVal = keyVal.Elem() +	// Try to decode encoding.TextUnmarshalers. +	case reflect.PtrTo(keyType).Implements(textUnmarshalerType): +		keyVal = reflect.New(keyType) +		v := keyVal.Interface().(encoding.TextUnmarshaler) +		err = v.UnmarshalText([]byte(key)) +		keyVal = keyVal.Elem() +	// Otherwise, go to type specific behavior +	default: +		switch keyType.Kind() { +		case reflect.String: +			keyVal = reflect.ValueOf(key).Convert(keyType) +		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: +			n, parseErr := strconv.ParseInt(key, 10, 64) +			if parseErr != nil || reflect.Zero(keyType).OverflowInt(n) { +				err = fmt.Errorf("failed to unmarshal number key %v", key) +			} +			keyVal = reflect.ValueOf(n).Convert(keyType) +		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: +			n, parseErr := strconv.ParseUint(key, 10, 64) +			if parseErr != nil || reflect.Zero(keyType).OverflowUint(n) { +				err = fmt.Errorf("failed to unmarshal number key %v", key) +				break +			} +			keyVal = reflect.ValueOf(n).Convert(keyType) +		case reflect.Float32, reflect.Float64: +			if mc.EncodeKeysWithStringer { +				parsed, err := strconv.ParseFloat(key, 64) +				if err != nil { +					return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %v", keyType.Kind(), err) +				} +				keyVal = reflect.ValueOf(parsed) +				break +			} +			fallthrough +		default: +			return keyVal, fmt.Errorf("unsupported key type: %v", keyType) +		} +	} +	return keyVal, err +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go new file mode 100644 index 000000000..fbd9f0a9e --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/mode.go @@ -0,0 +1,65 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import "fmt" + +type mode int + +const ( +	_ mode = iota +	mTopLevel +	mDocument +	mArray +	mValue +	mElement +	mCodeWithScope +	mSpacer +) + +func (m mode) String() string { +	var str string + +	switch m { +	case mTopLevel: +		str = "TopLevel" +	case mDocument: +		str = "DocumentMode" +	case mArray: +		str = "ArrayMode" +	case mValue: +		str = "ValueMode" +	case mElement: +		str = "ElementMode" +	case mCodeWithScope: +		str = "CodeWithScopeMode" +	case mSpacer: +		str = "CodeWithScopeSpacerFrame" +	default: +		str = "UnknownMode" +	} + +	return str +} + +// TransitionError is an error returned when an invalid progressing a +// ValueReader or ValueWriter state machine occurs. +type TransitionError struct { +	parent      mode +	current     mode +	destination mode +} + +func (te TransitionError) Error() string { +	if te.destination == mode(0) { +		return fmt.Sprintf("invalid state transition: cannot read/write value while in %s", te.current) +	} +	if te.parent == mode(0) { +		return fmt.Sprintf("invalid state transition: %s -> %s", te.current, te.destination) +	} +	return fmt.Sprintf("invalid state transition: %s -> %s; parent %s", te.current, te.destination, te.parent) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go new file mode 100644 index 000000000..616a3e701 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go @@ -0,0 +1,109 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"reflect" +	"sync" + +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +var _ ValueEncoder = &PointerCodec{} +var _ ValueDecoder = &PointerCodec{} + +// PointerCodec is the Codec used for pointers. +type PointerCodec struct { +	ecache map[reflect.Type]ValueEncoder +	dcache map[reflect.Type]ValueDecoder +	l      sync.RWMutex +} + +// NewPointerCodec returns a PointerCodec that has been initialized. +func NewPointerCodec() *PointerCodec { +	return &PointerCodec{ +		ecache: make(map[reflect.Type]ValueEncoder), +		dcache: make(map[reflect.Type]ValueDecoder), +	} +} + +// EncodeValue handles encoding a pointer by either encoding it to BSON Null if the pointer is nil +// or looking up an encoder for the type of value the pointer points to. +func (pc *PointerCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if val.Kind() != reflect.Ptr { +		if !val.IsValid() { +			return vw.WriteNull() +		} +		return ValueEncoderError{Name: "PointerCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val} +	} + +	if val.IsNil() { +		return vw.WriteNull() +	} + +	pc.l.RLock() +	enc, ok := pc.ecache[val.Type()] +	pc.l.RUnlock() +	if ok { +		if enc == nil { +			return ErrNoEncoder{Type: val.Type()} +		} +		return enc.EncodeValue(ec, vw, val.Elem()) +	} + +	enc, err := ec.LookupEncoder(val.Type().Elem()) +	pc.l.Lock() +	pc.ecache[val.Type()] = enc +	pc.l.Unlock() +	if err != nil { +		return err +	} + +	return enc.EncodeValue(ec, vw, val.Elem()) +} + +// DecodeValue handles decoding a pointer by looking up a decoder for the type it points to and +// using that to decode. If the BSON value is Null, this method will set the pointer to nil. +func (pc *PointerCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Kind() != reflect.Ptr { +		return ValueDecoderError{Name: "PointerCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Ptr}, Received: val} +	} + +	if vr.Type() == bsontype.Null { +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadNull() +	} +	if vr.Type() == bsontype.Undefined { +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadUndefined() +	} + +	if val.IsNil() { +		val.Set(reflect.New(val.Type().Elem())) +	} + +	pc.l.RLock() +	dec, ok := pc.dcache[val.Type()] +	pc.l.RUnlock() +	if ok { +		if dec == nil { +			return ErrNoDecoder{Type: val.Type()} +		} +		return dec.DecodeValue(dc, vr, val.Elem()) +	} + +	dec, err := dc.LookupDecoder(val.Type().Elem()) +	pc.l.Lock() +	pc.dcache[val.Type()] = dec +	pc.l.Unlock() +	if err != nil { +		return err +	} + +	return dec.DecodeValue(dc, vr, val.Elem()) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go new file mode 100644 index 000000000..4cf2b01ab --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/proxy.go @@ -0,0 +1,14 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +// Proxy is an interface implemented by types that cannot themselves be directly encoded. Types +// that implement this interface with have ProxyBSON called during the encoding process and that +// value will be encoded in place for the implementer. +type Proxy interface { +	ProxyBSON() (interface{}, error) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go new file mode 100644 index 000000000..80644023c --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/registry.go @@ -0,0 +1,469 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"errors" +	"fmt" +	"reflect" +	"sync" + +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +// ErrNilType is returned when nil is passed to either LookupEncoder or LookupDecoder. +var ErrNilType = errors.New("cannot perform a decoder lookup on <nil>") + +// ErrNotPointer is returned when a non-pointer type is provided to LookupDecoder. +var ErrNotPointer = errors.New("non-pointer provided to LookupDecoder") + +// ErrNoEncoder is returned when there wasn't an encoder available for a type. +type ErrNoEncoder struct { +	Type reflect.Type +} + +func (ene ErrNoEncoder) Error() string { +	if ene.Type == nil { +		return "no encoder found for <nil>" +	} +	return "no encoder found for " + ene.Type.String() +} + +// ErrNoDecoder is returned when there wasn't a decoder available for a type. +type ErrNoDecoder struct { +	Type reflect.Type +} + +func (end ErrNoDecoder) Error() string { +	return "no decoder found for " + end.Type.String() +} + +// ErrNoTypeMapEntry is returned when there wasn't a type available for the provided BSON type. +type ErrNoTypeMapEntry struct { +	Type bsontype.Type +} + +func (entme ErrNoTypeMapEntry) Error() string { +	return "no type map entry found for " + entme.Type.String() +} + +// ErrNotInterface is returned when the provided type is not an interface. +var ErrNotInterface = errors.New("The provided type is not an interface") + +// A RegistryBuilder is used to build a Registry. This type is not goroutine +// safe. +type RegistryBuilder struct { +	typeEncoders      map[reflect.Type]ValueEncoder +	interfaceEncoders []interfaceValueEncoder +	kindEncoders      map[reflect.Kind]ValueEncoder + +	typeDecoders      map[reflect.Type]ValueDecoder +	interfaceDecoders []interfaceValueDecoder +	kindDecoders      map[reflect.Kind]ValueDecoder + +	typeMap map[bsontype.Type]reflect.Type +} + +// A Registry is used to store and retrieve codecs for types and interfaces. This type is the main +// typed passed around and Encoders and Decoders are constructed from it. +type Registry struct { +	typeEncoders map[reflect.Type]ValueEncoder +	typeDecoders map[reflect.Type]ValueDecoder + +	interfaceEncoders []interfaceValueEncoder +	interfaceDecoders []interfaceValueDecoder + +	kindEncoders map[reflect.Kind]ValueEncoder +	kindDecoders map[reflect.Kind]ValueDecoder + +	typeMap map[bsontype.Type]reflect.Type + +	mu sync.RWMutex +} + +// NewRegistryBuilder creates a new empty RegistryBuilder. +func NewRegistryBuilder() *RegistryBuilder { +	return &RegistryBuilder{ +		typeEncoders: make(map[reflect.Type]ValueEncoder), +		typeDecoders: make(map[reflect.Type]ValueDecoder), + +		interfaceEncoders: make([]interfaceValueEncoder, 0), +		interfaceDecoders: make([]interfaceValueDecoder, 0), + +		kindEncoders: make(map[reflect.Kind]ValueEncoder), +		kindDecoders: make(map[reflect.Kind]ValueDecoder), + +		typeMap: make(map[bsontype.Type]reflect.Type), +	} +} + +func buildDefaultRegistry() *Registry { +	rb := NewRegistryBuilder() +	defaultValueEncoders.RegisterDefaultEncoders(rb) +	defaultValueDecoders.RegisterDefaultDecoders(rb) +	return rb.Build() +} + +// RegisterCodec will register the provided ValueCodec for the provided type. +func (rb *RegistryBuilder) RegisterCodec(t reflect.Type, codec ValueCodec) *RegistryBuilder { +	rb.RegisterTypeEncoder(t, codec) +	rb.RegisterTypeDecoder(t, codec) +	return rb +} + +// RegisterTypeEncoder will register the provided ValueEncoder for the provided type. +// +// The type will be used directly, so an encoder can be registered for a type and a different encoder can be registered +// for a pointer to that type. +// +// If the given type is an interface, the encoder will be called when marshalling a type that is that interface. It +// will not be called when marshalling a non-interface type that implements the interface. +func (rb *RegistryBuilder) RegisterTypeEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { +	rb.typeEncoders[t] = enc +	return rb +} + +// RegisterHookEncoder will register an encoder for the provided interface type t. This encoder will be called when +// marshalling a type if the type implements t or a pointer to the type implements t. If the provided type is not +// an interface (i.e. t.Kind() != reflect.Interface), this method will panic. +func (rb *RegistryBuilder) RegisterHookEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { +	if t.Kind() != reflect.Interface { +		panicStr := fmt.Sprintf("RegisterHookEncoder expects a type with kind reflect.Interface, "+ +			"got type %s with kind %s", t, t.Kind()) +		panic(panicStr) +	} + +	for idx, encoder := range rb.interfaceEncoders { +		if encoder.i == t { +			rb.interfaceEncoders[idx].ve = enc +			return rb +		} +	} + +	rb.interfaceEncoders = append(rb.interfaceEncoders, interfaceValueEncoder{i: t, ve: enc}) +	return rb +} + +// RegisterTypeDecoder will register the provided ValueDecoder for the provided type. +// +// The type will be used directly, so a decoder can be registered for a type and a different decoder can be registered +// for a pointer to that type. +// +// If the given type is an interface, the decoder will be called when unmarshalling into a type that is that interface. +// It will not be called when unmarshalling into a non-interface type that implements the interface. +func (rb *RegistryBuilder) RegisterTypeDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { +	rb.typeDecoders[t] = dec +	return rb +} + +// RegisterHookDecoder will register an decoder for the provided interface type t. This decoder will be called when +// unmarshalling into a type if the type implements t or a pointer to the type implements t. If the provided type is not +// an interface (i.e. t.Kind() != reflect.Interface), this method will panic. +func (rb *RegistryBuilder) RegisterHookDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { +	if t.Kind() != reflect.Interface { +		panicStr := fmt.Sprintf("RegisterHookDecoder expects a type with kind reflect.Interface, "+ +			"got type %s with kind %s", t, t.Kind()) +		panic(panicStr) +	} + +	for idx, decoder := range rb.interfaceDecoders { +		if decoder.i == t { +			rb.interfaceDecoders[idx].vd = dec +			return rb +		} +	} + +	rb.interfaceDecoders = append(rb.interfaceDecoders, interfaceValueDecoder{i: t, vd: dec}) +	return rb +} + +// RegisterEncoder registers the provided type and encoder pair. +// +// Deprecated: Use RegisterTypeEncoder or RegisterHookEncoder instead. +func (rb *RegistryBuilder) RegisterEncoder(t reflect.Type, enc ValueEncoder) *RegistryBuilder { +	if t == tEmpty { +		rb.typeEncoders[t] = enc +		return rb +	} +	switch t.Kind() { +	case reflect.Interface: +		for idx, ir := range rb.interfaceEncoders { +			if ir.i == t { +				rb.interfaceEncoders[idx].ve = enc +				return rb +			} +		} + +		rb.interfaceEncoders = append(rb.interfaceEncoders, interfaceValueEncoder{i: t, ve: enc}) +	default: +		rb.typeEncoders[t] = enc +	} +	return rb +} + +// RegisterDecoder registers the provided type and decoder pair. +// +// Deprecated: Use RegisterTypeDecoder or RegisterHookDecoder instead. +func (rb *RegistryBuilder) RegisterDecoder(t reflect.Type, dec ValueDecoder) *RegistryBuilder { +	if t == nil { +		rb.typeDecoders[nil] = dec +		return rb +	} +	if t == tEmpty { +		rb.typeDecoders[t] = dec +		return rb +	} +	switch t.Kind() { +	case reflect.Interface: +		for idx, ir := range rb.interfaceDecoders { +			if ir.i == t { +				rb.interfaceDecoders[idx].vd = dec +				return rb +			} +		} + +		rb.interfaceDecoders = append(rb.interfaceDecoders, interfaceValueDecoder{i: t, vd: dec}) +	default: +		rb.typeDecoders[t] = dec +	} +	return rb +} + +// RegisterDefaultEncoder will registr the provided ValueEncoder to the provided +// kind. +func (rb *RegistryBuilder) RegisterDefaultEncoder(kind reflect.Kind, enc ValueEncoder) *RegistryBuilder { +	rb.kindEncoders[kind] = enc +	return rb +} + +// RegisterDefaultDecoder will register the provided ValueDecoder to the +// provided kind. +func (rb *RegistryBuilder) RegisterDefaultDecoder(kind reflect.Kind, dec ValueDecoder) *RegistryBuilder { +	rb.kindDecoders[kind] = dec +	return rb +} + +// RegisterTypeMapEntry will register the provided type to the BSON type. The primary usage for this +// mapping is decoding situations where an empty interface is used and a default type needs to be +// created and decoded into. +// +// By default, BSON documents will decode into interface{} values as bson.D. To change the default type for BSON +// documents, a type map entry for bsontype.EmbeddedDocument should be registered. For example, to force BSON documents +// to decode to bson.Raw, use the following code: +// +//	rb.RegisterTypeMapEntry(bsontype.EmbeddedDocument, reflect.TypeOf(bson.Raw{})) +func (rb *RegistryBuilder) RegisterTypeMapEntry(bt bsontype.Type, rt reflect.Type) *RegistryBuilder { +	rb.typeMap[bt] = rt +	return rb +} + +// Build creates a Registry from the current state of this RegistryBuilder. +func (rb *RegistryBuilder) Build() *Registry { +	registry := new(Registry) + +	registry.typeEncoders = make(map[reflect.Type]ValueEncoder) +	for t, enc := range rb.typeEncoders { +		registry.typeEncoders[t] = enc +	} + +	registry.typeDecoders = make(map[reflect.Type]ValueDecoder) +	for t, dec := range rb.typeDecoders { +		registry.typeDecoders[t] = dec +	} + +	registry.interfaceEncoders = make([]interfaceValueEncoder, len(rb.interfaceEncoders)) +	copy(registry.interfaceEncoders, rb.interfaceEncoders) + +	registry.interfaceDecoders = make([]interfaceValueDecoder, len(rb.interfaceDecoders)) +	copy(registry.interfaceDecoders, rb.interfaceDecoders) + +	registry.kindEncoders = make(map[reflect.Kind]ValueEncoder) +	for kind, enc := range rb.kindEncoders { +		registry.kindEncoders[kind] = enc +	} + +	registry.kindDecoders = make(map[reflect.Kind]ValueDecoder) +	for kind, dec := range rb.kindDecoders { +		registry.kindDecoders[kind] = dec +	} + +	registry.typeMap = make(map[bsontype.Type]reflect.Type) +	for bt, rt := range rb.typeMap { +		registry.typeMap[bt] = rt +	} + +	return registry +} + +// LookupEncoder inspects the registry for an encoder for the given type. The lookup precedence works as follows: +// +// 1. An encoder registered for the exact type. If the given type represents an interface, an encoder registered using +// RegisterTypeEncoder for the interface will be selected. +// +// 2. An encoder registered using RegisterHookEncoder for an interface implemented by the type or by a pointer to the +// type. +// +// 3. An encoder registered for the reflect.Kind of the value. +// +// If no encoder is found, an error of type ErrNoEncoder is returned. +func (r *Registry) LookupEncoder(t reflect.Type) (ValueEncoder, error) { +	encodererr := ErrNoEncoder{Type: t} +	r.mu.RLock() +	enc, found := r.lookupTypeEncoder(t) +	r.mu.RUnlock() +	if found { +		if enc == nil { +			return nil, ErrNoEncoder{Type: t} +		} +		return enc, nil +	} + +	enc, found = r.lookupInterfaceEncoder(t, true) +	if found { +		r.mu.Lock() +		r.typeEncoders[t] = enc +		r.mu.Unlock() +		return enc, nil +	} + +	if t == nil { +		r.mu.Lock() +		r.typeEncoders[t] = nil +		r.mu.Unlock() +		return nil, encodererr +	} + +	enc, found = r.kindEncoders[t.Kind()] +	if !found { +		r.mu.Lock() +		r.typeEncoders[t] = nil +		r.mu.Unlock() +		return nil, encodererr +	} + +	r.mu.Lock() +	r.typeEncoders[t] = enc +	r.mu.Unlock() +	return enc, nil +} + +func (r *Registry) lookupTypeEncoder(t reflect.Type) (ValueEncoder, bool) { +	enc, found := r.typeEncoders[t] +	return enc, found +} + +func (r *Registry) lookupInterfaceEncoder(t reflect.Type, allowAddr bool) (ValueEncoder, bool) { +	if t == nil { +		return nil, false +	} +	for _, ienc := range r.interfaceEncoders { +		if t.Implements(ienc.i) { +			return ienc.ve, true +		} +		if allowAddr && t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(ienc.i) { +			// if *t implements an interface, this will catch if t implements an interface further ahead +			// in interfaceEncoders +			defaultEnc, found := r.lookupInterfaceEncoder(t, false) +			if !found { +				defaultEnc = r.kindEncoders[t.Kind()] +			} +			return newCondAddrEncoder(ienc.ve, defaultEnc), true +		} +	} +	return nil, false +} + +// LookupDecoder inspects the registry for an decoder for the given type. The lookup precedence works as follows: +// +// 1. A decoder registered for the exact type. If the given type represents an interface, a decoder registered using +// RegisterTypeDecoder for the interface will be selected. +// +// 2. A decoder registered using RegisterHookDecoder for an interface implemented by the type or by a pointer to the +// type. +// +// 3. A decoder registered for the reflect.Kind of the value. +// +// If no decoder is found, an error of type ErrNoDecoder is returned. +func (r *Registry) LookupDecoder(t reflect.Type) (ValueDecoder, error) { +	if t == nil { +		return nil, ErrNilType +	} +	decodererr := ErrNoDecoder{Type: t} +	r.mu.RLock() +	dec, found := r.lookupTypeDecoder(t) +	r.mu.RUnlock() +	if found { +		if dec == nil { +			return nil, ErrNoDecoder{Type: t} +		} +		return dec, nil +	} + +	dec, found = r.lookupInterfaceDecoder(t, true) +	if found { +		r.mu.Lock() +		r.typeDecoders[t] = dec +		r.mu.Unlock() +		return dec, nil +	} + +	dec, found = r.kindDecoders[t.Kind()] +	if !found { +		r.mu.Lock() +		r.typeDecoders[t] = nil +		r.mu.Unlock() +		return nil, decodererr +	} + +	r.mu.Lock() +	r.typeDecoders[t] = dec +	r.mu.Unlock() +	return dec, nil +} + +func (r *Registry) lookupTypeDecoder(t reflect.Type) (ValueDecoder, bool) { +	dec, found := r.typeDecoders[t] +	return dec, found +} + +func (r *Registry) lookupInterfaceDecoder(t reflect.Type, allowAddr bool) (ValueDecoder, bool) { +	for _, idec := range r.interfaceDecoders { +		if t.Implements(idec.i) { +			return idec.vd, true +		} +		if allowAddr && t.Kind() != reflect.Ptr && reflect.PtrTo(t).Implements(idec.i) { +			// if *t implements an interface, this will catch if t implements an interface further ahead +			// in interfaceDecoders +			defaultDec, found := r.lookupInterfaceDecoder(t, false) +			if !found { +				defaultDec = r.kindDecoders[t.Kind()] +			} +			return newCondAddrDecoder(idec.vd, defaultDec), true +		} +	} +	return nil, false +} + +// LookupTypeMapEntry inspects the registry's type map for a Go type for the corresponding BSON +// type. If no type is found, ErrNoTypeMapEntry is returned. +func (r *Registry) LookupTypeMapEntry(bt bsontype.Type) (reflect.Type, error) { +	t, ok := r.typeMap[bt] +	if !ok || t == nil { +		return nil, ErrNoTypeMapEntry{Type: bt} +	} +	return t, nil +} + +type interfaceValueEncoder struct { +	i  reflect.Type +	ve ValueEncoder +} + +type interfaceValueDecoder struct { +	i  reflect.Type +	vd ValueDecoder +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go new file mode 100644 index 000000000..3c1b6b860 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go @@ -0,0 +1,199 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"fmt" +	"reflect" + +	"go.mongodb.org/mongo-driver/bson/bsonoptions" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +var defaultSliceCodec = NewSliceCodec() + +// SliceCodec is the Codec used for slice values. +type SliceCodec struct { +	EncodeNilAsEmpty bool +} + +var _ ValueCodec = &MapCodec{} + +// NewSliceCodec returns a MapCodec with options opts. +func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec { +	sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...) + +	codec := SliceCodec{} +	if sliceOpt.EncodeNilAsEmpty != nil { +		codec.EncodeNilAsEmpty = *sliceOpt.EncodeNilAsEmpty +	} +	return &codec +} + +// EncodeValue is the ValueEncoder for slice types. +func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Kind() != reflect.Slice { +		return ValueEncoderError{Name: "SliceEncodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} +	} + +	if val.IsNil() && !sc.EncodeNilAsEmpty { +		return vw.WriteNull() +	} + +	// If we have a []byte we want to treat it as a binary instead of as an array. +	if val.Type().Elem() == tByte { +		var byteSlice []byte +		for idx := 0; idx < val.Len(); idx++ { +			byteSlice = append(byteSlice, val.Index(idx).Interface().(byte)) +		} +		return vw.WriteBinary(byteSlice) +	} + +	// If we have a []primitive.E we want to treat it as a document instead of as an array. +	if val.Type().ConvertibleTo(tD) { +		d := val.Convert(tD).Interface().(primitive.D) + +		dw, err := vw.WriteDocument() +		if err != nil { +			return err +		} + +		for _, e := range d { +			err = encodeElement(ec, dw, e) +			if err != nil { +				return err +			} +		} + +		return dw.WriteDocumentEnd() +	} + +	aw, err := vw.WriteArray() +	if err != nil { +		return err +	} + +	elemType := val.Type().Elem() +	encoder, err := ec.LookupEncoder(elemType) +	if err != nil && elemType.Kind() != reflect.Interface { +		return err +	} + +	for idx := 0; idx < val.Len(); idx++ { +		currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx)) +		if lookupErr != nil && lookupErr != errInvalidValue { +			return lookupErr +		} + +		vw, err := aw.WriteArrayElement() +		if err != nil { +			return err +		} + +		if lookupErr == errInvalidValue { +			err = vw.WriteNull() +			if err != nil { +				return err +			} +			continue +		} + +		err = currEncoder.EncodeValue(ec, vw, currVal) +		if err != nil { +			return err +		} +	} +	return aw.WriteArrayEnd() +} + +// DecodeValue is the ValueDecoder for slice types. +func (sc *SliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Kind() != reflect.Slice { +		return ValueDecoderError{Name: "SliceDecodeValue", Kinds: []reflect.Kind{reflect.Slice}, Received: val} +	} + +	switch vrType := vr.Type(); vrType { +	case bsontype.Array: +	case bsontype.Null: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadNull() +	case bsontype.Undefined: +		val.Set(reflect.Zero(val.Type())) +		return vr.ReadUndefined() +	case bsontype.Type(0), bsontype.EmbeddedDocument: +		if val.Type().Elem() != tE { +			return fmt.Errorf("cannot decode document into %s", val.Type()) +		} +	case bsontype.Binary: +		if val.Type().Elem() != tByte { +			return fmt.Errorf("SliceDecodeValue can only decode a binary into a byte array, got %v", vrType) +		} +		data, subtype, err := vr.ReadBinary() +		if err != nil { +			return err +		} +		if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { +			return fmt.Errorf("SliceDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype) +		} + +		if val.IsNil() { +			val.Set(reflect.MakeSlice(val.Type(), 0, len(data))) +		} + +		val.SetLen(0) +		for _, elem := range data { +			val.Set(reflect.Append(val, reflect.ValueOf(elem))) +		} +		return nil +	case bsontype.String: +		if sliceType := val.Type().Elem(); sliceType != tByte { +			return fmt.Errorf("SliceDecodeValue can only decode a string into a byte array, got %v", sliceType) +		} +		str, err := vr.ReadString() +		if err != nil { +			return err +		} +		byteStr := []byte(str) + +		if val.IsNil() { +			val.Set(reflect.MakeSlice(val.Type(), 0, len(byteStr))) +		} + +		val.SetLen(0) +		for _, elem := range byteStr { +			val.Set(reflect.Append(val, reflect.ValueOf(elem))) +		} +		return nil +	default: +		return fmt.Errorf("cannot decode %v into a slice", vrType) +	} + +	var elemsFunc func(DecodeContext, bsonrw.ValueReader, reflect.Value) ([]reflect.Value, error) +	switch val.Type().Elem() { +	case tE: +		dc.Ancestor = val.Type() +		elemsFunc = defaultValueDecoders.decodeD +	default: +		elemsFunc = defaultValueDecoders.decodeDefault +	} + +	elems, err := elemsFunc(dc, vr, val) +	if err != nil { +		return err +	} + +	if val.IsNil() { +		val.Set(reflect.MakeSlice(val.Type(), 0, len(elems))) +	} + +	val.SetLen(0) +	val.Set(reflect.Append(val, elems...)) + +	return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go new file mode 100644 index 000000000..5332b7c3b --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go @@ -0,0 +1,119 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"fmt" +	"reflect" + +	"go.mongodb.org/mongo-driver/bson/bsonoptions" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +// StringCodec is the Codec used for struct values. +type StringCodec struct { +	DecodeObjectIDAsHex bool +} + +var ( +	defaultStringCodec = NewStringCodec() + +	_ ValueCodec  = defaultStringCodec +	_ typeDecoder = defaultStringCodec +) + +// NewStringCodec returns a StringCodec with options opts. +func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec { +	stringOpt := bsonoptions.MergeStringCodecOptions(opts...) +	return &StringCodec{*stringOpt.DecodeObjectIDAsHex} +} + +// EncodeValue is the ValueEncoder for string types. +func (sc *StringCodec) EncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if val.Kind() != reflect.String { +		return ValueEncoderError{ +			Name:     "StringEncodeValue", +			Kinds:    []reflect.Kind{reflect.String}, +			Received: val, +		} +	} + +	return vw.WriteString(val.String()) +} + +func (sc *StringCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t.Kind() != reflect.String { +		return emptyValue, ValueDecoderError{ +			Name:     "StringDecodeValue", +			Kinds:    []reflect.Kind{reflect.String}, +			Received: reflect.Zero(t), +		} +	} + +	var str string +	var err error +	switch vr.Type() { +	case bsontype.String: +		str, err = vr.ReadString() +		if err != nil { +			return emptyValue, err +		} +	case bsontype.ObjectID: +		oid, err := vr.ReadObjectID() +		if err != nil { +			return emptyValue, err +		} +		if sc.DecodeObjectIDAsHex { +			str = oid.Hex() +		} else { +			byteArray := [12]byte(oid) +			str = string(byteArray[:]) +		} +	case bsontype.Symbol: +		str, err = vr.ReadSymbol() +		if err != nil { +			return emptyValue, err +		} +	case bsontype.Binary: +		data, subtype, err := vr.ReadBinary() +		if err != nil { +			return emptyValue, err +		} +		if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld { +			return emptyValue, decodeBinaryError{subtype: subtype, typeName: "string"} +		} +		str = string(data) +	case bsontype.Null: +		if err = vr.ReadNull(); err != nil { +			return emptyValue, err +		} +	case bsontype.Undefined: +		if err = vr.ReadUndefined(); err != nil { +			return emptyValue, err +		} +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a string type", vr.Type()) +	} + +	return reflect.ValueOf(str), nil +} + +// DecodeValue is the ValueDecoder for string types. +func (sc *StringCodec) DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Kind() != reflect.String { +		return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val} +	} + +	elem, err := sc.decodeType(dctx, vr, val.Type()) +	if err != nil { +		return err +	} + +	val.SetString(elem.String()) +	return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go new file mode 100644 index 000000000..be3f2081e --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go @@ -0,0 +1,664 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"errors" +	"fmt" +	"reflect" +	"sort" +	"strings" +	"sync" +	"time" + +	"go.mongodb.org/mongo-driver/bson/bsonoptions" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +// DecodeError represents an error that occurs when unmarshalling BSON bytes into a native Go type. +type DecodeError struct { +	keys    []string +	wrapped error +} + +// Unwrap returns the underlying error +func (de *DecodeError) Unwrap() error { +	return de.wrapped +} + +// Error implements the error interface. +func (de *DecodeError) Error() string { +	// The keys are stored in reverse order because the de.keys slice is builtup while propagating the error up the +	// stack of BSON keys, so we call de.Keys(), which reverses them. +	keyPath := strings.Join(de.Keys(), ".") +	return fmt.Sprintf("error decoding key %s: %v", keyPath, de.wrapped) +} + +// Keys returns the BSON key path that caused an error as a slice of strings. The keys in the slice are in top-down +// order. For example, if the document being unmarshalled was {a: {b: {c: 1}}} and the value for c was supposed to be +// a string, the keys slice will be ["a", "b", "c"]. +func (de *DecodeError) Keys() []string { +	reversedKeys := make([]string, 0, len(de.keys)) +	for idx := len(de.keys) - 1; idx >= 0; idx-- { +		reversedKeys = append(reversedKeys, de.keys[idx]) +	} + +	return reversedKeys +} + +// Zeroer allows custom struct types to implement a report of zero +// state. All struct types that don't implement Zeroer or where IsZero +// returns false are considered to be not zero. +type Zeroer interface { +	IsZero() bool +} + +// StructCodec is the Codec used for struct values. +type StructCodec struct { +	cache                            map[reflect.Type]*structDescription +	l                                sync.RWMutex +	parser                           StructTagParser +	DecodeZeroStruct                 bool +	DecodeDeepZeroInline             bool +	EncodeOmitDefaultStruct          bool +	AllowUnexportedFields            bool +	OverwriteDuplicatedInlinedFields bool +} + +var _ ValueEncoder = &StructCodec{} +var _ ValueDecoder = &StructCodec{} + +// NewStructCodec returns a StructCodec that uses p for struct tag parsing. +func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) (*StructCodec, error) { +	if p == nil { +		return nil, errors.New("a StructTagParser must be provided to NewStructCodec") +	} + +	structOpt := bsonoptions.MergeStructCodecOptions(opts...) + +	codec := &StructCodec{ +		cache:  make(map[reflect.Type]*structDescription), +		parser: p, +	} + +	if structOpt.DecodeZeroStruct != nil { +		codec.DecodeZeroStruct = *structOpt.DecodeZeroStruct +	} +	if structOpt.DecodeDeepZeroInline != nil { +		codec.DecodeDeepZeroInline = *structOpt.DecodeDeepZeroInline +	} +	if structOpt.EncodeOmitDefaultStruct != nil { +		codec.EncodeOmitDefaultStruct = *structOpt.EncodeOmitDefaultStruct +	} +	if structOpt.OverwriteDuplicatedInlinedFields != nil { +		codec.OverwriteDuplicatedInlinedFields = *structOpt.OverwriteDuplicatedInlinedFields +	} +	if structOpt.AllowUnexportedFields != nil { +		codec.AllowUnexportedFields = *structOpt.AllowUnexportedFields +	} + +	return codec, nil +} + +// EncodeValue handles encoding generic struct types. +func (sc *StructCodec) EncodeValue(r EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Kind() != reflect.Struct { +		return ValueEncoderError{Name: "StructCodec.EncodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val} +	} + +	sd, err := sc.describeStruct(r.Registry, val.Type()) +	if err != nil { +		return err +	} + +	dw, err := vw.WriteDocument() +	if err != nil { +		return err +	} +	var rv reflect.Value +	for _, desc := range sd.fl { +		if desc.inline == nil { +			rv = val.Field(desc.idx) +		} else { +			rv, err = fieldByIndexErr(val, desc.inline) +			if err != nil { +				continue +			} +		} + +		desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(r, desc.encoder, rv) + +		if err != nil && err != errInvalidValue { +			return err +		} + +		if err == errInvalidValue { +			if desc.omitEmpty { +				continue +			} +			vw2, err := dw.WriteDocumentElement(desc.name) +			if err != nil { +				return err +			} +			err = vw2.WriteNull() +			if err != nil { +				return err +			} +			continue +		} + +		if desc.encoder == nil { +			return ErrNoEncoder{Type: rv.Type()} +		} + +		encoder := desc.encoder + +		var isZero bool +		rvInterface := rv.Interface() +		if cz, ok := encoder.(CodecZeroer); ok { +			isZero = cz.IsTypeZero(rvInterface) +		} else if rv.Kind() == reflect.Interface { +			// sc.isZero will not treat an interface rv as an interface, so we need to check for the zero interface separately. +			isZero = rv.IsNil() +		} else { +			isZero = sc.isZero(rvInterface) +		} +		if desc.omitEmpty && isZero { +			continue +		} + +		vw2, err := dw.WriteDocumentElement(desc.name) +		if err != nil { +			return err +		} + +		ectx := EncodeContext{Registry: r.Registry, MinSize: desc.minSize} +		err = encoder.EncodeValue(ectx, vw2, rv) +		if err != nil { +			return err +		} +	} + +	if sd.inlineMap >= 0 { +		rv := val.Field(sd.inlineMap) +		collisionFn := func(key string) bool { +			_, exists := sd.fm[key] +			return exists +		} + +		return defaultMapCodec.mapEncodeValue(r, dw, rv, collisionFn) +	} + +	return dw.WriteDocumentEnd() +} + +func newDecodeError(key string, original error) error { +	de, ok := original.(*DecodeError) +	if !ok { +		return &DecodeError{ +			keys:    []string{key}, +			wrapped: original, +		} +	} + +	de.keys = append(de.keys, key) +	return de +} + +// DecodeValue implements the Codec interface. +// By default, map types in val will not be cleared. If a map has existing key/value pairs, it will be extended with the new ones from vr. +// For slices, the decoder will set the length of the slice to zero and append all elements. The underlying array will not be cleared. +func (sc *StructCodec) DecodeValue(r DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Kind() != reflect.Struct { +		return ValueDecoderError{Name: "StructCodec.DecodeValue", Kinds: []reflect.Kind{reflect.Struct}, Received: val} +	} + +	switch vrType := vr.Type(); vrType { +	case bsontype.Type(0), bsontype.EmbeddedDocument: +	case bsontype.Null: +		if err := vr.ReadNull(); err != nil { +			return err +		} + +		val.Set(reflect.Zero(val.Type())) +		return nil +	case bsontype.Undefined: +		if err := vr.ReadUndefined(); err != nil { +			return err +		} + +		val.Set(reflect.Zero(val.Type())) +		return nil +	default: +		return fmt.Errorf("cannot decode %v into a %s", vrType, val.Type()) +	} + +	sd, err := sc.describeStruct(r.Registry, val.Type()) +	if err != nil { +		return err +	} + +	if sc.DecodeZeroStruct { +		val.Set(reflect.Zero(val.Type())) +	} +	if sc.DecodeDeepZeroInline && sd.inline { +		val.Set(deepZero(val.Type())) +	} + +	var decoder ValueDecoder +	var inlineMap reflect.Value +	if sd.inlineMap >= 0 { +		inlineMap = val.Field(sd.inlineMap) +		decoder, err = r.LookupDecoder(inlineMap.Type().Elem()) +		if err != nil { +			return err +		} +	} + +	dr, err := vr.ReadDocument() +	if err != nil { +		return err +	} + +	for { +		name, vr, err := dr.ReadElement() +		if err == bsonrw.ErrEOD { +			break +		} +		if err != nil { +			return err +		} + +		fd, exists := sd.fm[name] +		if !exists { +			// if the original name isn't found in the struct description, try again with the name in lowercase +			// this could match if a BSON tag isn't specified because by default, describeStruct lowercases all field +			// names +			fd, exists = sd.fm[strings.ToLower(name)] +		} + +		if !exists { +			if sd.inlineMap < 0 { +				// The encoding/json package requires a flag to return on error for non-existent fields. +				// This functionality seems appropriate for the struct codec. +				err = vr.Skip() +				if err != nil { +					return err +				} +				continue +			} + +			if inlineMap.IsNil() { +				inlineMap.Set(reflect.MakeMap(inlineMap.Type())) +			} + +			elem := reflect.New(inlineMap.Type().Elem()).Elem() +			r.Ancestor = inlineMap.Type() +			err = decoder.DecodeValue(r, vr, elem) +			if err != nil { +				return err +			} +			inlineMap.SetMapIndex(reflect.ValueOf(name), elem) +			continue +		} + +		var field reflect.Value +		if fd.inline == nil { +			field = val.Field(fd.idx) +		} else { +			field, err = getInlineField(val, fd.inline) +			if err != nil { +				return err +			} +		} + +		if !field.CanSet() { // Being settable is a super set of being addressable. +			innerErr := fmt.Errorf("field %v is not settable", field) +			return newDecodeError(fd.name, innerErr) +		} +		if field.Kind() == reflect.Ptr && field.IsNil() { +			field.Set(reflect.New(field.Type().Elem())) +		} +		field = field.Addr() + +		dctx := DecodeContext{Registry: r.Registry, Truncate: fd.truncate || r.Truncate} +		if fd.decoder == nil { +			return newDecodeError(fd.name, ErrNoDecoder{Type: field.Elem().Type()}) +		} + +		err = fd.decoder.DecodeValue(dctx, vr, field.Elem()) +		if err != nil { +			return newDecodeError(fd.name, err) +		} +	} + +	return nil +} + +func (sc *StructCodec) isZero(i interface{}) bool { +	v := reflect.ValueOf(i) + +	// check the value validity +	if !v.IsValid() { +		return true +	} + +	if z, ok := v.Interface().(Zeroer); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) { +		return z.IsZero() +	} + +	switch v.Kind() { +	case reflect.Array, reflect.Map, reflect.Slice, reflect.String: +		return v.Len() == 0 +	case reflect.Bool: +		return !v.Bool() +	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: +		return v.Int() == 0 +	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: +		return v.Uint() == 0 +	case reflect.Float32, reflect.Float64: +		return v.Float() == 0 +	case reflect.Interface, reflect.Ptr: +		return v.IsNil() +	case reflect.Struct: +		if sc.EncodeOmitDefaultStruct { +			vt := v.Type() +			if vt == tTime { +				return v.Interface().(time.Time).IsZero() +			} +			for i := 0; i < v.NumField(); i++ { +				if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous { +					continue // Private field +				} +				fld := v.Field(i) +				if !sc.isZero(fld.Interface()) { +					return false +				} +			} +			return true +		} +	} + +	return false +} + +type structDescription struct { +	fm        map[string]fieldDescription +	fl        []fieldDescription +	inlineMap int +	inline    bool +} + +type fieldDescription struct { +	name      string // BSON key name +	fieldName string // struct field name +	idx       int +	omitEmpty bool +	minSize   bool +	truncate  bool +	inline    []int +	encoder   ValueEncoder +	decoder   ValueDecoder +} + +type byIndex []fieldDescription + +func (bi byIndex) Len() int { return len(bi) } + +func (bi byIndex) Swap(i, j int) { bi[i], bi[j] = bi[j], bi[i] } + +func (bi byIndex) Less(i, j int) bool { +	// If a field is inlined, its index in the top level struct is stored at inline[0] +	iIdx, jIdx := bi[i].idx, bi[j].idx +	if len(bi[i].inline) > 0 { +		iIdx = bi[i].inline[0] +	} +	if len(bi[j].inline) > 0 { +		jIdx = bi[j].inline[0] +	} +	if iIdx != jIdx { +		return iIdx < jIdx +	} +	for k, biik := range bi[i].inline { +		if k >= len(bi[j].inline) { +			return false +		} +		if biik != bi[j].inline[k] { +			return biik < bi[j].inline[k] +		} +	} +	return len(bi[i].inline) < len(bi[j].inline) +} + +func (sc *StructCodec) describeStruct(r *Registry, t reflect.Type) (*structDescription, error) { +	// We need to analyze the struct, including getting the tags, collecting +	// information about inlining, and create a map of the field name to the field. +	sc.l.RLock() +	ds, exists := sc.cache[t] +	sc.l.RUnlock() +	if exists { +		return ds, nil +	} + +	numFields := t.NumField() +	sd := &structDescription{ +		fm:        make(map[string]fieldDescription, numFields), +		fl:        make([]fieldDescription, 0, numFields), +		inlineMap: -1, +	} + +	var fields []fieldDescription +	for i := 0; i < numFields; i++ { +		sf := t.Field(i) +		if sf.PkgPath != "" && (!sc.AllowUnexportedFields || !sf.Anonymous) { +			// field is private or unexported fields aren't allowed, ignore +			continue +		} + +		sfType := sf.Type +		encoder, err := r.LookupEncoder(sfType) +		if err != nil { +			encoder = nil +		} +		decoder, err := r.LookupDecoder(sfType) +		if err != nil { +			decoder = nil +		} + +		description := fieldDescription{ +			fieldName: sf.Name, +			idx:       i, +			encoder:   encoder, +			decoder:   decoder, +		} + +		stags, err := sc.parser.ParseStructTags(sf) +		if err != nil { +			return nil, err +		} +		if stags.Skip { +			continue +		} +		description.name = stags.Name +		description.omitEmpty = stags.OmitEmpty +		description.minSize = stags.MinSize +		description.truncate = stags.Truncate + +		if stags.Inline { +			sd.inline = true +			switch sfType.Kind() { +			case reflect.Map: +				if sd.inlineMap >= 0 { +					return nil, errors.New("(struct " + t.String() + ") multiple inline maps") +				} +				if sfType.Key() != tString { +					return nil, errors.New("(struct " + t.String() + ") inline map must have a string keys") +				} +				sd.inlineMap = description.idx +			case reflect.Ptr: +				sfType = sfType.Elem() +				if sfType.Kind() != reflect.Struct { +					return nil, fmt.Errorf("(struct %s) inline fields must be a struct, a struct pointer, or a map", t.String()) +				} +				fallthrough +			case reflect.Struct: +				inlinesf, err := sc.describeStruct(r, sfType) +				if err != nil { +					return nil, err +				} +				for _, fd := range inlinesf.fl { +					if fd.inline == nil { +						fd.inline = []int{i, fd.idx} +					} else { +						fd.inline = append([]int{i}, fd.inline...) +					} +					fields = append(fields, fd) + +				} +			default: +				return nil, fmt.Errorf("(struct %s) inline fields must be a struct, a struct pointer, or a map", t.String()) +			} +			continue +		} +		fields = append(fields, description) +	} + +	// Sort fieldDescriptions by name and use dominance rules to determine which should be added for each name +	sort.Slice(fields, func(i, j int) bool { +		x := fields +		// sort field by name, breaking ties with depth, then +		// breaking ties with index sequence. +		if x[i].name != x[j].name { +			return x[i].name < x[j].name +		} +		if len(x[i].inline) != len(x[j].inline) { +			return len(x[i].inline) < len(x[j].inline) +		} +		return byIndex(x).Less(i, j) +	}) + +	for advance, i := 0, 0; i < len(fields); i += advance { +		// One iteration per name. +		// Find the sequence of fields with the name of this first field. +		fi := fields[i] +		name := fi.name +		for advance = 1; i+advance < len(fields); advance++ { +			fj := fields[i+advance] +			if fj.name != name { +				break +			} +		} +		if advance == 1 { // Only one field with this name +			sd.fl = append(sd.fl, fi) +			sd.fm[name] = fi +			continue +		} +		dominant, ok := dominantField(fields[i : i+advance]) +		if !ok || !sc.OverwriteDuplicatedInlinedFields { +			return nil, fmt.Errorf("struct %s has duplicated key %s", t.String(), name) +		} +		sd.fl = append(sd.fl, dominant) +		sd.fm[name] = dominant +	} + +	sort.Sort(byIndex(sd.fl)) + +	sc.l.Lock() +	sc.cache[t] = sd +	sc.l.Unlock() + +	return sd, nil +} + +// dominantField looks through the fields, all of which are known to +// have the same name, to find the single field that dominates the +// others using Go's inlining rules. If there are multiple top-level +// fields, the boolean will be false: This condition is an error in Go +// and we skip all the fields. +func dominantField(fields []fieldDescription) (fieldDescription, bool) { +	// The fields are sorted in increasing index-length order, then by presence of tag. +	// That means that the first field is the dominant one. We need only check +	// for error cases: two fields at top level. +	if len(fields) > 1 && +		len(fields[0].inline) == len(fields[1].inline) { +		return fieldDescription{}, false +	} +	return fields[0], true +} + +func fieldByIndexErr(v reflect.Value, index []int) (result reflect.Value, err error) { +	defer func() { +		if recovered := recover(); recovered != nil { +			switch r := recovered.(type) { +			case string: +				err = fmt.Errorf("%s", r) +			case error: +				err = r +			} +		} +	}() + +	result = v.FieldByIndex(index) +	return +} + +func getInlineField(val reflect.Value, index []int) (reflect.Value, error) { +	field, err := fieldByIndexErr(val, index) +	if err == nil { +		return field, nil +	} + +	// if parent of this element doesn't exist, fix its parent +	inlineParent := index[:len(index)-1] +	var fParent reflect.Value +	if fParent, err = fieldByIndexErr(val, inlineParent); err != nil { +		fParent, err = getInlineField(val, inlineParent) +		if err != nil { +			return fParent, err +		} +	} +	fParent.Set(reflect.New(fParent.Type().Elem())) + +	return fieldByIndexErr(val, index) +} + +// DeepZero returns recursive zero object +func deepZero(st reflect.Type) (result reflect.Value) { +	result = reflect.Indirect(reflect.New(st)) + +	if result.Kind() == reflect.Struct { +		for i := 0; i < result.NumField(); i++ { +			if f := result.Field(i); f.Kind() == reflect.Ptr { +				if f.CanInterface() { +					if ft := reflect.TypeOf(f.Interface()); ft.Elem().Kind() == reflect.Struct { +						result.Field(i).Set(recursivePointerTo(deepZero(ft.Elem()))) +					} +				} +			} +		} +	} + +	return +} + +// recursivePointerTo calls reflect.New(v.Type) but recursively for its fields inside +func recursivePointerTo(v reflect.Value) reflect.Value { +	v = reflect.Indirect(v) +	result := reflect.New(v.Type()) +	if v.Kind() == reflect.Struct { +		for i := 0; i < v.NumField(); i++ { +			if f := v.Field(i); f.Kind() == reflect.Ptr { +				if f.Elem().Kind() == reflect.Struct { +					result.Elem().Field(i).Set(recursivePointerTo(f)) +				} +			} +		} +	} + +	return result +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go new file mode 100644 index 000000000..62708c5c7 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_tag_parser.go @@ -0,0 +1,139 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"reflect" +	"strings" +) + +// StructTagParser returns the struct tags for a given struct field. +type StructTagParser interface { +	ParseStructTags(reflect.StructField) (StructTags, error) +} + +// StructTagParserFunc is an adapter that allows a generic function to be used +// as a StructTagParser. +type StructTagParserFunc func(reflect.StructField) (StructTags, error) + +// ParseStructTags implements the StructTagParser interface. +func (stpf StructTagParserFunc) ParseStructTags(sf reflect.StructField) (StructTags, error) { +	return stpf(sf) +} + +// StructTags represents the struct tag fields that the StructCodec uses during +// the encoding and decoding process. +// +// In the case of a struct, the lowercased field name is used as the key for each exported +// field but this behavior may be changed using a struct tag. The tag may also contain flags to +// adjust the marshalling behavior for the field. +// +// The properties are defined below: +// +//	OmitEmpty  Only include the field if it's not set to the zero value for the type or to +//	           empty slices or maps. +// +//	MinSize    Marshal an integer of a type larger than 32 bits value as an int32, if that's +//	           feasible while preserving the numeric value. +// +//	Truncate   When unmarshaling a BSON double, it is permitted to lose precision to fit within +//	           a float32. +// +//	Inline     Inline the field, which must be a struct or a map, causing all of its fields +//	           or keys to be processed as if they were part of the outer struct. For maps, +//	           keys must not conflict with the bson keys of other struct fields. +// +//	Skip       This struct field should be skipped. This is usually denoted by parsing a "-" +//	           for the name. +// +// TODO(skriptble): Add tags for undefined as nil and for null as nil. +type StructTags struct { +	Name      string +	OmitEmpty bool +	MinSize   bool +	Truncate  bool +	Inline    bool +	Skip      bool +} + +// DefaultStructTagParser is the StructTagParser used by the StructCodec by default. +// It will handle the bson struct tag. See the documentation for StructTags to see +// what each of the returned fields means. +// +// If there is no name in the struct tag fields, the struct field name is lowercased. +// The tag formats accepted are: +// +//	"[<key>][,<flag1>[,<flag2>]]" +// +//	`(...) bson:"[<key>][,<flag1>[,<flag2>]]" (...)` +// +// An example: +// +//	type T struct { +//	    A bool +//	    B int    "myb" +//	    C string "myc,omitempty" +//	    D string `bson:",omitempty" json:"jsonkey"` +//	    E int64  ",minsize" +//	    F int64  "myf,omitempty,minsize" +//	} +// +// A struct tag either consisting entirely of '-' or with a bson key with a +// value consisting entirely of '-' will return a StructTags with Skip true and +// the remaining fields will be their default values. +var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) { +	key := strings.ToLower(sf.Name) +	tag, ok := sf.Tag.Lookup("bson") +	if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 { +		tag = string(sf.Tag) +	} +	return parseTags(key, tag) +} + +func parseTags(key string, tag string) (StructTags, error) { +	var st StructTags +	if tag == "-" { +		st.Skip = true +		return st, nil +	} + +	for idx, str := range strings.Split(tag, ",") { +		if idx == 0 && str != "" { +			key = str +		} +		switch str { +		case "omitempty": +			st.OmitEmpty = true +		case "minsize": +			st.MinSize = true +		case "truncate": +			st.Truncate = true +		case "inline": +			st.Inline = true +		} +	} + +	st.Name = key + +	return st, nil +} + +// JSONFallbackStructTagParser has the same behavior as DefaultStructTagParser +// but will also fallback to parsing the json tag instead on a field where the +// bson tag isn't available. +var JSONFallbackStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) { +	key := strings.ToLower(sf.Name) +	tag, ok := sf.Tag.Lookup("bson") +	if !ok { +		tag, ok = sf.Tag.Lookup("json") +	} +	if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 { +		tag = string(sf.Tag) +	} + +	return parseTags(key, tag) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go new file mode 100644 index 000000000..ec7e30f72 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go @@ -0,0 +1,127 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"fmt" +	"reflect" +	"time" + +	"go.mongodb.org/mongo-driver/bson/bsonoptions" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +const ( +	timeFormatString = "2006-01-02T15:04:05.999Z07:00" +) + +// TimeCodec is the Codec used for time.Time values. +type TimeCodec struct { +	UseLocalTimeZone bool +} + +var ( +	defaultTimeCodec = NewTimeCodec() + +	_ ValueCodec  = defaultTimeCodec +	_ typeDecoder = defaultTimeCodec +) + +// NewTimeCodec returns a TimeCodec with options opts. +func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec { +	timeOpt := bsonoptions.MergeTimeCodecOptions(opts...) + +	codec := TimeCodec{} +	if timeOpt.UseLocalTimeZone != nil { +		codec.UseLocalTimeZone = *timeOpt.UseLocalTimeZone +	} +	return &codec +} + +func (tc *TimeCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	if t != tTime { +		return emptyValue, ValueDecoderError{ +			Name:     "TimeDecodeValue", +			Types:    []reflect.Type{tTime}, +			Received: reflect.Zero(t), +		} +	} + +	var timeVal time.Time +	switch vrType := vr.Type(); vrType { +	case bsontype.DateTime: +		dt, err := vr.ReadDateTime() +		if err != nil { +			return emptyValue, err +		} +		timeVal = time.Unix(dt/1000, dt%1000*1000000) +	case bsontype.String: +		// assume strings are in the isoTimeFormat +		timeStr, err := vr.ReadString() +		if err != nil { +			return emptyValue, err +		} +		timeVal, err = time.Parse(timeFormatString, timeStr) +		if err != nil { +			return emptyValue, err +		} +	case bsontype.Int64: +		i64, err := vr.ReadInt64() +		if err != nil { +			return emptyValue, err +		} +		timeVal = time.Unix(i64/1000, i64%1000*1000000) +	case bsontype.Timestamp: +		t, _, err := vr.ReadTimestamp() +		if err != nil { +			return emptyValue, err +		} +		timeVal = time.Unix(int64(t), 0) +	case bsontype.Null: +		if err := vr.ReadNull(); err != nil { +			return emptyValue, err +		} +	case bsontype.Undefined: +		if err := vr.ReadUndefined(); err != nil { +			return emptyValue, err +		} +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into a time.Time", vrType) +	} + +	if !tc.UseLocalTimeZone { +		timeVal = timeVal.UTC() +	} +	return reflect.ValueOf(timeVal), nil +} + +// DecodeValue is the ValueDecoderFunc for time.Time. +func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tTime { +		return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val} +	} + +	elem, err := tc.decodeType(dc, vr, tTime) +	if err != nil { +		return err +	} + +	val.Set(elem) +	return nil +} + +// EncodeValue is the ValueEncoderFunc for time.TIme. +func (tc *TimeCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tTime { +		return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val} +	} +	tt := val.Interface().(time.Time) +	dt := primitive.NewDateTimeFromTime(tt) +	return vw.WriteDateTime(int64(dt)) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go new file mode 100644 index 000000000..07f4b70e6 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/types.go @@ -0,0 +1,57 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"encoding/json" +	"net/url" +	"reflect" +	"time" + +	"go.mongodb.org/mongo-driver/bson/primitive" +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +var tBool = reflect.TypeOf(false) +var tFloat64 = reflect.TypeOf(float64(0)) +var tInt32 = reflect.TypeOf(int32(0)) +var tInt64 = reflect.TypeOf(int64(0)) +var tString = reflect.TypeOf("") +var tTime = reflect.TypeOf(time.Time{}) + +var tEmpty = reflect.TypeOf((*interface{})(nil)).Elem() +var tByteSlice = reflect.TypeOf([]byte(nil)) +var tByte = reflect.TypeOf(byte(0x00)) +var tURL = reflect.TypeOf(url.URL{}) +var tJSONNumber = reflect.TypeOf(json.Number("")) + +var tValueMarshaler = reflect.TypeOf((*ValueMarshaler)(nil)).Elem() +var tValueUnmarshaler = reflect.TypeOf((*ValueUnmarshaler)(nil)).Elem() +var tMarshaler = reflect.TypeOf((*Marshaler)(nil)).Elem() +var tUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem() +var tProxy = reflect.TypeOf((*Proxy)(nil)).Elem() + +var tBinary = reflect.TypeOf(primitive.Binary{}) +var tUndefined = reflect.TypeOf(primitive.Undefined{}) +var tOID = reflect.TypeOf(primitive.ObjectID{}) +var tDateTime = reflect.TypeOf(primitive.DateTime(0)) +var tNull = reflect.TypeOf(primitive.Null{}) +var tRegex = reflect.TypeOf(primitive.Regex{}) +var tCodeWithScope = reflect.TypeOf(primitive.CodeWithScope{}) +var tDBPointer = reflect.TypeOf(primitive.DBPointer{}) +var tJavaScript = reflect.TypeOf(primitive.JavaScript("")) +var tSymbol = reflect.TypeOf(primitive.Symbol("")) +var tTimestamp = reflect.TypeOf(primitive.Timestamp{}) +var tDecimal = reflect.TypeOf(primitive.Decimal128{}) +var tMinKey = reflect.TypeOf(primitive.MinKey{}) +var tMaxKey = reflect.TypeOf(primitive.MaxKey{}) +var tD = reflect.TypeOf(primitive.D{}) +var tA = reflect.TypeOf(primitive.A{}) +var tE = reflect.TypeOf(primitive.E{}) + +var tCoreDocument = reflect.TypeOf(bsoncore.Document{}) +var tCoreArray = reflect.TypeOf(bsoncore.Array{}) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go new file mode 100644 index 000000000..0b21ce999 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go @@ -0,0 +1,173 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsoncodec + +import ( +	"fmt" +	"math" +	"reflect" + +	"go.mongodb.org/mongo-driver/bson/bsonoptions" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +// UIntCodec is the Codec used for uint values. +type UIntCodec struct { +	EncodeToMinSize bool +} + +var ( +	defaultUIntCodec = NewUIntCodec() + +	_ ValueCodec  = defaultUIntCodec +	_ typeDecoder = defaultUIntCodec +) + +// NewUIntCodec returns a UIntCodec with options opts. +func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec { +	uintOpt := bsonoptions.MergeUIntCodecOptions(opts...) + +	codec := UIntCodec{} +	if uintOpt.EncodeToMinSize != nil { +		codec.EncodeToMinSize = *uintOpt.EncodeToMinSize +	} +	return &codec +} + +// EncodeValue is the ValueEncoder for uint types. +func (uic *UIntCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	switch val.Kind() { +	case reflect.Uint8, reflect.Uint16: +		return vw.WriteInt32(int32(val.Uint())) +	case reflect.Uint, reflect.Uint32, reflect.Uint64: +		u64 := val.Uint() + +		// If ec.MinSize or if encodeToMinSize is true for a non-uint64 value we should write val as an int32 +		useMinSize := ec.MinSize || (uic.EncodeToMinSize && val.Kind() != reflect.Uint64) + +		if u64 <= math.MaxInt32 && useMinSize { +			return vw.WriteInt32(int32(u64)) +		} +		if u64 > math.MaxInt64 { +			return fmt.Errorf("%d overflows int64", u64) +		} +		return vw.WriteInt64(int64(u64)) +	} + +	return ValueEncoderError{ +		Name:     "UintEncodeValue", +		Kinds:    []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, +		Received: val, +	} +} + +func (uic *UIntCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) { +	var i64 int64 +	var err error +	switch vrType := vr.Type(); vrType { +	case bsontype.Int32: +		i32, err := vr.ReadInt32() +		if err != nil { +			return emptyValue, err +		} +		i64 = int64(i32) +	case bsontype.Int64: +		i64, err = vr.ReadInt64() +		if err != nil { +			return emptyValue, err +		} +	case bsontype.Double: +		f64, err := vr.ReadDouble() +		if err != nil { +			return emptyValue, err +		} +		if !dc.Truncate && math.Floor(f64) != f64 { +			return emptyValue, errCannotTruncate +		} +		if f64 > float64(math.MaxInt64) { +			return emptyValue, fmt.Errorf("%g overflows int64", f64) +		} +		i64 = int64(f64) +	case bsontype.Boolean: +		b, err := vr.ReadBoolean() +		if err != nil { +			return emptyValue, err +		} +		if b { +			i64 = 1 +		} +	case bsontype.Null: +		if err = vr.ReadNull(); err != nil { +			return emptyValue, err +		} +	case bsontype.Undefined: +		if err = vr.ReadUndefined(); err != nil { +			return emptyValue, err +		} +	default: +		return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType) +	} + +	switch t.Kind() { +	case reflect.Uint8: +		if i64 < 0 || i64 > math.MaxUint8 { +			return emptyValue, fmt.Errorf("%d overflows uint8", i64) +		} + +		return reflect.ValueOf(uint8(i64)), nil +	case reflect.Uint16: +		if i64 < 0 || i64 > math.MaxUint16 { +			return emptyValue, fmt.Errorf("%d overflows uint16", i64) +		} + +		return reflect.ValueOf(uint16(i64)), nil +	case reflect.Uint32: +		if i64 < 0 || i64 > math.MaxUint32 { +			return emptyValue, fmt.Errorf("%d overflows uint32", i64) +		} + +		return reflect.ValueOf(uint32(i64)), nil +	case reflect.Uint64: +		if i64 < 0 { +			return emptyValue, fmt.Errorf("%d overflows uint64", i64) +		} + +		return reflect.ValueOf(uint64(i64)), nil +	case reflect.Uint: +		if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint +			return emptyValue, fmt.Errorf("%d overflows uint", i64) +		} + +		return reflect.ValueOf(uint(i64)), nil +	default: +		return emptyValue, ValueDecoderError{ +			Name:     "UintDecodeValue", +			Kinds:    []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, +			Received: reflect.Zero(t), +		} +	} +} + +// DecodeValue is the ValueDecoder for uint types. +func (uic *UIntCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() { +		return ValueDecoderError{ +			Name:     "UintDecodeValue", +			Kinds:    []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint}, +			Received: val, +		} +	} + +	elem, err := uic.decodeType(dc, vr, val.Type()) +	if err != nil { +		return err +	} + +	val.SetUint(elem.Uint()) +	return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go new file mode 100644 index 000000000..b1256a4dc --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/byte_slice_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// ByteSliceCodecOptions represents all possible options for byte slice encoding and decoding. +type ByteSliceCodecOptions struct { +	EncodeNilAsEmpty *bool // Specifies if a nil byte slice should encode as an empty binary instead of null. Defaults to false. +} + +// ByteSliceCodec creates a new *ByteSliceCodecOptions +func ByteSliceCodec() *ByteSliceCodecOptions { +	return &ByteSliceCodecOptions{} +} + +// SetEncodeNilAsEmpty specifies  if a nil byte slice should encode as an empty binary instead of null. Defaults to false. +func (bs *ByteSliceCodecOptions) SetEncodeNilAsEmpty(b bool) *ByteSliceCodecOptions { +	bs.EncodeNilAsEmpty = &b +	return bs +} + +// MergeByteSliceCodecOptions combines the given *ByteSliceCodecOptions into a single *ByteSliceCodecOptions in a last one wins fashion. +func MergeByteSliceCodecOptions(opts ...*ByteSliceCodecOptions) *ByteSliceCodecOptions { +	bs := ByteSliceCodec() +	for _, opt := range opts { +		if opt == nil { +			continue +		} +		if opt.EncodeNilAsEmpty != nil { +			bs.EncodeNilAsEmpty = opt.EncodeNilAsEmpty +		} +	} + +	return bs +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go new file mode 100644 index 000000000..c40973c8d --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/doc.go @@ -0,0 +1,8 @@ +// Copyright (C) MongoDB, Inc. 2022-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package bsonoptions defines the optional configurations for the BSON codecs. +package bsonoptions diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go new file mode 100644 index 000000000..6caaa000e --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/empty_interface_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// EmptyInterfaceCodecOptions represents all possible options for interface{} encoding and decoding. +type EmptyInterfaceCodecOptions struct { +	DecodeBinaryAsSlice *bool // Specifies if Old and Generic type binarys should default to []slice instead of primitive.Binary. Defaults to false. +} + +// EmptyInterfaceCodec creates a new *EmptyInterfaceCodecOptions +func EmptyInterfaceCodec() *EmptyInterfaceCodecOptions { +	return &EmptyInterfaceCodecOptions{} +} + +// SetDecodeBinaryAsSlice specifies if Old and Generic type binarys should default to []slice instead of primitive.Binary. Defaults to false. +func (e *EmptyInterfaceCodecOptions) SetDecodeBinaryAsSlice(b bool) *EmptyInterfaceCodecOptions { +	e.DecodeBinaryAsSlice = &b +	return e +} + +// MergeEmptyInterfaceCodecOptions combines the given *EmptyInterfaceCodecOptions into a single *EmptyInterfaceCodecOptions in a last one wins fashion. +func MergeEmptyInterfaceCodecOptions(opts ...*EmptyInterfaceCodecOptions) *EmptyInterfaceCodecOptions { +	e := EmptyInterfaceCodec() +	for _, opt := range opts { +		if opt == nil { +			continue +		} +		if opt.DecodeBinaryAsSlice != nil { +			e.DecodeBinaryAsSlice = opt.DecodeBinaryAsSlice +		} +	} + +	return e +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go new file mode 100644 index 000000000..7a6a880b8 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/map_codec_options.go @@ -0,0 +1,67 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// MapCodecOptions represents all possible options for map encoding and decoding. +type MapCodecOptions struct { +	DecodeZerosMap   *bool // Specifies if the map should be zeroed before decoding into it. Defaults to false. +	EncodeNilAsEmpty *bool // Specifies if a nil map should encode as an empty document instead of null. Defaults to false. +	// Specifies how keys should be handled. If false, the behavior matches encoding/json, where the encoding key type must +	// either be a string, an integer type, or implement bsoncodec.KeyMarshaler and the decoding key type must either be a +	// string, an integer type, or implement bsoncodec.KeyUnmarshaler. If true, keys are encoded with fmt.Sprint() and the +	// encoding key type must be a string, an integer type, or a float. If true, the use of Stringer will override +	// TextMarshaler/TextUnmarshaler. Defaults to false. +	EncodeKeysWithStringer *bool +} + +// MapCodec creates a new *MapCodecOptions +func MapCodec() *MapCodecOptions { +	return &MapCodecOptions{} +} + +// SetDecodeZerosMap specifies if the map should be zeroed before decoding into it. Defaults to false. +func (t *MapCodecOptions) SetDecodeZerosMap(b bool) *MapCodecOptions { +	t.DecodeZerosMap = &b +	return t +} + +// SetEncodeNilAsEmpty specifies if a nil map should encode as an empty document instead of null. Defaults to false. +func (t *MapCodecOptions) SetEncodeNilAsEmpty(b bool) *MapCodecOptions { +	t.EncodeNilAsEmpty = &b +	return t +} + +// SetEncodeKeysWithStringer specifies how keys should be handled. If false, the behavior matches encoding/json, where the +// encoding key type must either be a string, an integer type, or implement bsoncodec.KeyMarshaler and the decoding key +// type must either be a string, an integer type, or implement bsoncodec.KeyUnmarshaler. If true, keys are encoded with +// fmt.Sprint() and the encoding key type must be a string, an integer type, or a float. If true, the use of Stringer +// will override TextMarshaler/TextUnmarshaler. Defaults to false. +func (t *MapCodecOptions) SetEncodeKeysWithStringer(b bool) *MapCodecOptions { +	t.EncodeKeysWithStringer = &b +	return t +} + +// MergeMapCodecOptions combines the given *MapCodecOptions into a single *MapCodecOptions in a last one wins fashion. +func MergeMapCodecOptions(opts ...*MapCodecOptions) *MapCodecOptions { +	s := MapCodec() +	for _, opt := range opts { +		if opt == nil { +			continue +		} +		if opt.DecodeZerosMap != nil { +			s.DecodeZerosMap = opt.DecodeZerosMap +		} +		if opt.EncodeNilAsEmpty != nil { +			s.EncodeNilAsEmpty = opt.EncodeNilAsEmpty +		} +		if opt.EncodeKeysWithStringer != nil { +			s.EncodeKeysWithStringer = opt.EncodeKeysWithStringer +		} +	} + +	return s +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go new file mode 100644 index 000000000..ef965e4b4 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/slice_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// SliceCodecOptions represents all possible options for slice encoding and decoding. +type SliceCodecOptions struct { +	EncodeNilAsEmpty *bool // Specifies if a nil slice should encode as an empty array instead of null. Defaults to false. +} + +// SliceCodec creates a new *SliceCodecOptions +func SliceCodec() *SliceCodecOptions { +	return &SliceCodecOptions{} +} + +// SetEncodeNilAsEmpty specifies  if a nil slice should encode as an empty array instead of null. Defaults to false. +func (s *SliceCodecOptions) SetEncodeNilAsEmpty(b bool) *SliceCodecOptions { +	s.EncodeNilAsEmpty = &b +	return s +} + +// MergeSliceCodecOptions combines the given *SliceCodecOptions into a single *SliceCodecOptions in a last one wins fashion. +func MergeSliceCodecOptions(opts ...*SliceCodecOptions) *SliceCodecOptions { +	s := SliceCodec() +	for _, opt := range opts { +		if opt == nil { +			continue +		} +		if opt.EncodeNilAsEmpty != nil { +			s.EncodeNilAsEmpty = opt.EncodeNilAsEmpty +		} +	} + +	return s +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go new file mode 100644 index 000000000..65964f420 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/string_codec_options.go @@ -0,0 +1,41 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +var defaultDecodeOIDAsHex = true + +// StringCodecOptions represents all possible options for string encoding and decoding. +type StringCodecOptions struct { +	DecodeObjectIDAsHex *bool // Specifies if we should decode ObjectID as the hex value. Defaults to true. +} + +// StringCodec creates a new *StringCodecOptions +func StringCodec() *StringCodecOptions { +	return &StringCodecOptions{} +} + +// SetDecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation. If false, a string made +// from the raw object ID bytes will be used. Defaults to true. +func (t *StringCodecOptions) SetDecodeObjectIDAsHex(b bool) *StringCodecOptions { +	t.DecodeObjectIDAsHex = &b +	return t +} + +// MergeStringCodecOptions combines the given *StringCodecOptions into a single *StringCodecOptions in a last one wins fashion. +func MergeStringCodecOptions(opts ...*StringCodecOptions) *StringCodecOptions { +	s := &StringCodecOptions{&defaultDecodeOIDAsHex} +	for _, opt := range opts { +		if opt == nil { +			continue +		} +		if opt.DecodeObjectIDAsHex != nil { +			s.DecodeObjectIDAsHex = opt.DecodeObjectIDAsHex +		} +	} + +	return s +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go new file mode 100644 index 000000000..78d1dd866 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/struct_codec_options.go @@ -0,0 +1,87 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +var defaultOverwriteDuplicatedInlinedFields = true + +// StructCodecOptions represents all possible options for struct encoding and decoding. +type StructCodecOptions struct { +	DecodeZeroStruct                 *bool // Specifies if structs should be zeroed before decoding into them. Defaults to false. +	DecodeDeepZeroInline             *bool // Specifies if structs should be recursively zeroed when a inline value is decoded. Defaults to false. +	EncodeOmitDefaultStruct          *bool // Specifies if default structs should be considered empty by omitempty. Defaults to false. +	AllowUnexportedFields            *bool // Specifies if unexported fields should be marshaled/unmarshaled. Defaults to false. +	OverwriteDuplicatedInlinedFields *bool // Specifies if fields in inlined structs can be overwritten by higher level struct fields with the same key. Defaults to true. +} + +// StructCodec creates a new *StructCodecOptions +func StructCodec() *StructCodecOptions { +	return &StructCodecOptions{} +} + +// SetDecodeZeroStruct specifies if structs should be zeroed before decoding into them. Defaults to false. +func (t *StructCodecOptions) SetDecodeZeroStruct(b bool) *StructCodecOptions { +	t.DecodeZeroStruct = &b +	return t +} + +// SetDecodeDeepZeroInline specifies if structs should be zeroed before decoding into them. Defaults to false. +func (t *StructCodecOptions) SetDecodeDeepZeroInline(b bool) *StructCodecOptions { +	t.DecodeDeepZeroInline = &b +	return t +} + +// SetEncodeOmitDefaultStruct specifies if default structs should be considered empty by omitempty. A default struct has all +// its values set to their default value. Defaults to false. +func (t *StructCodecOptions) SetEncodeOmitDefaultStruct(b bool) *StructCodecOptions { +	t.EncodeOmitDefaultStruct = &b +	return t +} + +// SetOverwriteDuplicatedInlinedFields specifies if inlined struct fields can be overwritten by higher level struct fields with the +// same bson key. When true and decoding, values will be written to the outermost struct with a matching key, and when +// encoding, keys will have the value of the top-most matching field. When false, decoding and encoding will error if +// there are duplicate keys after the struct is inlined. Defaults to true. +func (t *StructCodecOptions) SetOverwriteDuplicatedInlinedFields(b bool) *StructCodecOptions { +	t.OverwriteDuplicatedInlinedFields = &b +	return t +} + +// SetAllowUnexportedFields specifies if unexported fields should be marshaled/unmarshaled. Defaults to false. +func (t *StructCodecOptions) SetAllowUnexportedFields(b bool) *StructCodecOptions { +	t.AllowUnexportedFields = &b +	return t +} + +// MergeStructCodecOptions combines the given *StructCodecOptions into a single *StructCodecOptions in a last one wins fashion. +func MergeStructCodecOptions(opts ...*StructCodecOptions) *StructCodecOptions { +	s := &StructCodecOptions{ +		OverwriteDuplicatedInlinedFields: &defaultOverwriteDuplicatedInlinedFields, +	} +	for _, opt := range opts { +		if opt == nil { +			continue +		} + +		if opt.DecodeZeroStruct != nil { +			s.DecodeZeroStruct = opt.DecodeZeroStruct +		} +		if opt.DecodeDeepZeroInline != nil { +			s.DecodeDeepZeroInline = opt.DecodeDeepZeroInline +		} +		if opt.EncodeOmitDefaultStruct != nil { +			s.EncodeOmitDefaultStruct = opt.EncodeOmitDefaultStruct +		} +		if opt.OverwriteDuplicatedInlinedFields != nil { +			s.OverwriteDuplicatedInlinedFields = opt.OverwriteDuplicatedInlinedFields +		} +		if opt.AllowUnexportedFields != nil { +			s.AllowUnexportedFields = opt.AllowUnexportedFields +		} +	} + +	return s +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go new file mode 100644 index 000000000..13496d121 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/time_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// TimeCodecOptions represents all possible options for time.Time encoding and decoding. +type TimeCodecOptions struct { +	UseLocalTimeZone *bool // Specifies if we should decode into the local time zone. Defaults to false. +} + +// TimeCodec creates a new *TimeCodecOptions +func TimeCodec() *TimeCodecOptions { +	return &TimeCodecOptions{} +} + +// SetUseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false. +func (t *TimeCodecOptions) SetUseLocalTimeZone(b bool) *TimeCodecOptions { +	t.UseLocalTimeZone = &b +	return t +} + +// MergeTimeCodecOptions combines the given *TimeCodecOptions into a single *TimeCodecOptions in a last one wins fashion. +func MergeTimeCodecOptions(opts ...*TimeCodecOptions) *TimeCodecOptions { +	t := TimeCodec() +	for _, opt := range opts { +		if opt == nil { +			continue +		} +		if opt.UseLocalTimeZone != nil { +			t.UseLocalTimeZone = opt.UseLocalTimeZone +		} +	} + +	return t +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go new file mode 100644 index 000000000..e08b7f192 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonoptions/uint_codec_options.go @@ -0,0 +1,38 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonoptions + +// UIntCodecOptions represents all possible options for uint encoding and decoding. +type UIntCodecOptions struct { +	EncodeToMinSize *bool // Specifies if all uints except uint64 should be decoded to minimum size bsontype. Defaults to false. +} + +// UIntCodec creates a new *UIntCodecOptions +func UIntCodec() *UIntCodecOptions { +	return &UIntCodecOptions{} +} + +// SetEncodeToMinSize specifies if all uints except uint64 should be decoded to minimum size bsontype. Defaults to false. +func (u *UIntCodecOptions) SetEncodeToMinSize(b bool) *UIntCodecOptions { +	u.EncodeToMinSize = &b +	return u +} + +// MergeUIntCodecOptions combines the given *UIntCodecOptions into a single *UIntCodecOptions in a last one wins fashion. +func MergeUIntCodecOptions(opts ...*UIntCodecOptions) *UIntCodecOptions { +	u := UIntCodec() +	for _, opt := range opts { +		if opt == nil { +			continue +		} +		if opt.EncodeToMinSize != nil { +			u.EncodeToMinSize = opt.EncodeToMinSize +		} +	} + +	return u +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go new file mode 100644 index 000000000..5cdf6460b --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go @@ -0,0 +1,445 @@ +// 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 bsonrw + +import ( +	"fmt" +	"io" + +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +// Copier is a type that allows copying between ValueReaders, ValueWriters, and +// []byte values. +type Copier struct{} + +// NewCopier creates a new copier with the given registry. If a nil registry is provided +// a default registry is used. +func NewCopier() Copier { +	return Copier{} +} + +// CopyDocument handles copying a document from src to dst. +func CopyDocument(dst ValueWriter, src ValueReader) error { +	return Copier{}.CopyDocument(dst, src) +} + +// CopyDocument handles copying one document from the src to the dst. +func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error { +	dr, err := src.ReadDocument() +	if err != nil { +		return err +	} + +	dw, err := dst.WriteDocument() +	if err != nil { +		return err +	} + +	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 { +	dw, err := dst.WriteDocument() +	if err != nil { +		return err +	} + +	err = c.CopyBytesToDocumentWriter(dw, src) +	if err != nil { +		return err +	} + +	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 { +		return fmt.Errorf("couldn't read length from src, not enough bytes. length=%d", len(src)) +	} +	if len(src) < int(length) { +		return fmt.Errorf("length read exceeds number of bytes available. length=%d bytes=%d", len(src), length) +	} +	rem = rem[:length-4] + +	var t bsontype.Type +	var key string +	var val bsoncore.Value +	for { +		t, rem, ok = bsoncore.ReadType(rem) +		if !ok { +			return io.EOF +		} +		if t == bsontype.Type(0) { +			if len(rem) != 0 { +				return fmt.Errorf("document end byte found before end of document. remaining bytes=%v", rem) +			} +			break +		} + +		key, rem, ok = bsoncore.ReadKey(rem) +		if !ok { +			return fmt.Errorf("invalid key found. remaining bytes=%v", rem) +		} + +		// 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(vw, t, val.Data) +		if err != nil { +			return err +		} +	} +	return nil +} + +// CopyDocumentToBytes copies an entire document from the ValueReader and +// returns it as bytes. +func (c Copier) CopyDocumentToBytes(src ValueReader) ([]byte, error) { +	return c.AppendDocumentBytes(nil, src) +} + +// AppendDocumentBytes functions the same as CopyDocumentToBytes, but will +// append the result to dst. +func (c Copier) AppendDocumentBytes(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.CopyDocument(vw, src) +	dst = vw.buf +	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 { +		return wvb.WriteValueBytes(t, src) +	} + +	vr := vrPool.Get().(*valueReader) +	defer vrPool.Put(vr) + +	vr.reset(src) +	vr.pushElement(t) + +	return c.CopyValue(dst, vr) +} + +// CopyValueToBytes copies a value from src and returns it as a bsontype.Type and a +// []byte. +func (c Copier) CopyValueToBytes(src ValueReader) (bsontype.Type, []byte, error) { +	return c.AppendValueBytes(nil, src) +} + +// AppendValueBytes functions the same as CopyValueToBytes, but will append the +// result to dst. +func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, []byte, error) { +	if br, ok := src.(BytesReader); ok { +		return br.ReadValueBytes(dst) +	} + +	vw := vwPool.Get().(*valueWriter) +	defer vwPool.Put(vw) + +	start := len(dst) + +	vw.reset(dst) +	vw.push(mElement) + +	err := c.CopyValue(vw, src) +	if err != nil { +		return 0, dst, err +	} + +	return bsontype.Type(vw.buf[start]), vw.buf[start+2:], nil +} + +// CopyValue will copy a single value from src to dst. +func (c Copier) CopyValue(dst ValueWriter, src ValueReader) error { +	var err error +	switch src.Type() { +	case bsontype.Double: +		var f64 float64 +		f64, err = src.ReadDouble() +		if err != nil { +			break +		} +		err = dst.WriteDouble(f64) +	case bsontype.String: +		var str string +		str, err = src.ReadString() +		if err != nil { +			return err +		} +		err = dst.WriteString(str) +	case bsontype.EmbeddedDocument: +		err = c.CopyDocument(dst, src) +	case bsontype.Array: +		err = c.copyArray(dst, src) +	case bsontype.Binary: +		var data []byte +		var subtype byte +		data, subtype, err = src.ReadBinary() +		if err != nil { +			break +		} +		err = dst.WriteBinaryWithSubtype(data, subtype) +	case bsontype.Undefined: +		err = src.ReadUndefined() +		if err != nil { +			break +		} +		err = dst.WriteUndefined() +	case bsontype.ObjectID: +		var oid primitive.ObjectID +		oid, err = src.ReadObjectID() +		if err != nil { +			break +		} +		err = dst.WriteObjectID(oid) +	case bsontype.Boolean: +		var b bool +		b, err = src.ReadBoolean() +		if err != nil { +			break +		} +		err = dst.WriteBoolean(b) +	case bsontype.DateTime: +		var dt int64 +		dt, err = src.ReadDateTime() +		if err != nil { +			break +		} +		err = dst.WriteDateTime(dt) +	case bsontype.Null: +		err = src.ReadNull() +		if err != nil { +			break +		} +		err = dst.WriteNull() +	case bsontype.Regex: +		var pattern, options string +		pattern, options, err = src.ReadRegex() +		if err != nil { +			break +		} +		err = dst.WriteRegex(pattern, options) +	case bsontype.DBPointer: +		var ns string +		var pointer primitive.ObjectID +		ns, pointer, err = src.ReadDBPointer() +		if err != nil { +			break +		} +		err = dst.WriteDBPointer(ns, pointer) +	case bsontype.JavaScript: +		var js string +		js, err = src.ReadJavascript() +		if err != nil { +			break +		} +		err = dst.WriteJavascript(js) +	case bsontype.Symbol: +		var symbol string +		symbol, err = src.ReadSymbol() +		if err != nil { +			break +		} +		err = dst.WriteSymbol(symbol) +	case bsontype.CodeWithScope: +		var code string +		var srcScope DocumentReader +		code, srcScope, err = src.ReadCodeWithScope() +		if err != nil { +			break +		} + +		var dstScope DocumentWriter +		dstScope, err = dst.WriteCodeWithScope(code) +		if err != nil { +			break +		} +		err = c.copyDocumentCore(dstScope, srcScope) +	case bsontype.Int32: +		var i32 int32 +		i32, err = src.ReadInt32() +		if err != nil { +			break +		} +		err = dst.WriteInt32(i32) +	case bsontype.Timestamp: +		var t, i uint32 +		t, i, err = src.ReadTimestamp() +		if err != nil { +			break +		} +		err = dst.WriteTimestamp(t, i) +	case bsontype.Int64: +		var i64 int64 +		i64, err = src.ReadInt64() +		if err != nil { +			break +		} +		err = dst.WriteInt64(i64) +	case bsontype.Decimal128: +		var d128 primitive.Decimal128 +		d128, err = src.ReadDecimal128() +		if err != nil { +			break +		} +		err = dst.WriteDecimal128(d128) +	case bsontype.MinKey: +		err = src.ReadMinKey() +		if err != nil { +			break +		} +		err = dst.WriteMinKey() +	case bsontype.MaxKey: +		err = src.ReadMaxKey() +		if err != nil { +			break +		} +		err = dst.WriteMaxKey() +	default: +		err = fmt.Errorf("Cannot copy unknown BSON type %s", src.Type()) +	} + +	return err +} + +func (c Copier) copyArray(dst ValueWriter, src ValueReader) error { +	ar, err := src.ReadArray() +	if err != nil { +		return err +	} + +	aw, err := dst.WriteArray() +	if err != nil { +		return err +	} + +	for { +		vr, err := ar.ReadValue() +		if err == ErrEOA { +			break +		} +		if err != nil { +			return err +		} + +		vw, err := aw.WriteArrayElement() +		if err != nil { +			return err +		} + +		err = c.CopyValue(vw, vr) +		if err != nil { +			return err +		} +	} + +	return aw.WriteArrayEnd() +} + +func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error { +	for { +		key, vr, err := dr.ReadElement() +		if err == ErrEOD { +			break +		} +		if err != nil { +			return err +		} + +		vw, err := dw.WriteDocumentElement(key) +		if err != nil { +			return err +		} + +		err = c.CopyValue(vw, vr) +		if err != nil { +			return err +		} +	} + +	return dw.WriteDocumentEnd() +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/doc.go new file mode 100644 index 000000000..750b0d2af --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/doc.go @@ -0,0 +1,9 @@ +// 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 bsonrw contains abstractions for reading and writing +// BSON and BSON like types from sources. +package bsonrw // import "go.mongodb.org/mongo-driver/bson/bsonrw" 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 new file mode 100644 index 000000000..54c76bf74 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go @@ -0,0 +1,806 @@ +// 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 bsonrw + +import ( +	"encoding/base64" +	"encoding/hex" +	"errors" +	"fmt" +	"io" +	"strings" + +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +const maxNestingDepth = 200 + +// ErrInvalidJSON indicates the JSON input is invalid +var ErrInvalidJSON = errors.New("invalid JSON input") + +type jsonParseState byte + +const ( +	jpsStartState jsonParseState = iota +	jpsSawBeginObject +	jpsSawEndObject +	jpsSawBeginArray +	jpsSawEndArray +	jpsSawColon +	jpsSawComma +	jpsSawKey +	jpsSawValue +	jpsDoneState +	jpsInvalidState +) + +type jsonParseMode byte + +const ( +	jpmInvalidMode jsonParseMode = iota +	jpmObjectMode +	jpmArrayMode +) + +type extJSONValue struct { +	t bsontype.Type +	v interface{} +} + +type extJSONObject struct { +	keys   []string +	values []*extJSONValue +} + +type extJSONParser struct { +	js *jsonScanner +	s  jsonParseState +	m  []jsonParseMode +	k  string +	v  *extJSONValue + +	err       error +	canonical bool +	depth     int +	maxDepth  int + +	emptyObject bool +	relaxedUUID bool +} + +// newExtJSONParser returns a new extended JSON parser, ready to to begin +// parsing from the first character of the argued json input. It will not +// perform any read-ahead and will therefore not report any errors about +// malformed JSON at this point. +func newExtJSONParser(r io.Reader, canonical bool) *extJSONParser { +	return &extJSONParser{ +		js:        &jsonScanner{r: r}, +		s:         jpsStartState, +		m:         []jsonParseMode{}, +		canonical: canonical, +		maxDepth:  maxNestingDepth, +	} +} + +// peekType examines the next value and returns its BSON Type +func (ejp *extJSONParser) peekType() (bsontype.Type, error) { +	var t bsontype.Type +	var err error +	initialState := ejp.s + +	ejp.advanceState() +	switch ejp.s { +	case jpsSawValue: +		t = ejp.v.t +	case jpsSawBeginArray: +		t = bsontype.Array +	case jpsInvalidState: +		err = ejp.err +	case jpsSawComma: +		// in array mode, seeing a comma means we need to progress again to actually observe a type +		if ejp.peekMode() == jpmArrayMode { +			return ejp.peekType() +		} +	case jpsSawEndArray: +		// this would only be a valid state if we were in array mode, so return end-of-array error +		err = ErrEOA +	case jpsSawBeginObject: +		// peek key to determine type +		ejp.advanceState() +		switch ejp.s { +		case jpsSawEndObject: // empty embedded document +			t = bsontype.EmbeddedDocument +			ejp.emptyObject = true +		case jpsInvalidState: +			err = ejp.err +		case jpsSawKey: +			if initialState == jpsStartState { +				return bsontype.EmbeddedDocument, nil +			} +			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 +				_, err = ejp.readValue(bsontype.JavaScript) +				if err != nil { +					break +				} + +				switch ejp.s { +				case jpsSawEndObject: // type is TypeJavaScript +				case jpsSawComma: +					ejp.advanceState() + +					if ejp.s == jpsSawKey && ejp.k == "$scope" { +						t = bsontype.CodeWithScope +					} else { +						err = fmt.Errorf("invalid extended JSON: unexpected key %s in CodeWithScope object", ejp.k) +					} +				case jpsInvalidState: +					err = ejp.err +				default: +					err = ErrInvalidJSON +				} +			case bsontype.CodeWithScope: +				err = errors.New("invalid extended JSON: code with $scope must contain $code before $scope") +			} +		} +	} + +	return t, err +} + +// readKey parses the next key and its type and returns them +func (ejp *extJSONParser) readKey() (string, bsontype.Type, error) { +	if ejp.emptyObject { +		ejp.emptyObject = false +		return "", 0, ErrEOD +	} + +	// advance to key (or return with error) +	switch ejp.s { +	case jpsStartState: +		ejp.advanceState() +		if ejp.s == jpsSawBeginObject { +			ejp.advanceState() +		} +	case jpsSawBeginObject: +		ejp.advanceState() +	case jpsSawValue, jpsSawEndObject, jpsSawEndArray: +		ejp.advanceState() +		switch ejp.s { +		case jpsSawBeginObject, jpsSawComma: +			ejp.advanceState() +		case jpsSawEndObject: +			return "", 0, ErrEOD +		case jpsDoneState: +			return "", 0, io.EOF +		case jpsInvalidState: +			return "", 0, ejp.err +		default: +			return "", 0, ErrInvalidJSON +		} +	case jpsSawKey: // do nothing (key was peeked before) +	default: +		return "", 0, invalidRequestError("key") +	} + +	// read key +	var key string + +	switch ejp.s { +	case jpsSawKey: +		key = ejp.k +	case jpsSawEndObject: +		return "", 0, ErrEOD +	case jpsInvalidState: +		return "", 0, ejp.err +	default: +		return "", 0, invalidRequestError("key") +	} + +	// check for colon +	ejp.advanceState() +	if err := ensureColon(ejp.s, key); err != nil { +		return "", 0, err +	} + +	// peek at the value to determine type +	t, err := ejp.peekType() +	if err != nil { +		return "", 0, err +	} + +	return key, t, nil +} + +// readValue returns the value corresponding to the Type returned by peekType +func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) { +	if ejp.s == jpsInvalidState { +		return nil, ejp.err +	} + +	var v *extJSONValue + +	switch t { +	case bsontype.Null, bsontype.Boolean, bsontype.String: +		if ejp.s != jpsSawValue { +			return nil, invalidRequestError(t.String()) +		} +		v = ejp.v +	case bsontype.Int32, bsontype.Int64, bsontype.Double: +		// relaxed version allows these to be literal number values +		if ejp.s == jpsSawValue { +			v = ejp.v +			break +		} +		fallthrough +	case bsontype.Decimal128, bsontype.Symbol, bsontype.ObjectID, bsontype.MinKey, bsontype.MaxKey, bsontype.Undefined: +		switch ejp.s { +		case jpsSawKey: +			// read colon +			ejp.advanceState() +			if err := ensureColon(ejp.s, ejp.k); err != nil { +				return nil, err +			} + +			// read value +			ejp.advanceState() +			if ejp.s != jpsSawValue || !ejp.ensureExtValueType(t) { +				return nil, invalidJSONErrorForType("value", t) +			} + +			v = ejp.v + +			// read end object +			ejp.advanceState() +			if ejp.s != jpsSawEndObject { +				return nil, invalidJSONErrorForType("} after value", t) +			} +		default: +			return nil, invalidRequestError(t.String()) +		} +	case bsontype.Binary, bsontype.Regex, bsontype.Timestamp, bsontype.DBPointer: +		if ejp.s != jpsSawKey { +			return nil, invalidRequestError(t.String()) +		} +		// read colon +		ejp.advanceState() +		if err := ensureColon(ejp.s, ejp.k); err != nil { +			return nil, err +		} + +		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 + +			ejp.advanceState() +			if ejp.s != jpsSawComma { +				return nil, invalidJSONErrorForType(",", bsontype.Binary) +			} + +			ejp.advanceState() +			key, t, err := ejp.readKey() +			if err != nil { +				return nil, err +			} +			if key != "$type" { +				return nil, invalidJSONErrorForType("$type", bsontype.Binary) +			} + +			subType, err := ejp.readValue(t) +			if err != nil { +				return nil, err +			} + +			ejp.advanceState() +			if ejp.s != jpsSawEndObject { +				return nil, invalidJSONErrorForType("2 key-value pairs and then }", bsontype.Binary) +			} + +			v = &extJSONValue{ +				t: bsontype.EmbeddedDocument, +				v: &extJSONObject{ +					keys:   []string{"base64", "subType"}, +					values: []*extJSONValue{base64, subType}, +				}, +			} +			break +		} + +		// read KV pairs +		if ejp.s != jpsSawBeginObject { +			return nil, invalidJSONErrorForType("{", t) +		} + +		keys, vals, err := ejp.readObject(2, true) +		if err != nil { +			return nil, err +		} + +		ejp.advanceState() +		if ejp.s != jpsSawEndObject { +			return nil, invalidJSONErrorForType("2 key-value pairs and then }", t) +		} + +		v = &extJSONValue{t: bsontype.EmbeddedDocument, v: &extJSONObject{keys: keys, values: vals}} + +	case bsontype.DateTime: +		switch ejp.s { +		case jpsSawValue: +			v = ejp.v +		case jpsSawKey: +			// read colon +			ejp.advanceState() +			if err := ensureColon(ejp.s, ejp.k); err != nil { +				return nil, err +			} + +			ejp.advanceState() +			switch ejp.s { +			case jpsSawBeginObject: +				keys, vals, err := ejp.readObject(1, true) +				if err != nil { +					return nil, err +				} +				v = &extJSONValue{t: bsontype.EmbeddedDocument, v: &extJSONObject{keys: keys, values: vals}} +			case jpsSawValue: +				if ejp.canonical { +					return nil, invalidJSONError("{") +				} +				v = ejp.v +			default: +				if ejp.canonical { +					return nil, invalidJSONErrorForType("object", t) +				} +				return nil, invalidJSONErrorForType("ISO-8601 Internet Date/Time Format as described in RFC-3339", t) +			} + +			ejp.advanceState() +			if ejp.s != jpsSawEndObject { +				return nil, invalidJSONErrorForType("value and then }", t) +			} +		default: +			return nil, invalidRequestError(t.String()) +		} +	case bsontype.JavaScript: +		switch ejp.s { +		case jpsSawKey: +			// read colon +			ejp.advanceState() +			if err := ensureColon(ejp.s, ejp.k); err != nil { +				return nil, err +			} + +			// read value +			ejp.advanceState() +			if ejp.s != jpsSawValue { +				return nil, invalidJSONErrorForType("value", t) +			} +			v = ejp.v + +			// read end object or comma and just return +			ejp.advanceState() +		case jpsSawEndObject: +			v = ejp.v +		default: +			return nil, invalidRequestError(t.String()) +		} +	case bsontype.CodeWithScope: +		if ejp.s == jpsSawKey && ejp.k == "$scope" { +			v = ejp.v // this is the $code string from earlier + +			// read colon +			ejp.advanceState() +			if err := ensureColon(ejp.s, ejp.k); err != nil { +				return nil, err +			} + +			// read { +			ejp.advanceState() +			if ejp.s != jpsSawBeginObject { +				return nil, invalidJSONError("$scope to be embedded document") +			} +		} else { +			return nil, invalidRequestError(t.String()) +		} +	case bsontype.EmbeddedDocument, bsontype.Array: +		return nil, invalidRequestError(t.String()) +	} + +	return v, nil +} + +// readObject is a utility method for reading full objects of known (or expected) size +// it is useful for extended JSON types such as binary, datetime, regex, and timestamp +func (ejp *extJSONParser) readObject(numKeys int, started bool) ([]string, []*extJSONValue, error) { +	keys := make([]string, numKeys) +	vals := make([]*extJSONValue, numKeys) + +	if !started { +		ejp.advanceState() +		if ejp.s != jpsSawBeginObject { +			return nil, nil, invalidJSONError("{") +		} +	} + +	for i := 0; i < numKeys; i++ { +		key, t, err := ejp.readKey() +		if err != nil { +			return nil, nil, err +		} + +		switch ejp.s { +		case jpsSawKey: +			v, err := ejp.readValue(t) +			if err != nil { +				return nil, nil, err +			} + +			keys[i] = key +			vals[i] = v +		case jpsSawValue: +			keys[i] = key +			vals[i] = ejp.v +		default: +			return nil, nil, invalidJSONError("value") +		} +	} + +	ejp.advanceState() +	if ejp.s != jpsSawEndObject { +		return nil, nil, invalidJSONError("}") +	} + +	return keys, vals, nil +} + +// advanceState reads the next JSON token from the scanner and transitions +// from the current state based on that token's type +func (ejp *extJSONParser) advanceState() { +	if ejp.s == jpsDoneState || ejp.s == jpsInvalidState { +		return +	} + +	jt, err := ejp.js.nextToken() + +	if err != nil { +		ejp.err = err +		ejp.s = jpsInvalidState +		return +	} + +	valid := ejp.validateToken(jt.t) +	if !valid { +		ejp.err = unexpectedTokenError(jt) +		ejp.s = jpsInvalidState +		return +	} + +	switch jt.t { +	case jttBeginObject: +		ejp.s = jpsSawBeginObject +		ejp.pushMode(jpmObjectMode) +		ejp.depth++ + +		if ejp.depth > ejp.maxDepth { +			ejp.err = nestingDepthError(jt.p, ejp.depth) +			ejp.s = jpsInvalidState +		} +	case jttEndObject: +		ejp.s = jpsSawEndObject +		ejp.depth-- + +		if ejp.popMode() != jpmObjectMode { +			ejp.err = unexpectedTokenError(jt) +			ejp.s = jpsInvalidState +		} +	case jttBeginArray: +		ejp.s = jpsSawBeginArray +		ejp.pushMode(jpmArrayMode) +	case jttEndArray: +		ejp.s = jpsSawEndArray + +		if ejp.popMode() != jpmArrayMode { +			ejp.err = unexpectedTokenError(jt) +			ejp.s = jpsInvalidState +		} +	case jttColon: +		ejp.s = jpsSawColon +	case jttComma: +		ejp.s = jpsSawComma +	case jttEOF: +		ejp.s = jpsDoneState +		if len(ejp.m) != 0 { +			ejp.err = unexpectedTokenError(jt) +			ejp.s = jpsInvalidState +		} +	case jttString: +		switch ejp.s { +		case jpsSawComma: +			if ejp.peekMode() == jpmArrayMode { +				ejp.s = jpsSawValue +				ejp.v = extendJSONToken(jt) +				return +			} +			fallthrough +		case jpsSawBeginObject: +			ejp.s = jpsSawKey +			ejp.k = jt.v.(string) +			return +		} +		fallthrough +	default: +		ejp.s = jpsSawValue +		ejp.v = extendJSONToken(jt) +	} +} + +var jpsValidTransitionTokens = map[jsonParseState]map[jsonTokenType]bool{ +	jpsStartState: { +		jttBeginObject: true, +		jttBeginArray:  true, +		jttInt32:       true, +		jttInt64:       true, +		jttDouble:      true, +		jttString:      true, +		jttBool:        true, +		jttNull:        true, +		jttEOF:         true, +	}, +	jpsSawBeginObject: { +		jttEndObject: true, +		jttString:    true, +	}, +	jpsSawEndObject: { +		jttEndObject: true, +		jttEndArray:  true, +		jttComma:     true, +		jttEOF:       true, +	}, +	jpsSawBeginArray: { +		jttBeginObject: true, +		jttBeginArray:  true, +		jttEndArray:    true, +		jttInt32:       true, +		jttInt64:       true, +		jttDouble:      true, +		jttString:      true, +		jttBool:        true, +		jttNull:        true, +	}, +	jpsSawEndArray: { +		jttEndObject: true, +		jttEndArray:  true, +		jttComma:     true, +		jttEOF:       true, +	}, +	jpsSawColon: { +		jttBeginObject: true, +		jttBeginArray:  true, +		jttInt32:       true, +		jttInt64:       true, +		jttDouble:      true, +		jttString:      true, +		jttBool:        true, +		jttNull:        true, +	}, +	jpsSawComma: { +		jttBeginObject: true, +		jttBeginArray:  true, +		jttInt32:       true, +		jttInt64:       true, +		jttDouble:      true, +		jttString:      true, +		jttBool:        true, +		jttNull:        true, +	}, +	jpsSawKey: { +		jttColon: true, +	}, +	jpsSawValue: { +		jttEndObject: true, +		jttEndArray:  true, +		jttComma:     true, +		jttEOF:       true, +	}, +	jpsDoneState:    {}, +	jpsInvalidState: {}, +} + +func (ejp *extJSONParser) validateToken(jtt jsonTokenType) bool { +	switch ejp.s { +	case jpsSawEndObject: +		// if we are at depth zero and the next token is a '{', +		// we can consider it valid only if we are not in array mode. +		if jtt == jttBeginObject && ejp.depth == 0 { +			return ejp.peekMode() != jpmArrayMode +		} +	case jpsSawComma: +		switch ejp.peekMode() { +		// the only valid next token after a comma inside a document is a string (a key) +		case jpmObjectMode: +			return jtt == jttString +		case jpmInvalidMode: +			return false +		} +	} + +	_, ok := jpsValidTransitionTokens[ejp.s][jtt] +	return ok +} + +// ensureExtValueType returns true if the current value has the expected +// value type for single-key extended JSON types. For example, +// {"$numberInt": v} v must be TypeString +func (ejp *extJSONParser) ensureExtValueType(t bsontype.Type) bool { +	switch t { +	case bsontype.MinKey, bsontype.MaxKey: +		return ejp.v.t == bsontype.Int32 +	case bsontype.Undefined: +		return ejp.v.t == bsontype.Boolean +	case bsontype.Int32, bsontype.Int64, bsontype.Double, bsontype.Decimal128, bsontype.Symbol, bsontype.ObjectID: +		return ejp.v.t == bsontype.String +	default: +		return false +	} +} + +func (ejp *extJSONParser) pushMode(m jsonParseMode) { +	ejp.m = append(ejp.m, m) +} + +func (ejp *extJSONParser) popMode() jsonParseMode { +	l := len(ejp.m) +	if l == 0 { +		return jpmInvalidMode +	} + +	m := ejp.m[l-1] +	ejp.m = ejp.m[:l-1] + +	return m +} + +func (ejp *extJSONParser) peekMode() jsonParseMode { +	l := len(ejp.m) +	if l == 0 { +		return jpmInvalidMode +	} + +	return ejp.m[l-1] +} + +func extendJSONToken(jt *jsonToken) *extJSONValue { +	var t bsontype.Type + +	switch jt.t { +	case jttInt32: +		t = bsontype.Int32 +	case jttInt64: +		t = bsontype.Int64 +	case jttDouble: +		t = bsontype.Double +	case jttString: +		t = bsontype.String +	case jttBool: +		t = bsontype.Boolean +	case jttNull: +		t = bsontype.Null +	default: +		return nil +	} + +	return &extJSONValue{t: t, v: jt.v} +} + +func ensureColon(s jsonParseState, key string) error { +	if s != jpsSawColon { +		return fmt.Errorf("invalid JSON input: missing colon after key \"%s\"", key) +	} + +	return nil +} + +func invalidRequestError(s string) error { +	return fmt.Errorf("invalid request to read %s", s) +} + +func invalidJSONError(expected string) error { +	return fmt.Errorf("invalid JSON input; expected %s", expected) +} + +func invalidJSONErrorForType(expected string, t bsontype.Type) error { +	return fmt.Errorf("invalid JSON input; expected %s for %s", expected, t) +} + +func unexpectedTokenError(jt *jsonToken) error { +	switch jt.t { +	case jttInt32, jttInt64, jttDouble: +		return fmt.Errorf("invalid JSON input; unexpected number (%v) at position %d", jt.v, jt.p) +	case jttString: +		return fmt.Errorf("invalid JSON input; unexpected string (\"%v\") at position %d", jt.v, jt.p) +	case jttBool: +		return fmt.Errorf("invalid JSON input; unexpected boolean literal (%v) at position %d", jt.v, jt.p) +	case jttNull: +		return fmt.Errorf("invalid JSON input; unexpected null literal at position %d", jt.p) +	case jttEOF: +		return fmt.Errorf("invalid JSON input; unexpected end of input at position %d", jt.p) +	default: +		return fmt.Errorf("invalid JSON input; unexpected %c at position %d", jt.v.(byte), jt.p) +	} +} + +func nestingDepthError(p, depth int) error { +	return fmt.Errorf("invalid JSON input; nesting too deep (%d levels) at position %d", depth, p) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go new file mode 100644 index 000000000..35832d73a --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go @@ -0,0 +1,644 @@ +// 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 bsonrw + +import ( +	"fmt" +	"io" +	"sync" + +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +// ExtJSONValueReaderPool is a pool for ValueReaders that read ExtJSON. +type ExtJSONValueReaderPool struct { +	pool sync.Pool +} + +// NewExtJSONValueReaderPool instantiates a new ExtJSONValueReaderPool. +func NewExtJSONValueReaderPool() *ExtJSONValueReaderPool { +	return &ExtJSONValueReaderPool{ +		pool: sync.Pool{ +			New: func() interface{} { +				return new(extJSONValueReader) +			}, +		}, +	} +} + +// Get retrieves a ValueReader from the pool and uses src as the underlying ExtJSON. +func (bvrp *ExtJSONValueReaderPool) Get(r io.Reader, canonical bool) (ValueReader, error) { +	vr := bvrp.pool.Get().(*extJSONValueReader) +	return vr.reset(r, canonical) +} + +// Put inserts a ValueReader into the pool. If the ValueReader is not a ExtJSON ValueReader nothing +// is inserted into the pool and ok will be false. +func (bvrp *ExtJSONValueReaderPool) Put(vr ValueReader) (ok bool) { +	bvr, ok := vr.(*extJSONValueReader) +	if !ok { +		return false +	} + +	bvr, _ = bvr.reset(nil, false) +	bvrp.pool.Put(bvr) +	return true +} + +type ejvrState struct { +	mode  mode +	vType bsontype.Type +	depth int +} + +// extJSONValueReader is for reading extended JSON. +type extJSONValueReader struct { +	p *extJSONParser + +	stack []ejvrState +	frame int +} + +// NewExtJSONValueReader creates a new ValueReader from a given io.Reader +// It will interpret the JSON of r as canonical or relaxed according to the +// given canonical flag +func NewExtJSONValueReader(r io.Reader, canonical bool) (ValueReader, error) { +	return newExtJSONValueReader(r, canonical) +} + +func newExtJSONValueReader(r io.Reader, canonical bool) (*extJSONValueReader, error) { +	ejvr := new(extJSONValueReader) +	return ejvr.reset(r, canonical) +} + +func (ejvr *extJSONValueReader) reset(r io.Reader, canonical bool) (*extJSONValueReader, error) { +	p := newExtJSONParser(r, canonical) +	typ, err := p.peekType() + +	if err != nil { +		return nil, ErrInvalidJSON +	} + +	var m mode +	switch typ { +	case bsontype.EmbeddedDocument: +		m = mTopLevel +	case bsontype.Array: +		m = mArray +	default: +		m = mValue +	} + +	stack := make([]ejvrState, 1, 5) +	stack[0] = ejvrState{ +		mode:  m, +		vType: typ, +	} +	return &extJSONValueReader{ +		p:     p, +		stack: stack, +	}, nil +} + +func (ejvr *extJSONValueReader) advanceFrame() { +	if ejvr.frame+1 >= len(ejvr.stack) { // We need to grow the stack +		length := len(ejvr.stack) +		if length+1 >= cap(ejvr.stack) { +			// double it +			buf := make([]ejvrState, 2*cap(ejvr.stack)+1) +			copy(buf, ejvr.stack) +			ejvr.stack = buf +		} +		ejvr.stack = ejvr.stack[:length+1] +	} +	ejvr.frame++ + +	// Clean the stack +	ejvr.stack[ejvr.frame].mode = 0 +	ejvr.stack[ejvr.frame].vType = 0 +	ejvr.stack[ejvr.frame].depth = 0 +} + +func (ejvr *extJSONValueReader) pushDocument() { +	ejvr.advanceFrame() + +	ejvr.stack[ejvr.frame].mode = mDocument +	ejvr.stack[ejvr.frame].depth = ejvr.p.depth +} + +func (ejvr *extJSONValueReader) pushCodeWithScope() { +	ejvr.advanceFrame() + +	ejvr.stack[ejvr.frame].mode = mCodeWithScope +} + +func (ejvr *extJSONValueReader) pushArray() { +	ejvr.advanceFrame() + +	ejvr.stack[ejvr.frame].mode = mArray +} + +func (ejvr *extJSONValueReader) push(m mode, t bsontype.Type) { +	ejvr.advanceFrame() + +	ejvr.stack[ejvr.frame].mode = m +	ejvr.stack[ejvr.frame].vType = t +} + +func (ejvr *extJSONValueReader) pop() { +	switch ejvr.stack[ejvr.frame].mode { +	case mElement, mValue: +		ejvr.frame-- +	case mDocument, mArray, mCodeWithScope: +		ejvr.frame -= 2 // we pop twice to jump over the vrElement: vrDocument -> vrElement -> vrDocument/TopLevel/etc... +	} +} + +func (ejvr *extJSONValueReader) skipObject() { +	// read entire object until depth returns to 0 (last ending } or ] seen) +	depth := 1 +	for depth > 0 { +		ejvr.p.advanceState() + +		// If object is empty, raise depth and continue. When emptyObject is true, the +		// parser has already read both the opening and closing brackets of an empty +		// object ("{}"), so the next valid token will be part of the parent document, +		// not part of the nested document. +		// +		// If there is a comma, there are remaining fields, emptyObject must be set back +		// to false, and comma must be skipped with advanceState(). +		if ejvr.p.emptyObject { +			if ejvr.p.s == jpsSawComma { +				ejvr.p.emptyObject = false +				ejvr.p.advanceState() +			} +			depth-- +			continue +		} + +		switch ejvr.p.s { +		case jpsSawBeginObject, jpsSawBeginArray: +			depth++ +		case jpsSawEndObject, jpsSawEndArray: +			depth-- +		} +	} +} + +func (ejvr *extJSONValueReader) invalidTransitionErr(destination mode, name string, modes []mode) error { +	te := TransitionError{ +		name:        name, +		current:     ejvr.stack[ejvr.frame].mode, +		destination: destination, +		modes:       modes, +		action:      "read", +	} +	if ejvr.frame != 0 { +		te.parent = ejvr.stack[ejvr.frame-1].mode +	} +	return te +} + +func (ejvr *extJSONValueReader) typeError(t bsontype.Type) error { +	return fmt.Errorf("positioned on %s, but attempted to read %s", ejvr.stack[ejvr.frame].vType, t) +} + +func (ejvr *extJSONValueReader) ensureElementValue(t bsontype.Type, destination mode, callerName string, addModes ...mode) error { +	switch ejvr.stack[ejvr.frame].mode { +	case mElement, mValue: +		if ejvr.stack[ejvr.frame].vType != t { +			return ejvr.typeError(t) +		} +	default: +		modes := []mode{mElement, mValue} +		if addModes != nil { +			modes = append(modes, addModes...) +		} +		return ejvr.invalidTransitionErr(destination, callerName, modes) +	} + +	return nil +} + +func (ejvr *extJSONValueReader) Type() bsontype.Type { +	return ejvr.stack[ejvr.frame].vType +} + +func (ejvr *extJSONValueReader) Skip() error { +	switch ejvr.stack[ejvr.frame].mode { +	case mElement, mValue: +	default: +		return ejvr.invalidTransitionErr(0, "Skip", []mode{mElement, mValue}) +	} + +	defer ejvr.pop() + +	t := ejvr.stack[ejvr.frame].vType +	switch t { +	case bsontype.Array, bsontype.EmbeddedDocument, bsontype.CodeWithScope: +		// read entire array, doc or CodeWithScope +		ejvr.skipObject() +	default: +		_, err := ejvr.p.readValue(t) +		if err != nil { +			return err +		} +	} + +	return nil +} + +func (ejvr *extJSONValueReader) ReadArray() (ArrayReader, error) { +	switch ejvr.stack[ejvr.frame].mode { +	case mTopLevel: // allow reading array from top level +	case mArray: +		return ejvr, nil +	default: +		if err := ejvr.ensureElementValue(bsontype.Array, mArray, "ReadArray", mTopLevel, mArray); err != nil { +			return nil, err +		} +	} + +	ejvr.pushArray() + +	return ejvr, nil +} + +func (ejvr *extJSONValueReader) ReadBinary() (b []byte, btype byte, err error) { +	if err := ejvr.ensureElementValue(bsontype.Binary, 0, "ReadBinary"); err != nil { +		return nil, 0, err +	} + +	v, err := ejvr.p.readValue(bsontype.Binary) +	if err != nil { +		return nil, 0, err +	} + +	b, btype, err = v.parseBinary() + +	ejvr.pop() +	return b, btype, err +} + +func (ejvr *extJSONValueReader) ReadBoolean() (bool, error) { +	if err := ejvr.ensureElementValue(bsontype.Boolean, 0, "ReadBoolean"); err != nil { +		return false, err +	} + +	v, err := ejvr.p.readValue(bsontype.Boolean) +	if err != nil { +		return false, err +	} + +	if v.t != bsontype.Boolean { +		return false, fmt.Errorf("expected type bool, but got type %s", v.t) +	} + +	ejvr.pop() +	return v.v.(bool), nil +} + +func (ejvr *extJSONValueReader) ReadDocument() (DocumentReader, error) { +	switch ejvr.stack[ejvr.frame].mode { +	case mTopLevel: +		return ejvr, nil +	case mElement, mValue: +		if ejvr.stack[ejvr.frame].vType != bsontype.EmbeddedDocument { +			return nil, ejvr.typeError(bsontype.EmbeddedDocument) +		} + +		ejvr.pushDocument() +		return ejvr, nil +	default: +		return nil, ejvr.invalidTransitionErr(mDocument, "ReadDocument", []mode{mTopLevel, mElement, mValue}) +	} +} + +func (ejvr *extJSONValueReader) ReadCodeWithScope() (code string, dr DocumentReader, err error) { +	if err = ejvr.ensureElementValue(bsontype.CodeWithScope, 0, "ReadCodeWithScope"); err != nil { +		return "", nil, err +	} + +	v, err := ejvr.p.readValue(bsontype.CodeWithScope) +	if err != nil { +		return "", nil, err +	} + +	code, err = v.parseJavascript() + +	ejvr.pushCodeWithScope() +	return code, ejvr, err +} + +func (ejvr *extJSONValueReader) ReadDBPointer() (ns string, oid primitive.ObjectID, err error) { +	if err = ejvr.ensureElementValue(bsontype.DBPointer, 0, "ReadDBPointer"); err != nil { +		return "", primitive.NilObjectID, err +	} + +	v, err := ejvr.p.readValue(bsontype.DBPointer) +	if err != nil { +		return "", primitive.NilObjectID, err +	} + +	ns, oid, err = v.parseDBPointer() + +	ejvr.pop() +	return ns, oid, err +} + +func (ejvr *extJSONValueReader) ReadDateTime() (int64, error) { +	if err := ejvr.ensureElementValue(bsontype.DateTime, 0, "ReadDateTime"); err != nil { +		return 0, err +	} + +	v, err := ejvr.p.readValue(bsontype.DateTime) +	if err != nil { +		return 0, err +	} + +	d, err := v.parseDateTime() + +	ejvr.pop() +	return d, err +} + +func (ejvr *extJSONValueReader) ReadDecimal128() (primitive.Decimal128, error) { +	if err := ejvr.ensureElementValue(bsontype.Decimal128, 0, "ReadDecimal128"); err != nil { +		return primitive.Decimal128{}, err +	} + +	v, err := ejvr.p.readValue(bsontype.Decimal128) +	if err != nil { +		return primitive.Decimal128{}, err +	} + +	d, err := v.parseDecimal128() + +	ejvr.pop() +	return d, err +} + +func (ejvr *extJSONValueReader) ReadDouble() (float64, error) { +	if err := ejvr.ensureElementValue(bsontype.Double, 0, "ReadDouble"); err != nil { +		return 0, err +	} + +	v, err := ejvr.p.readValue(bsontype.Double) +	if err != nil { +		return 0, err +	} + +	d, err := v.parseDouble() + +	ejvr.pop() +	return d, err +} + +func (ejvr *extJSONValueReader) ReadInt32() (int32, error) { +	if err := ejvr.ensureElementValue(bsontype.Int32, 0, "ReadInt32"); err != nil { +		return 0, err +	} + +	v, err := ejvr.p.readValue(bsontype.Int32) +	if err != nil { +		return 0, err +	} + +	i, err := v.parseInt32() + +	ejvr.pop() +	return i, err +} + +func (ejvr *extJSONValueReader) ReadInt64() (int64, error) { +	if err := ejvr.ensureElementValue(bsontype.Int64, 0, "ReadInt64"); err != nil { +		return 0, err +	} + +	v, err := ejvr.p.readValue(bsontype.Int64) +	if err != nil { +		return 0, err +	} + +	i, err := v.parseInt64() + +	ejvr.pop() +	return i, err +} + +func (ejvr *extJSONValueReader) ReadJavascript() (code string, err error) { +	if err = ejvr.ensureElementValue(bsontype.JavaScript, 0, "ReadJavascript"); err != nil { +		return "", err +	} + +	v, err := ejvr.p.readValue(bsontype.JavaScript) +	if err != nil { +		return "", err +	} + +	code, err = v.parseJavascript() + +	ejvr.pop() +	return code, err +} + +func (ejvr *extJSONValueReader) ReadMaxKey() error { +	if err := ejvr.ensureElementValue(bsontype.MaxKey, 0, "ReadMaxKey"); err != nil { +		return err +	} + +	v, err := ejvr.p.readValue(bsontype.MaxKey) +	if err != nil { +		return err +	} + +	err = v.parseMinMaxKey("max") + +	ejvr.pop() +	return err +} + +func (ejvr *extJSONValueReader) ReadMinKey() error { +	if err := ejvr.ensureElementValue(bsontype.MinKey, 0, "ReadMinKey"); err != nil { +		return err +	} + +	v, err := ejvr.p.readValue(bsontype.MinKey) +	if err != nil { +		return err +	} + +	err = v.parseMinMaxKey("min") + +	ejvr.pop() +	return err +} + +func (ejvr *extJSONValueReader) ReadNull() error { +	if err := ejvr.ensureElementValue(bsontype.Null, 0, "ReadNull"); err != nil { +		return err +	} + +	v, err := ejvr.p.readValue(bsontype.Null) +	if err != nil { +		return err +	} + +	if v.t != bsontype.Null { +		return fmt.Errorf("expected type null but got type %s", v.t) +	} + +	ejvr.pop() +	return nil +} + +func (ejvr *extJSONValueReader) ReadObjectID() (primitive.ObjectID, error) { +	if err := ejvr.ensureElementValue(bsontype.ObjectID, 0, "ReadObjectID"); err != nil { +		return primitive.ObjectID{}, err +	} + +	v, err := ejvr.p.readValue(bsontype.ObjectID) +	if err != nil { +		return primitive.ObjectID{}, err +	} + +	oid, err := v.parseObjectID() + +	ejvr.pop() +	return oid, err +} + +func (ejvr *extJSONValueReader) ReadRegex() (pattern string, options string, err error) { +	if err = ejvr.ensureElementValue(bsontype.Regex, 0, "ReadRegex"); err != nil { +		return "", "", err +	} + +	v, err := ejvr.p.readValue(bsontype.Regex) +	if err != nil { +		return "", "", err +	} + +	pattern, options, err = v.parseRegex() + +	ejvr.pop() +	return pattern, options, err +} + +func (ejvr *extJSONValueReader) ReadString() (string, error) { +	if err := ejvr.ensureElementValue(bsontype.String, 0, "ReadString"); err != nil { +		return "", err +	} + +	v, err := ejvr.p.readValue(bsontype.String) +	if err != nil { +		return "", err +	} + +	if v.t != bsontype.String { +		return "", fmt.Errorf("expected type string but got type %s", v.t) +	} + +	ejvr.pop() +	return v.v.(string), nil +} + +func (ejvr *extJSONValueReader) ReadSymbol() (symbol string, err error) { +	if err = ejvr.ensureElementValue(bsontype.Symbol, 0, "ReadSymbol"); err != nil { +		return "", err +	} + +	v, err := ejvr.p.readValue(bsontype.Symbol) +	if err != nil { +		return "", err +	} + +	symbol, err = v.parseSymbol() + +	ejvr.pop() +	return symbol, err +} + +func (ejvr *extJSONValueReader) ReadTimestamp() (t uint32, i uint32, err error) { +	if err = ejvr.ensureElementValue(bsontype.Timestamp, 0, "ReadTimestamp"); err != nil { +		return 0, 0, err +	} + +	v, err := ejvr.p.readValue(bsontype.Timestamp) +	if err != nil { +		return 0, 0, err +	} + +	t, i, err = v.parseTimestamp() + +	ejvr.pop() +	return t, i, err +} + +func (ejvr *extJSONValueReader) ReadUndefined() error { +	if err := ejvr.ensureElementValue(bsontype.Undefined, 0, "ReadUndefined"); err != nil { +		return err +	} + +	v, err := ejvr.p.readValue(bsontype.Undefined) +	if err != nil { +		return err +	} + +	err = v.parseUndefined() + +	ejvr.pop() +	return err +} + +func (ejvr *extJSONValueReader) ReadElement() (string, ValueReader, error) { +	switch ejvr.stack[ejvr.frame].mode { +	case mTopLevel, mDocument, mCodeWithScope: +	default: +		return "", nil, ejvr.invalidTransitionErr(mElement, "ReadElement", []mode{mTopLevel, mDocument, mCodeWithScope}) +	} + +	name, t, err := ejvr.p.readKey() + +	if err != nil { +		if err == ErrEOD { +			if ejvr.stack[ejvr.frame].mode == mCodeWithScope { +				_, err := ejvr.p.peekType() +				if err != nil { +					return "", nil, err +				} +			} + +			ejvr.pop() +		} + +		return "", nil, err +	} + +	ejvr.push(mElement, t) +	return name, ejvr, nil +} + +func (ejvr *extJSONValueReader) ReadValue() (ValueReader, error) { +	switch ejvr.stack[ejvr.frame].mode { +	case mArray: +	default: +		return nil, ejvr.invalidTransitionErr(mValue, "ReadValue", []mode{mArray}) +	} + +	t, err := ejvr.p.peekType() +	if err != nil { +		if err == ErrEOA { +			ejvr.pop() +		} + +		return nil, err +	} + +	ejvr.push(mValue, t) +	return ejvr, nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_tables.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_tables.go new file mode 100644 index 000000000..ba39c9601 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_tables.go @@ -0,0 +1,223 @@ +// 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 +// +// Based on github.com/golang/go by The Go Authors +// See THIRD-PARTY-NOTICES for original license terms. + +package bsonrw + +import "unicode/utf8" + +// safeSet holds the value true if the ASCII character with the given array +// position can be represented inside a JSON string without any further +// escaping. +// +// All values are true except for the ASCII control characters (0-31), the +// double quote ("), and the backslash character ("\"). +var safeSet = [utf8.RuneSelf]bool{ +	' ':      true, +	'!':      true, +	'"':      false, +	'#':      true, +	'$':      true, +	'%':      true, +	'&':      true, +	'\'':     true, +	'(':      true, +	')':      true, +	'*':      true, +	'+':      true, +	',':      true, +	'-':      true, +	'.':      true, +	'/':      true, +	'0':      true, +	'1':      true, +	'2':      true, +	'3':      true, +	'4':      true, +	'5':      true, +	'6':      true, +	'7':      true, +	'8':      true, +	'9':      true, +	':':      true, +	';':      true, +	'<':      true, +	'=':      true, +	'>':      true, +	'?':      true, +	'@':      true, +	'A':      true, +	'B':      true, +	'C':      true, +	'D':      true, +	'E':      true, +	'F':      true, +	'G':      true, +	'H':      true, +	'I':      true, +	'J':      true, +	'K':      true, +	'L':      true, +	'M':      true, +	'N':      true, +	'O':      true, +	'P':      true, +	'Q':      true, +	'R':      true, +	'S':      true, +	'T':      true, +	'U':      true, +	'V':      true, +	'W':      true, +	'X':      true, +	'Y':      true, +	'Z':      true, +	'[':      true, +	'\\':     false, +	']':      true, +	'^':      true, +	'_':      true, +	'`':      true, +	'a':      true, +	'b':      true, +	'c':      true, +	'd':      true, +	'e':      true, +	'f':      true, +	'g':      true, +	'h':      true, +	'i':      true, +	'j':      true, +	'k':      true, +	'l':      true, +	'm':      true, +	'n':      true, +	'o':      true, +	'p':      true, +	'q':      true, +	'r':      true, +	's':      true, +	't':      true, +	'u':      true, +	'v':      true, +	'w':      true, +	'x':      true, +	'y':      true, +	'z':      true, +	'{':      true, +	'|':      true, +	'}':      true, +	'~':      true, +	'\u007f': true, +} + +// htmlSafeSet holds the value true if the ASCII character with the given +// array position can be safely represented inside a JSON string, embedded +// inside of HTML <script> tags, without any additional escaping. +// +// All values are true except for the ASCII control characters (0-31), the +// double quote ("), the backslash character ("\"), HTML opening and closing +// tags ("<" and ">"), and the ampersand ("&"). +var htmlSafeSet = [utf8.RuneSelf]bool{ +	' ':      true, +	'!':      true, +	'"':      false, +	'#':      true, +	'$':      true, +	'%':      true, +	'&':      false, +	'\'':     true, +	'(':      true, +	')':      true, +	'*':      true, +	'+':      true, +	',':      true, +	'-':      true, +	'.':      true, +	'/':      true, +	'0':      true, +	'1':      true, +	'2':      true, +	'3':      true, +	'4':      true, +	'5':      true, +	'6':      true, +	'7':      true, +	'8':      true, +	'9':      true, +	':':      true, +	';':      true, +	'<':      false, +	'=':      true, +	'>':      false, +	'?':      true, +	'@':      true, +	'A':      true, +	'B':      true, +	'C':      true, +	'D':      true, +	'E':      true, +	'F':      true, +	'G':      true, +	'H':      true, +	'I':      true, +	'J':      true, +	'K':      true, +	'L':      true, +	'M':      true, +	'N':      true, +	'O':      true, +	'P':      true, +	'Q':      true, +	'R':      true, +	'S':      true, +	'T':      true, +	'U':      true, +	'V':      true, +	'W':      true, +	'X':      true, +	'Y':      true, +	'Z':      true, +	'[':      true, +	'\\':     false, +	']':      true, +	'^':      true, +	'_':      true, +	'`':      true, +	'a':      true, +	'b':      true, +	'c':      true, +	'd':      true, +	'e':      true, +	'f':      true, +	'g':      true, +	'h':      true, +	'i':      true, +	'j':      true, +	'k':      true, +	'l':      true, +	'm':      true, +	'n':      true, +	'o':      true, +	'p':      true, +	'q':      true, +	'r':      true, +	's':      true, +	't':      true, +	'u':      true, +	'v':      true, +	'w':      true, +	'x':      true, +	'y':      true, +	'z':      true, +	'{':      true, +	'|':      true, +	'}':      true, +	'~':      true, +	'\u007f': true, +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_wrappers.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_wrappers.go new file mode 100644 index 000000000..969570424 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_wrappers.go @@ -0,0 +1,492 @@ +// 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 bsonrw + +import ( +	"encoding/base64" +	"errors" +	"fmt" +	"math" +	"strconv" +	"time" + +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +func wrapperKeyBSONType(key string) bsontype.Type { +	switch key { +	case "$numberInt": +		return bsontype.Int32 +	case "$numberLong": +		return bsontype.Int64 +	case "$oid": +		return bsontype.ObjectID +	case "$symbol": +		return bsontype.Symbol +	case "$numberDouble": +		return bsontype.Double +	case "$numberDecimal": +		return bsontype.Decimal128 +	case "$binary": +		return bsontype.Binary +	case "$code": +		return bsontype.JavaScript +	case "$scope": +		return bsontype.CodeWithScope +	case "$timestamp": +		return bsontype.Timestamp +	case "$regularExpression": +		return bsontype.Regex +	case "$dbPointer": +		return bsontype.DBPointer +	case "$date": +		return bsontype.DateTime +	case "$minKey": +		return bsontype.MinKey +	case "$maxKey": +		return bsontype.MaxKey +	case "$undefined": +		return bsontype.Undefined +	} + +	return bsontype.EmbeddedDocument +} + +func (ejv *extJSONValue) parseBinary() (b []byte, subType byte, err error) { +	if ejv.t != bsontype.EmbeddedDocument { +		return nil, 0, fmt.Errorf("$binary value should be object, but instead is %s", ejv.t) +	} + +	binObj := ejv.v.(*extJSONObject) +	bFound := false +	stFound := false + +	for i, key := range binObj.keys { +		val := binObj.values[i] + +		switch key { +		case "base64": +			if bFound { +				return nil, 0, errors.New("duplicate base64 key in $binary") +			} + +			if val.t != bsontype.String { +				return nil, 0, fmt.Errorf("$binary base64 value should be string, but instead is %s", val.t) +			} + +			base64Bytes, err := base64.StdEncoding.DecodeString(val.v.(string)) +			if err != nil { +				return nil, 0, fmt.Errorf("invalid $binary base64 string: %s", val.v.(string)) +			} + +			b = base64Bytes +			bFound = true +		case "subType": +			if stFound { +				return nil, 0, errors.New("duplicate subType key in $binary") +			} + +			if val.t != bsontype.String { +				return nil, 0, fmt.Errorf("$binary subType value should be string, but instead is %s", val.t) +			} + +			i, err := strconv.ParseInt(val.v.(string), 16, 64) +			if err != nil { +				return nil, 0, fmt.Errorf("invalid $binary subType string: %s", val.v.(string)) +			} + +			subType = byte(i) +			stFound = true +		default: +			return nil, 0, fmt.Errorf("invalid key in $binary object: %s", key) +		} +	} + +	if !bFound { +		return nil, 0, errors.New("missing base64 field in $binary object") +	} + +	if !stFound { +		return nil, 0, errors.New("missing subType field in $binary object") + +	} + +	return b, subType, nil +} + +func (ejv *extJSONValue) parseDBPointer() (ns string, oid primitive.ObjectID, err error) { +	if ejv.t != bsontype.EmbeddedDocument { +		return "", primitive.NilObjectID, fmt.Errorf("$dbPointer value should be object, but instead is %s", ejv.t) +	} + +	dbpObj := ejv.v.(*extJSONObject) +	oidFound := false +	nsFound := false + +	for i, key := range dbpObj.keys { +		val := dbpObj.values[i] + +		switch key { +		case "$ref": +			if nsFound { +				return "", primitive.NilObjectID, errors.New("duplicate $ref key in $dbPointer") +			} + +			if val.t != bsontype.String { +				return "", primitive.NilObjectID, fmt.Errorf("$dbPointer $ref value should be string, but instead is %s", val.t) +			} + +			ns = val.v.(string) +			nsFound = true +		case "$id": +			if oidFound { +				return "", primitive.NilObjectID, errors.New("duplicate $id key in $dbPointer") +			} + +			if val.t != bsontype.String { +				return "", primitive.NilObjectID, fmt.Errorf("$dbPointer $id value should be string, but instead is %s", val.t) +			} + +			oid, err = primitive.ObjectIDFromHex(val.v.(string)) +			if err != nil { +				return "", primitive.NilObjectID, err +			} + +			oidFound = true +		default: +			return "", primitive.NilObjectID, fmt.Errorf("invalid key in $dbPointer object: %s", key) +		} +	} + +	if !nsFound { +		return "", oid, errors.New("missing $ref field in $dbPointer object") +	} + +	if !oidFound { +		return "", oid, errors.New("missing $id field in $dbPointer object") +	} + +	return ns, oid, nil +} + +const ( +	rfc3339Milli = "2006-01-02T15:04:05.999Z07:00" +) + +var ( +	timeFormats = []string{rfc3339Milli, "2006-01-02T15:04:05.999Z0700"} +) + +func (ejv *extJSONValue) parseDateTime() (int64, error) { +	switch ejv.t { +	case bsontype.Int32: +		return int64(ejv.v.(int32)), nil +	case bsontype.Int64: +		return ejv.v.(int64), nil +	case bsontype.String: +		return parseDatetimeString(ejv.v.(string)) +	case bsontype.EmbeddedDocument: +		return parseDatetimeObject(ejv.v.(*extJSONObject)) +	default: +		return 0, fmt.Errorf("$date value should be string or object, but instead is %s", ejv.t) +	} +} + +func parseDatetimeString(data string) (int64, error) { +	var t time.Time +	var err error +	// try acceptable time formats until one matches +	for _, format := range timeFormats { +		t, err = time.Parse(format, data) +		if err == nil { +			break +		} +	} +	if err != nil { +		return 0, fmt.Errorf("invalid $date value string: %s", data) +	} + +	return int64(primitive.NewDateTimeFromTime(t)), nil +} + +func parseDatetimeObject(data *extJSONObject) (d int64, err error) { +	dFound := false + +	for i, key := range data.keys { +		val := data.values[i] + +		switch key { +		case "$numberLong": +			if dFound { +				return 0, errors.New("duplicate $numberLong key in $date") +			} + +			if val.t != bsontype.String { +				return 0, fmt.Errorf("$date $numberLong field should be string, but instead is %s", val.t) +			} + +			d, err = val.parseInt64() +			if err != nil { +				return 0, err +			} +			dFound = true +		default: +			return 0, fmt.Errorf("invalid key in $date object: %s", key) +		} +	} + +	if !dFound { +		return 0, errors.New("missing $numberLong field in $date object") +	} + +	return d, nil +} + +func (ejv *extJSONValue) parseDecimal128() (primitive.Decimal128, error) { +	if ejv.t != bsontype.String { +		return primitive.Decimal128{}, fmt.Errorf("$numberDecimal value should be string, but instead is %s", ejv.t) +	} + +	d, err := primitive.ParseDecimal128(ejv.v.(string)) +	if err != nil { +		return primitive.Decimal128{}, fmt.Errorf("$invalid $numberDecimal string: %s", ejv.v.(string)) +	} + +	return d, nil +} + +func (ejv *extJSONValue) parseDouble() (float64, error) { +	if ejv.t == bsontype.Double { +		return ejv.v.(float64), nil +	} + +	if ejv.t != bsontype.String { +		return 0, fmt.Errorf("$numberDouble value should be string, but instead is %s", ejv.t) +	} + +	switch ejv.v.(string) { +	case "Infinity": +		return math.Inf(1), nil +	case "-Infinity": +		return math.Inf(-1), nil +	case "NaN": +		return math.NaN(), nil +	} + +	f, err := strconv.ParseFloat(ejv.v.(string), 64) +	if err != nil { +		return 0, err +	} + +	return f, nil +} + +func (ejv *extJSONValue) parseInt32() (int32, error) { +	if ejv.t == bsontype.Int32 { +		return ejv.v.(int32), nil +	} + +	if ejv.t != bsontype.String { +		return 0, fmt.Errorf("$numberInt value should be string, but instead is %s", ejv.t) +	} + +	i, err := strconv.ParseInt(ejv.v.(string), 10, 64) +	if err != nil { +		return 0, err +	} + +	if i < math.MinInt32 || i > math.MaxInt32 { +		return 0, fmt.Errorf("$numberInt value should be int32 but instead is int64: %d", i) +	} + +	return int32(i), nil +} + +func (ejv *extJSONValue) parseInt64() (int64, error) { +	if ejv.t == bsontype.Int64 { +		return ejv.v.(int64), nil +	} + +	if ejv.t != bsontype.String { +		return 0, fmt.Errorf("$numberLong value should be string, but instead is %s", ejv.t) +	} + +	i, err := strconv.ParseInt(ejv.v.(string), 10, 64) +	if err != nil { +		return 0, err +	} + +	return i, nil +} + +func (ejv *extJSONValue) parseJavascript() (code string, err error) { +	if ejv.t != bsontype.String { +		return "", fmt.Errorf("$code value should be string, but instead is %s", ejv.t) +	} + +	return ejv.v.(string), nil +} + +func (ejv *extJSONValue) parseMinMaxKey(minmax string) error { +	if ejv.t != bsontype.Int32 { +		return fmt.Errorf("$%sKey value should be int32, but instead is %s", minmax, ejv.t) +	} + +	if ejv.v.(int32) != 1 { +		return fmt.Errorf("$%sKey value must be 1, but instead is %d", minmax, ejv.v.(int32)) +	} + +	return nil +} + +func (ejv *extJSONValue) parseObjectID() (primitive.ObjectID, error) { +	if ejv.t != bsontype.String { +		return primitive.NilObjectID, fmt.Errorf("$oid value should be string, but instead is %s", ejv.t) +	} + +	return primitive.ObjectIDFromHex(ejv.v.(string)) +} + +func (ejv *extJSONValue) parseRegex() (pattern, options string, err error) { +	if ejv.t != bsontype.EmbeddedDocument { +		return "", "", fmt.Errorf("$regularExpression value should be object, but instead is %s", ejv.t) +	} + +	regexObj := ejv.v.(*extJSONObject) +	patFound := false +	optFound := false + +	for i, key := range regexObj.keys { +		val := regexObj.values[i] + +		switch key { +		case "pattern": +			if patFound { +				return "", "", errors.New("duplicate pattern key in $regularExpression") +			} + +			if val.t != bsontype.String { +				return "", "", fmt.Errorf("$regularExpression pattern value should be string, but instead is %s", val.t) +			} + +			pattern = val.v.(string) +			patFound = true +		case "options": +			if optFound { +				return "", "", errors.New("duplicate options key in $regularExpression") +			} + +			if val.t != bsontype.String { +				return "", "", fmt.Errorf("$regularExpression options value should be string, but instead is %s", val.t) +			} + +			options = val.v.(string) +			optFound = true +		default: +			return "", "", fmt.Errorf("invalid key in $regularExpression object: %s", key) +		} +	} + +	if !patFound { +		return "", "", errors.New("missing pattern field in $regularExpression object") +	} + +	if !optFound { +		return "", "", errors.New("missing options field in $regularExpression object") + +	} + +	return pattern, options, nil +} + +func (ejv *extJSONValue) parseSymbol() (string, error) { +	if ejv.t != bsontype.String { +		return "", fmt.Errorf("$symbol value should be string, but instead is %s", ejv.t) +	} + +	return ejv.v.(string), nil +} + +func (ejv *extJSONValue) parseTimestamp() (t, i uint32, err error) { +	if ejv.t != bsontype.EmbeddedDocument { +		return 0, 0, fmt.Errorf("$timestamp value should be object, but instead is %s", ejv.t) +	} + +	handleKey := func(key string, val *extJSONValue, flag bool) (uint32, error) { +		if flag { +			return 0, fmt.Errorf("duplicate %s key in $timestamp", key) +		} + +		switch val.t { +		case bsontype.Int32: +			value := val.v.(int32) + +			if value < 0 { +				return 0, fmt.Errorf("$timestamp %s number should be uint32: %d", key, value) +			} + +			return uint32(value), nil +		case bsontype.Int64: +			value := val.v.(int64) +			if value < 0 || value > int64(math.MaxUint32) { +				return 0, fmt.Errorf("$timestamp %s number should be uint32: %d", key, value) +			} + +			return uint32(value), nil +		default: +			return 0, fmt.Errorf("$timestamp %s value should be uint32, but instead is %s", key, val.t) +		} +	} + +	tsObj := ejv.v.(*extJSONObject) +	tFound := false +	iFound := false + +	for j, key := range tsObj.keys { +		val := tsObj.values[j] + +		switch key { +		case "t": +			if t, err = handleKey(key, val, tFound); err != nil { +				return 0, 0, err +			} + +			tFound = true +		case "i": +			if i, err = handleKey(key, val, iFound); err != nil { +				return 0, 0, err +			} + +			iFound = true +		default: +			return 0, 0, fmt.Errorf("invalid key in $timestamp object: %s", key) +		} +	} + +	if !tFound { +		return 0, 0, errors.New("missing t field in $timestamp object") +	} + +	if !iFound { +		return 0, 0, errors.New("missing i field in $timestamp object") +	} + +	return t, i, nil +} + +func (ejv *extJSONValue) parseUndefined() error { +	if ejv.t != bsontype.Boolean { +		return fmt.Errorf("undefined value should be boolean, but instead is %s", ejv.t) +	} + +	if !ejv.v.(bool) { +		return fmt.Errorf("$undefined balue boolean should be true, but instead is %v", ejv.v.(bool)) +	} + +	return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go new file mode 100644 index 000000000..99ed524b7 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go @@ -0,0 +1,732 @@ +// 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 bsonrw + +import ( +	"bytes" +	"encoding/base64" +	"fmt" +	"io" +	"math" +	"sort" +	"strconv" +	"strings" +	"sync" +	"time" +	"unicode/utf8" + +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +// ExtJSONValueWriterPool is a pool for ExtJSON ValueWriters. +type ExtJSONValueWriterPool struct { +	pool sync.Pool +} + +// NewExtJSONValueWriterPool creates a new pool for ValueWriter instances that write to ExtJSON. +func NewExtJSONValueWriterPool() *ExtJSONValueWriterPool { +	return &ExtJSONValueWriterPool{ +		pool: sync.Pool{ +			New: func() interface{} { +				return new(extJSONValueWriter) +			}, +		}, +	} +} + +// Get retrieves a ExtJSON ValueWriter from the pool and resets it to use w as the destination. +func (bvwp *ExtJSONValueWriterPool) Get(w io.Writer, canonical, escapeHTML bool) ValueWriter { +	vw := bvwp.pool.Get().(*extJSONValueWriter) +	if writer, ok := w.(*SliceWriter); ok { +		vw.reset(*writer, canonical, escapeHTML) +		vw.w = writer +		return vw +	} +	vw.buf = vw.buf[:0] +	vw.w = w +	return vw +} + +// Put inserts a ValueWriter into the pool. If the ValueWriter is not a ExtJSON ValueWriter, nothing +// happens and ok will be false. +func (bvwp *ExtJSONValueWriterPool) Put(vw ValueWriter) (ok bool) { +	bvw, ok := vw.(*extJSONValueWriter) +	if !ok { +		return false +	} + +	if _, ok := bvw.w.(*SliceWriter); ok { +		bvw.buf = nil +	} +	bvw.w = nil + +	bvwp.pool.Put(bvw) +	return true +} + +type ejvwState struct { +	mode mode +} + +type extJSONValueWriter struct { +	w   io.Writer +	buf []byte + +	stack      []ejvwState +	frame      int64 +	canonical  bool +	escapeHTML bool +} + +// NewExtJSONValueWriter creates a ValueWriter that writes Extended JSON to w. +func NewExtJSONValueWriter(w io.Writer, canonical, escapeHTML bool) (ValueWriter, error) { +	if w == nil { +		return nil, errNilWriter +	} + +	return newExtJSONWriter(w, canonical, escapeHTML), nil +} + +func newExtJSONWriter(w io.Writer, canonical, escapeHTML bool) *extJSONValueWriter { +	stack := make([]ejvwState, 1, 5) +	stack[0] = ejvwState{mode: mTopLevel} + +	return &extJSONValueWriter{ +		w:          w, +		buf:        []byte{}, +		stack:      stack, +		canonical:  canonical, +		escapeHTML: escapeHTML, +	} +} + +func newExtJSONWriterFromSlice(buf []byte, canonical, escapeHTML bool) *extJSONValueWriter { +	stack := make([]ejvwState, 1, 5) +	stack[0] = ejvwState{mode: mTopLevel} + +	return &extJSONValueWriter{ +		buf:        buf, +		stack:      stack, +		canonical:  canonical, +		escapeHTML: escapeHTML, +	} +} + +func (ejvw *extJSONValueWriter) reset(buf []byte, canonical, escapeHTML bool) { +	if ejvw.stack == nil { +		ejvw.stack = make([]ejvwState, 1, 5) +	} + +	ejvw.stack = ejvw.stack[:1] +	ejvw.stack[0] = ejvwState{mode: mTopLevel} +	ejvw.canonical = canonical +	ejvw.escapeHTML = escapeHTML +	ejvw.frame = 0 +	ejvw.buf = buf +	ejvw.w = nil +} + +func (ejvw *extJSONValueWriter) advanceFrame() { +	if ejvw.frame+1 >= int64(len(ejvw.stack)) { // We need to grow the stack +		length := len(ejvw.stack) +		if length+1 >= cap(ejvw.stack) { +			// double it +			buf := make([]ejvwState, 2*cap(ejvw.stack)+1) +			copy(buf, ejvw.stack) +			ejvw.stack = buf +		} +		ejvw.stack = ejvw.stack[:length+1] +	} +	ejvw.frame++ +} + +func (ejvw *extJSONValueWriter) push(m mode) { +	ejvw.advanceFrame() + +	ejvw.stack[ejvw.frame].mode = m +} + +func (ejvw *extJSONValueWriter) pop() { +	switch ejvw.stack[ejvw.frame].mode { +	case mElement, mValue: +		ejvw.frame-- +	case mDocument, mArray, mCodeWithScope: +		ejvw.frame -= 2 // we pop twice to jump over the mElement: mDocument -> mElement -> mDocument/mTopLevel/etc... +	} +} + +func (ejvw *extJSONValueWriter) invalidTransitionErr(destination mode, name string, modes []mode) error { +	te := TransitionError{ +		name:        name, +		current:     ejvw.stack[ejvw.frame].mode, +		destination: destination, +		modes:       modes, +		action:      "write", +	} +	if ejvw.frame != 0 { +		te.parent = ejvw.stack[ejvw.frame-1].mode +	} +	return te +} + +func (ejvw *extJSONValueWriter) ensureElementValue(destination mode, callerName string, addmodes ...mode) error { +	switch ejvw.stack[ejvw.frame].mode { +	case mElement, mValue: +	default: +		modes := []mode{mElement, mValue} +		if addmodes != nil { +			modes = append(modes, addmodes...) +		} +		return ejvw.invalidTransitionErr(destination, callerName, modes) +	} + +	return nil +} + +func (ejvw *extJSONValueWriter) writeExtendedSingleValue(key string, value string, quotes bool) { +	var s string +	if quotes { +		s = fmt.Sprintf(`{"$%s":"%s"}`, key, value) +	} else { +		s = fmt.Sprintf(`{"$%s":%s}`, key, value) +	} + +	ejvw.buf = append(ejvw.buf, []byte(s)...) +} + +func (ejvw *extJSONValueWriter) WriteArray() (ArrayWriter, error) { +	if err := ejvw.ensureElementValue(mArray, "WriteArray"); err != nil { +		return nil, err +	} + +	ejvw.buf = append(ejvw.buf, '[') + +	ejvw.push(mArray) +	return ejvw, nil +} + +func (ejvw *extJSONValueWriter) WriteBinary(b []byte) error { +	return ejvw.WriteBinaryWithSubtype(b, 0x00) +} + +func (ejvw *extJSONValueWriter) WriteBinaryWithSubtype(b []byte, btype byte) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteBinaryWithSubtype"); err != nil { +		return err +	} + +	var buf bytes.Buffer +	buf.WriteString(`{"$binary":{"base64":"`) +	buf.WriteString(base64.StdEncoding.EncodeToString(b)) +	buf.WriteString(fmt.Sprintf(`","subType":"%02x"}},`, btype)) + +	ejvw.buf = append(ejvw.buf, buf.Bytes()...) + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteBoolean(b bool) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteBoolean"); err != nil { +		return err +	} + +	ejvw.buf = append(ejvw.buf, []byte(strconv.FormatBool(b))...) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteCodeWithScope(code string) (DocumentWriter, error) { +	if err := ejvw.ensureElementValue(mCodeWithScope, "WriteCodeWithScope"); err != nil { +		return nil, err +	} + +	var buf bytes.Buffer +	buf.WriteString(`{"$code":`) +	writeStringWithEscapes(code, &buf, ejvw.escapeHTML) +	buf.WriteString(`,"$scope":{`) + +	ejvw.buf = append(ejvw.buf, buf.Bytes()...) + +	ejvw.push(mCodeWithScope) +	return ejvw, nil +} + +func (ejvw *extJSONValueWriter) WriteDBPointer(ns string, oid primitive.ObjectID) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteDBPointer"); err != nil { +		return err +	} + +	var buf bytes.Buffer +	buf.WriteString(`{"$dbPointer":{"$ref":"`) +	buf.WriteString(ns) +	buf.WriteString(`","$id":{"$oid":"`) +	buf.WriteString(oid.Hex()) +	buf.WriteString(`"}}},`) + +	ejvw.buf = append(ejvw.buf, buf.Bytes()...) + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteDateTime(dt int64) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteDateTime"); err != nil { +		return err +	} + +	t := time.Unix(dt/1e3, dt%1e3*1e6).UTC() + +	if ejvw.canonical || t.Year() < 1970 || t.Year() > 9999 { +		s := fmt.Sprintf(`{"$numberLong":"%d"}`, dt) +		ejvw.writeExtendedSingleValue("date", s, false) +	} else { +		ejvw.writeExtendedSingleValue("date", t.Format(rfc3339Milli), true) +	} + +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteDecimal128(d primitive.Decimal128) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteDecimal128"); err != nil { +		return err +	} + +	ejvw.writeExtendedSingleValue("numberDecimal", d.String(), true) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteDocument() (DocumentWriter, error) { +	if ejvw.stack[ejvw.frame].mode == mTopLevel { +		ejvw.buf = append(ejvw.buf, '{') +		return ejvw, nil +	} + +	if err := ejvw.ensureElementValue(mDocument, "WriteDocument", mTopLevel); err != nil { +		return nil, err +	} + +	ejvw.buf = append(ejvw.buf, '{') +	ejvw.push(mDocument) +	return ejvw, nil +} + +func (ejvw *extJSONValueWriter) WriteDouble(f float64) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteDouble"); err != nil { +		return err +	} + +	s := formatDouble(f) + +	if ejvw.canonical { +		ejvw.writeExtendedSingleValue("numberDouble", s, true) +	} else { +		switch s { +		case "Infinity": +			fallthrough +		case "-Infinity": +			fallthrough +		case "NaN": +			s = fmt.Sprintf(`{"$numberDouble":"%s"}`, s) +		} +		ejvw.buf = append(ejvw.buf, []byte(s)...) +	} + +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteInt32(i int32) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteInt32"); err != nil { +		return err +	} + +	s := strconv.FormatInt(int64(i), 10) + +	if ejvw.canonical { +		ejvw.writeExtendedSingleValue("numberInt", s, true) +	} else { +		ejvw.buf = append(ejvw.buf, []byte(s)...) +	} + +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteInt64(i int64) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteInt64"); err != nil { +		return err +	} + +	s := strconv.FormatInt(i, 10) + +	if ejvw.canonical { +		ejvw.writeExtendedSingleValue("numberLong", s, true) +	} else { +		ejvw.buf = append(ejvw.buf, []byte(s)...) +	} + +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteJavascript(code string) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteJavascript"); err != nil { +		return err +	} + +	var buf bytes.Buffer +	writeStringWithEscapes(code, &buf, ejvw.escapeHTML) + +	ejvw.writeExtendedSingleValue("code", buf.String(), false) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteMaxKey() error { +	if err := ejvw.ensureElementValue(mode(0), "WriteMaxKey"); err != nil { +		return err +	} + +	ejvw.writeExtendedSingleValue("maxKey", "1", false) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteMinKey() error { +	if err := ejvw.ensureElementValue(mode(0), "WriteMinKey"); err != nil { +		return err +	} + +	ejvw.writeExtendedSingleValue("minKey", "1", false) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteNull() error { +	if err := ejvw.ensureElementValue(mode(0), "WriteNull"); err != nil { +		return err +	} + +	ejvw.buf = append(ejvw.buf, []byte("null")...) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteObjectID(oid primitive.ObjectID) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteObjectID"); err != nil { +		return err +	} + +	ejvw.writeExtendedSingleValue("oid", oid.Hex(), true) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteRegex(pattern string, options string) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteRegex"); err != nil { +		return err +	} + +	var buf bytes.Buffer +	buf.WriteString(`{"$regularExpression":{"pattern":`) +	writeStringWithEscapes(pattern, &buf, ejvw.escapeHTML) +	buf.WriteString(`,"options":"`) +	buf.WriteString(sortStringAlphebeticAscending(options)) +	buf.WriteString(`"}},`) + +	ejvw.buf = append(ejvw.buf, buf.Bytes()...) + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteString(s string) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteString"); err != nil { +		return err +	} + +	var buf bytes.Buffer +	writeStringWithEscapes(s, &buf, ejvw.escapeHTML) + +	ejvw.buf = append(ejvw.buf, buf.Bytes()...) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteSymbol(symbol string) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteSymbol"); err != nil { +		return err +	} + +	var buf bytes.Buffer +	writeStringWithEscapes(symbol, &buf, ejvw.escapeHTML) + +	ejvw.writeExtendedSingleValue("symbol", buf.String(), false) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteTimestamp(t uint32, i uint32) error { +	if err := ejvw.ensureElementValue(mode(0), "WriteTimestamp"); err != nil { +		return err +	} + +	var buf bytes.Buffer +	buf.WriteString(`{"$timestamp":{"t":`) +	buf.WriteString(strconv.FormatUint(uint64(t), 10)) +	buf.WriteString(`,"i":`) +	buf.WriteString(strconv.FormatUint(uint64(i), 10)) +	buf.WriteString(`}},`) + +	ejvw.buf = append(ejvw.buf, buf.Bytes()...) + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteUndefined() error { +	if err := ejvw.ensureElementValue(mode(0), "WriteUndefined"); err != nil { +		return err +	} + +	ejvw.writeExtendedSingleValue("undefined", "true", false) +	ejvw.buf = append(ejvw.buf, ',') + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteDocumentElement(key string) (ValueWriter, error) { +	switch ejvw.stack[ejvw.frame].mode { +	case mDocument, mTopLevel, mCodeWithScope: +		var buf bytes.Buffer +		writeStringWithEscapes(key, &buf, ejvw.escapeHTML) + +		ejvw.buf = append(ejvw.buf, []byte(fmt.Sprintf(`%s:`, buf.String()))...) +		ejvw.push(mElement) +	default: +		return nil, ejvw.invalidTransitionErr(mElement, "WriteDocumentElement", []mode{mDocument, mTopLevel, mCodeWithScope}) +	} + +	return ejvw, nil +} + +func (ejvw *extJSONValueWriter) WriteDocumentEnd() error { +	switch ejvw.stack[ejvw.frame].mode { +	case mDocument, mTopLevel, mCodeWithScope: +	default: +		return fmt.Errorf("incorrect mode to end document: %s", ejvw.stack[ejvw.frame].mode) +	} + +	// close the document +	if ejvw.buf[len(ejvw.buf)-1] == ',' { +		ejvw.buf[len(ejvw.buf)-1] = '}' +	} else { +		ejvw.buf = append(ejvw.buf, '}') +	} + +	switch ejvw.stack[ejvw.frame].mode { +	case mCodeWithScope: +		ejvw.buf = append(ejvw.buf, '}') +		fallthrough +	case mDocument: +		ejvw.buf = append(ejvw.buf, ',') +	case mTopLevel: +		if ejvw.w != nil { +			if _, err := ejvw.w.Write(ejvw.buf); err != nil { +				return err +			} +			ejvw.buf = ejvw.buf[:0] +		} +	} + +	ejvw.pop() +	return nil +} + +func (ejvw *extJSONValueWriter) WriteArrayElement() (ValueWriter, error) { +	switch ejvw.stack[ejvw.frame].mode { +	case mArray: +		ejvw.push(mValue) +	default: +		return nil, ejvw.invalidTransitionErr(mValue, "WriteArrayElement", []mode{mArray}) +	} + +	return ejvw, nil +} + +func (ejvw *extJSONValueWriter) WriteArrayEnd() error { +	switch ejvw.stack[ejvw.frame].mode { +	case mArray: +		// close the array +		if ejvw.buf[len(ejvw.buf)-1] == ',' { +			ejvw.buf[len(ejvw.buf)-1] = ']' +		} else { +			ejvw.buf = append(ejvw.buf, ']') +		} + +		ejvw.buf = append(ejvw.buf, ',') + +		ejvw.pop() +	default: +		return fmt.Errorf("incorrect mode to end array: %s", ejvw.stack[ejvw.frame].mode) +	} + +	return nil +} + +func formatDouble(f float64) string { +	var s string +	if math.IsInf(f, 1) { +		s = "Infinity" +	} else if math.IsInf(f, -1) { +		s = "-Infinity" +	} else if math.IsNaN(f) { +		s = "NaN" +	} else { +		// Print exactly one decimalType place for integers; otherwise, print as many are necessary to +		// perfectly represent it. +		s = strconv.FormatFloat(f, 'G', -1, 64) +		if !strings.ContainsRune(s, 'E') && !strings.ContainsRune(s, '.') { +			s += ".0" +		} +	} + +	return s +} + +var hexChars = "0123456789abcdef" + +func writeStringWithEscapes(s string, buf *bytes.Buffer, escapeHTML bool) { +	buf.WriteByte('"') +	start := 0 +	for i := 0; i < len(s); { +		if b := s[i]; b < utf8.RuneSelf { +			if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) { +				i++ +				continue +			} +			if start < i { +				buf.WriteString(s[start:i]) +			} +			switch b { +			case '\\', '"': +				buf.WriteByte('\\') +				buf.WriteByte(b) +			case '\n': +				buf.WriteByte('\\') +				buf.WriteByte('n') +			case '\r': +				buf.WriteByte('\\') +				buf.WriteByte('r') +			case '\t': +				buf.WriteByte('\\') +				buf.WriteByte('t') +			case '\b': +				buf.WriteByte('\\') +				buf.WriteByte('b') +			case '\f': +				buf.WriteByte('\\') +				buf.WriteByte('f') +			default: +				// This encodes bytes < 0x20 except for \t, \n and \r. +				// If escapeHTML is set, it also escapes <, >, and & +				// because they can lead to security holes when +				// user-controlled strings are rendered into JSON +				// and served to some browsers. +				buf.WriteString(`\u00`) +				buf.WriteByte(hexChars[b>>4]) +				buf.WriteByte(hexChars[b&0xF]) +			} +			i++ +			start = i +			continue +		} +		c, size := utf8.DecodeRuneInString(s[i:]) +		if c == utf8.RuneError && size == 1 { +			if start < i { +				buf.WriteString(s[start:i]) +			} +			buf.WriteString(`\ufffd`) +			i += size +			start = i +			continue +		} +		// U+2028 is LINE SEPARATOR. +		// U+2029 is PARAGRAPH SEPARATOR. +		// They are both technically valid characters in JSON strings, +		// but don't work in JSONP, which has to be evaluated as JavaScript, +		// and can lead to security holes there. It is valid JSON to +		// escape them, so we do so unconditionally. +		// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. +		if c == '\u2028' || c == '\u2029' { +			if start < i { +				buf.WriteString(s[start:i]) +			} +			buf.WriteString(`\u202`) +			buf.WriteByte(hexChars[c&0xF]) +			i += size +			start = i +			continue +		} +		i += size +	} +	if start < len(s) { +		buf.WriteString(s[start:]) +	} +	buf.WriteByte('"') +} + +type sortableString []rune + +func (ss sortableString) Len() int { +	return len(ss) +} + +func (ss sortableString) Less(i, j int) bool { +	return ss[i] < ss[j] +} + +func (ss sortableString) Swap(i, j int) { +	oldI := ss[i] +	ss[i] = ss[j] +	ss[j] = oldI +} + +func sortStringAlphebeticAscending(s string) string { +	ss := sortableString([]rune(s)) +	sort.Sort(ss) +	return string([]rune(ss)) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go new file mode 100644 index 000000000..cd4843a3a --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go @@ -0,0 +1,528 @@ +// 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 bsonrw + +import ( +	"bytes" +	"errors" +	"fmt" +	"io" +	"math" +	"strconv" +	"unicode" +	"unicode/utf16" +) + +type jsonTokenType byte + +const ( +	jttBeginObject jsonTokenType = iota +	jttEndObject +	jttBeginArray +	jttEndArray +	jttColon +	jttComma +	jttInt32 +	jttInt64 +	jttDouble +	jttString +	jttBool +	jttNull +	jttEOF +) + +type jsonToken struct { +	t jsonTokenType +	v interface{} +	p int +} + +type jsonScanner struct { +	r           io.Reader +	buf         []byte +	pos         int +	lastReadErr error +} + +// nextToken returns the next JSON token if one exists. A token is a character +// of the JSON grammar, a number, a string, or a literal. +func (js *jsonScanner) nextToken() (*jsonToken, error) { +	c, err := js.readNextByte() + +	// keep reading until a non-space is encountered (break on read error or EOF) +	for isWhiteSpace(c) && err == nil { +		c, err = js.readNextByte() +	} + +	if err == io.EOF { +		return &jsonToken{t: jttEOF}, nil +	} else if err != nil { +		return nil, err +	} + +	// switch on the character +	switch c { +	case '{': +		return &jsonToken{t: jttBeginObject, v: byte('{'), p: js.pos - 1}, nil +	case '}': +		return &jsonToken{t: jttEndObject, v: byte('}'), p: js.pos - 1}, nil +	case '[': +		return &jsonToken{t: jttBeginArray, v: byte('['), p: js.pos - 1}, nil +	case ']': +		return &jsonToken{t: jttEndArray, v: byte(']'), p: js.pos - 1}, nil +	case ':': +		return &jsonToken{t: jttColon, v: byte(':'), p: js.pos - 1}, nil +	case ',': +		return &jsonToken{t: jttComma, v: byte(','), p: js.pos - 1}, nil +	case '"': // RFC-8259 only allows for double quotes (") not single (') +		return js.scanString() +	default: +		// check if it's a number +		if c == '-' || isDigit(c) { +			return js.scanNumber(c) +		} else if c == 't' || c == 'f' || c == 'n' { +			// maybe a literal +			return js.scanLiteral(c) +		} else { +			return nil, fmt.Errorf("invalid JSON input. Position: %d. Character: %c", js.pos-1, c) +		} +	} +} + +// readNextByte attempts to read the next byte from the buffer. If the buffer +// has been exhausted, this function calls readIntoBuf, thus refilling the +// buffer and resetting the read position to 0 +func (js *jsonScanner) readNextByte() (byte, error) { +	if js.pos >= len(js.buf) { +		err := js.readIntoBuf() + +		if err != nil { +			return 0, err +		} +	} + +	b := js.buf[js.pos] +	js.pos++ + +	return b, nil +} + +// readNNextBytes reads n bytes into dst, starting at offset +func (js *jsonScanner) readNNextBytes(dst []byte, n, offset int) error { +	var err error + +	for i := 0; i < n; i++ { +		dst[i+offset], err = js.readNextByte() +		if err != nil { +			return err +		} +	} + +	return nil +} + +// readIntoBuf reads up to 512 bytes from the scanner's io.Reader into the buffer +func (js *jsonScanner) readIntoBuf() error { +	if js.lastReadErr != nil { +		js.buf = js.buf[:0] +		js.pos = 0 +		return js.lastReadErr +	} + +	if cap(js.buf) == 0 { +		js.buf = make([]byte, 0, 512) +	} + +	n, err := js.r.Read(js.buf[:cap(js.buf)]) +	if err != nil { +		js.lastReadErr = err +		if n > 0 { +			err = nil +		} +	} +	js.buf = js.buf[:n] +	js.pos = 0 + +	return err +} + +func isWhiteSpace(c byte) bool { +	return c == ' ' || c == '\t' || c == '\r' || c == '\n' +} + +func isDigit(c byte) bool { +	return unicode.IsDigit(rune(c)) +} + +func isValueTerminator(c byte) bool { +	return c == ',' || c == '}' || c == ']' || isWhiteSpace(c) +} + +// getu4 decodes the 4-byte hex sequence from the beginning of s, returning the hex value as a rune, +// or it returns -1. Note that the "\u" from the unicode escape sequence should not be present. +// It is copied and lightly modified from the Go JSON decode function at +// https://github.com/golang/go/blob/1b0a0316802b8048d69da49dc23c5a5ab08e8ae8/src/encoding/json/decode.go#L1169-L1188 +func getu4(s []byte) rune { +	if len(s) < 4 { +		return -1 +	} +	var r rune +	for _, c := range s[:4] { +		switch { +		case '0' <= c && c <= '9': +			c = c - '0' +		case 'a' <= c && c <= 'f': +			c = c - 'a' + 10 +		case 'A' <= c && c <= 'F': +			c = c - 'A' + 10 +		default: +			return -1 +		} +		r = r*16 + rune(c) +	} +	return r +} + +// scanString reads from an opening '"' to a closing '"' and handles escaped characters +func (js *jsonScanner) scanString() (*jsonToken, error) { +	var b bytes.Buffer +	var c byte +	var err error + +	p := js.pos - 1 + +	for { +		c, err = js.readNextByte() +		if err != nil { +			if err == io.EOF { +				return nil, errors.New("end of input in JSON string") +			} +			return nil, err +		} + +	evalNextChar: +		switch c { +		case '\\': +			c, err = js.readNextByte() +			if err != nil { +				if err == io.EOF { +					return nil, errors.New("end of input in JSON string") +				} +				return nil, err +			} + +		evalNextEscapeChar: +			switch c { +			case '"', '\\', '/': +				b.WriteByte(c) +			case 'b': +				b.WriteByte('\b') +			case 'f': +				b.WriteByte('\f') +			case 'n': +				b.WriteByte('\n') +			case 'r': +				b.WriteByte('\r') +			case 't': +				b.WriteByte('\t') +			case 'u': +				us := make([]byte, 4) +				err = js.readNNextBytes(us, 4, 0) +				if err != nil { +					return nil, fmt.Errorf("invalid unicode sequence in JSON string: %s", us) +				} + +				rn := getu4(us) + +				// If the rune we just decoded is the high or low value of a possible surrogate pair, +				// try to decode the next sequence as the low value of a surrogate pair. We're +				// expecting the next sequence to be another Unicode escape sequence (e.g. "\uDD1E"), +				// but need to handle cases where the input is not a valid surrogate pair. +				// For more context on unicode surrogate pairs, see: +				// https://www.christianfscott.com/rust-chars-vs-go-runes/ +				// https://www.unicode.org/glossary/#high_surrogate_code_point +				if utf16.IsSurrogate(rn) { +					c, err = js.readNextByte() +					if err != nil { +						if err == io.EOF { +							return nil, errors.New("end of input in JSON string") +						} +						return nil, err +					} + +					// If the next value isn't the beginning of a backslash escape sequence, write +					// the Unicode replacement character for the surrogate value and goto the +					// beginning of the next char eval block. +					if c != '\\' { +						b.WriteRune(unicode.ReplacementChar) +						goto evalNextChar +					} + +					c, err = js.readNextByte() +					if err != nil { +						if err == io.EOF { +							return nil, errors.New("end of input in JSON string") +						} +						return nil, err +					} + +					// If the next value isn't the beginning of a unicode escape sequence, write the +					// Unicode replacement character for the surrogate value and goto the beginning +					// of the next escape char eval block. +					if c != 'u' { +						b.WriteRune(unicode.ReplacementChar) +						goto evalNextEscapeChar +					} + +					err = js.readNNextBytes(us, 4, 0) +					if err != nil { +						return nil, fmt.Errorf("invalid unicode sequence in JSON string: %s", us) +					} + +					rn2 := getu4(us) + +					// Try to decode the pair of runes as a utf16 surrogate pair. If that fails, write +					// the Unicode replacement character for the surrogate value and the 2nd decoded rune. +					if rnPair := utf16.DecodeRune(rn, rn2); rnPair != unicode.ReplacementChar { +						b.WriteRune(rnPair) +					} else { +						b.WriteRune(unicode.ReplacementChar) +						b.WriteRune(rn2) +					} + +					break +				} + +				b.WriteRune(rn) +			default: +				return nil, fmt.Errorf("invalid escape sequence in JSON string '\\%c'", c) +			} +		case '"': +			return &jsonToken{t: jttString, v: b.String(), p: p}, nil +		default: +			b.WriteByte(c) +		} +	} +} + +// scanLiteral reads an unquoted sequence of characters and determines if it is one of +// three valid JSON literals (true, false, null); if so, it returns the appropriate +// jsonToken; otherwise, it returns an error +func (js *jsonScanner) scanLiteral(first byte) (*jsonToken, error) { +	p := js.pos - 1 + +	lit := make([]byte, 4) +	lit[0] = first + +	err := js.readNNextBytes(lit, 3, 1) +	if err != nil { +		return nil, err +	} + +	c5, err := js.readNextByte() + +	if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || err == io.EOF) { +		js.pos = int(math.Max(0, float64(js.pos-1))) +		return &jsonToken{t: jttBool, v: true, p: p}, nil +	} else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || err == io.EOF) { +		js.pos = int(math.Max(0, float64(js.pos-1))) +		return &jsonToken{t: jttNull, v: nil, p: p}, nil +	} else if bytes.Equal([]byte("fals"), lit) { +		if c5 == 'e' { +			c5, err = js.readNextByte() + +			if isValueTerminator(c5) || err == io.EOF { +				js.pos = int(math.Max(0, float64(js.pos-1))) +				return &jsonToken{t: jttBool, v: false, p: p}, nil +			} +		} +	} + +	return nil, fmt.Errorf("invalid JSON literal. Position: %d, literal: %s", p, lit) +} + +type numberScanState byte + +const ( +	nssSawLeadingMinus numberScanState = iota +	nssSawLeadingZero +	nssSawIntegerDigits +	nssSawDecimalPoint +	nssSawFractionDigits +	nssSawExponentLetter +	nssSawExponentSign +	nssSawExponentDigits +	nssDone +	nssInvalid +) + +// scanNumber reads a JSON number (according to RFC-8259) +func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { +	var b bytes.Buffer +	var s numberScanState +	var c byte +	var err error + +	t := jttInt64 // assume it's an int64 until the type can be determined +	start := js.pos - 1 + +	b.WriteByte(first) + +	switch first { +	case '-': +		s = nssSawLeadingMinus +	case '0': +		s = nssSawLeadingZero +	default: +		s = nssSawIntegerDigits +	} + +	for { +		c, err = js.readNextByte() + +		if err != nil && err != io.EOF { +			return nil, err +		} + +		switch s { +		case nssSawLeadingMinus: +			switch c { +			case '0': +				s = nssSawLeadingZero +				b.WriteByte(c) +			default: +				if isDigit(c) { +					s = nssSawIntegerDigits +					b.WriteByte(c) +				} else { +					s = nssInvalid +				} +			} +		case nssSawLeadingZero: +			switch c { +			case '.': +				s = nssSawDecimalPoint +				b.WriteByte(c) +			case 'e', 'E': +				s = nssSawExponentLetter +				b.WriteByte(c) +			case '}', ']', ',': +				s = nssDone +			default: +				if isWhiteSpace(c) || err == io.EOF { +					s = nssDone +				} else { +					s = nssInvalid +				} +			} +		case nssSawIntegerDigits: +			switch c { +			case '.': +				s = nssSawDecimalPoint +				b.WriteByte(c) +			case 'e', 'E': +				s = nssSawExponentLetter +				b.WriteByte(c) +			case '}', ']', ',': +				s = nssDone +			default: +				if isWhiteSpace(c) || err == io.EOF { +					s = nssDone +				} else if isDigit(c) { +					s = nssSawIntegerDigits +					b.WriteByte(c) +				} else { +					s = nssInvalid +				} +			} +		case nssSawDecimalPoint: +			t = jttDouble +			if isDigit(c) { +				s = nssSawFractionDigits +				b.WriteByte(c) +			} else { +				s = nssInvalid +			} +		case nssSawFractionDigits: +			switch c { +			case 'e', 'E': +				s = nssSawExponentLetter +				b.WriteByte(c) +			case '}', ']', ',': +				s = nssDone +			default: +				if isWhiteSpace(c) || err == io.EOF { +					s = nssDone +				} else if isDigit(c) { +					s = nssSawFractionDigits +					b.WriteByte(c) +				} else { +					s = nssInvalid +				} +			} +		case nssSawExponentLetter: +			t = jttDouble +			switch c { +			case '+', '-': +				s = nssSawExponentSign +				b.WriteByte(c) +			default: +				if isDigit(c) { +					s = nssSawExponentDigits +					b.WriteByte(c) +				} else { +					s = nssInvalid +				} +			} +		case nssSawExponentSign: +			if isDigit(c) { +				s = nssSawExponentDigits +				b.WriteByte(c) +			} else { +				s = nssInvalid +			} +		case nssSawExponentDigits: +			switch c { +			case '}', ']', ',': +				s = nssDone +			default: +				if isWhiteSpace(c) || err == io.EOF { +					s = nssDone +				} else if isDigit(c) { +					s = nssSawExponentDigits +					b.WriteByte(c) +				} else { +					s = nssInvalid +				} +			} +		} + +		switch s { +		case nssInvalid: +			return nil, fmt.Errorf("invalid JSON number. Position: %d", start) +		case nssDone: +			js.pos = int(math.Max(0, float64(js.pos-1))) +			if t != jttDouble { +				v, err := strconv.ParseInt(b.String(), 10, 64) +				if err == nil { +					if v < math.MinInt32 || v > math.MaxInt32 { +						return &jsonToken{t: jttInt64, v: v, p: start}, nil +					} + +					return &jsonToken{t: jttInt32, v: int32(v), p: start}, nil +				} +			} + +			v, err := strconv.ParseFloat(b.String(), 64) +			if err != nil { +				return nil, err +			} + +			return &jsonToken{t: jttDouble, v: v, p: start}, nil +		} +	} +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/mode.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/mode.go new file mode 100644 index 000000000..617b5e221 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/mode.go @@ -0,0 +1,108 @@ +// 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 bsonrw + +import ( +	"fmt" +) + +type mode int + +const ( +	_ mode = iota +	mTopLevel +	mDocument +	mArray +	mValue +	mElement +	mCodeWithScope +	mSpacer +) + +func (m mode) String() string { +	var str string + +	switch m { +	case mTopLevel: +		str = "TopLevel" +	case mDocument: +		str = "DocumentMode" +	case mArray: +		str = "ArrayMode" +	case mValue: +		str = "ValueMode" +	case mElement: +		str = "ElementMode" +	case mCodeWithScope: +		str = "CodeWithScopeMode" +	case mSpacer: +		str = "CodeWithScopeSpacerFrame" +	default: +		str = "UnknownMode" +	} + +	return str +} + +func (m mode) TypeString() string { +	var str string + +	switch m { +	case mTopLevel: +		str = "TopLevel" +	case mDocument: +		str = "Document" +	case mArray: +		str = "Array" +	case mValue: +		str = "Value" +	case mElement: +		str = "Element" +	case mCodeWithScope: +		str = "CodeWithScope" +	case mSpacer: +		str = "CodeWithScopeSpacer" +	default: +		str = "Unknown" +	} + +	return str +} + +// TransitionError is an error returned when an invalid progressing a +// ValueReader or ValueWriter state machine occurs. +// If read is false, the error is for writing +type TransitionError struct { +	name        string +	parent      mode +	current     mode +	destination mode +	modes       []mode +	action      string +} + +func (te TransitionError) Error() string { +	errString := fmt.Sprintf("%s can only %s", te.name, te.action) +	if te.destination != mode(0) { +		errString = fmt.Sprintf("%s a %s", errString, te.destination.TypeString()) +	} +	errString = fmt.Sprintf("%s while positioned on a", errString) +	for ind, m := range te.modes { +		if ind != 0 && len(te.modes) > 2 { +			errString = fmt.Sprintf("%s,", errString) +		} +		if ind == len(te.modes)-1 && len(te.modes) > 1 { +			errString = fmt.Sprintf("%s or", errString) +		} +		errString = fmt.Sprintf("%s %s", errString, m.TypeString()) +	} +	errString = fmt.Sprintf("%s but is positioned on a %s", errString, te.current.TypeString()) +	if te.parent != mode(0) { +		errString = fmt.Sprintf("%s with parent %s", errString, te.parent.TypeString()) +	} +	return errString +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/reader.go new file mode 100644 index 000000000..0b8fa28d5 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/reader.go @@ -0,0 +1,63 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bsonrw + +import ( +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +// ArrayReader is implemented by types that allow reading values from a BSON +// array. +type ArrayReader interface { +	ReadValue() (ValueReader, error) +} + +// DocumentReader is implemented by types that allow reading elements from a +// BSON document. +type DocumentReader interface { +	ReadElement() (string, ValueReader, error) +} + +// ValueReader is a generic interface used to read values from BSON. This type +// is implemented by several types with different underlying representations of +// BSON, such as a bson.Document, raw BSON bytes, or extended JSON. +type ValueReader interface { +	Type() bsontype.Type +	Skip() error + +	ReadArray() (ArrayReader, error) +	ReadBinary() (b []byte, btype byte, err error) +	ReadBoolean() (bool, error) +	ReadDocument() (DocumentReader, error) +	ReadCodeWithScope() (code string, dr DocumentReader, err error) +	ReadDBPointer() (ns string, oid primitive.ObjectID, err error) +	ReadDateTime() (int64, error) +	ReadDecimal128() (primitive.Decimal128, error) +	ReadDouble() (float64, error) +	ReadInt32() (int32, error) +	ReadInt64() (int64, error) +	ReadJavascript() (code string, err error) +	ReadMaxKey() error +	ReadMinKey() error +	ReadNull() error +	ReadObjectID() (primitive.ObjectID, error) +	ReadRegex() (pattern, options string, err error) +	ReadString() (string, error) +	ReadSymbol() (symbol string, err error) +	ReadTimestamp() (t, i uint32, err error) +	ReadUndefined() error +} + +// BytesReader is a generic interface used to read BSON bytes from a +// ValueReader. This imterface is meant to be a superset of ValueReader, so that +// types that implement ValueReader may also implement this interface. +// +// The bytes of the value will be appended to dst. +type BytesReader interface { +	ReadValueBytes(dst []byte) (bsontype.Type, []byte, error) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go new file mode 100644 index 000000000..ef5d837c2 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_reader.go @@ -0,0 +1,874 @@ +// 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 bsonrw + +import ( +	"bytes" +	"encoding/binary" +	"errors" +	"fmt" +	"io" +	"math" +	"sync" + +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +var _ ValueReader = (*valueReader)(nil) + +var vrPool = sync.Pool{ +	New: func() interface{} { +		return new(valueReader) +	}, +} + +// BSONValueReaderPool is a pool for ValueReaders that read BSON. +type BSONValueReaderPool struct { +	pool sync.Pool +} + +// NewBSONValueReaderPool instantiates a new BSONValueReaderPool. +func NewBSONValueReaderPool() *BSONValueReaderPool { +	return &BSONValueReaderPool{ +		pool: sync.Pool{ +			New: func() interface{} { +				return new(valueReader) +			}, +		}, +	} +} + +// Get retrieves a ValueReader from the pool and uses src as the underlying BSON. +func (bvrp *BSONValueReaderPool) Get(src []byte) ValueReader { +	vr := bvrp.pool.Get().(*valueReader) +	vr.reset(src) +	return vr +} + +// Put inserts a ValueReader into the pool. If the ValueReader is not a BSON ValueReader nothing +// is inserted into the pool and ok will be false. +func (bvrp *BSONValueReaderPool) Put(vr ValueReader) (ok bool) { +	bvr, ok := vr.(*valueReader) +	if !ok { +		return false +	} + +	bvr.reset(nil) +	bvrp.pool.Put(bvr) +	return true +} + +// ErrEOA is the error returned when the end of a BSON array has been reached. +var ErrEOA = errors.New("end of array") + +// ErrEOD is the error returned when the end of a BSON document has been reached. +var ErrEOD = errors.New("end of document") + +type vrState struct { +	mode  mode +	vType bsontype.Type +	end   int64 +} + +// valueReader is for reading BSON values. +type valueReader struct { +	offset int64 +	d      []byte + +	stack []vrState +	frame int64 +} + +// NewBSONDocumentReader returns a ValueReader using b for the underlying BSON +// representation. Parameter b must be a BSON Document. +func NewBSONDocumentReader(b []byte) ValueReader { +	// TODO(skriptble): There's a lack of symmetry between the reader and writer, since the reader takes a []byte while the +	// TODO writer takes an io.Writer. We should have two versions of each, one that takes a []byte and one that takes an +	// TODO io.Reader or io.Writer. The []byte version will need to return a thing that can return the finished []byte since +	// TODO it might be reallocated when appended to. +	return newValueReader(b) +} + +// NewBSONValueReader returns a ValueReader that starts in the Value mode instead of in top +// level document mode. This enables the creation of a ValueReader for a single BSON value. +func NewBSONValueReader(t bsontype.Type, val []byte) ValueReader { +	stack := make([]vrState, 1, 5) +	stack[0] = vrState{ +		mode:  mValue, +		vType: t, +	} +	return &valueReader{ +		d:     val, +		stack: stack, +	} +} + +func newValueReader(b []byte) *valueReader { +	stack := make([]vrState, 1, 5) +	stack[0] = vrState{ +		mode: mTopLevel, +	} +	return &valueReader{ +		d:     b, +		stack: stack, +	} +} + +func (vr *valueReader) reset(b []byte) { +	if vr.stack == nil { +		vr.stack = make([]vrState, 1, 5) +	} +	vr.stack = vr.stack[:1] +	vr.stack[0] = vrState{mode: mTopLevel} +	vr.d = b +	vr.offset = 0 +	vr.frame = 0 +} + +func (vr *valueReader) advanceFrame() { +	if vr.frame+1 >= int64(len(vr.stack)) { // We need to grow the stack +		length := len(vr.stack) +		if length+1 >= cap(vr.stack) { +			// double it +			buf := make([]vrState, 2*cap(vr.stack)+1) +			copy(buf, vr.stack) +			vr.stack = buf +		} +		vr.stack = vr.stack[:length+1] +	} +	vr.frame++ + +	// Clean the stack +	vr.stack[vr.frame].mode = 0 +	vr.stack[vr.frame].vType = 0 +	vr.stack[vr.frame].end = 0 +} + +func (vr *valueReader) pushDocument() error { +	vr.advanceFrame() + +	vr.stack[vr.frame].mode = mDocument + +	size, err := vr.readLength() +	if err != nil { +		return err +	} +	vr.stack[vr.frame].end = int64(size) + vr.offset - 4 + +	return nil +} + +func (vr *valueReader) pushArray() error { +	vr.advanceFrame() + +	vr.stack[vr.frame].mode = mArray + +	size, err := vr.readLength() +	if err != nil { +		return err +	} +	vr.stack[vr.frame].end = int64(size) + vr.offset - 4 + +	return nil +} + +func (vr *valueReader) pushElement(t bsontype.Type) { +	vr.advanceFrame() + +	vr.stack[vr.frame].mode = mElement +	vr.stack[vr.frame].vType = t +} + +func (vr *valueReader) pushValue(t bsontype.Type) { +	vr.advanceFrame() + +	vr.stack[vr.frame].mode = mValue +	vr.stack[vr.frame].vType = t +} + +func (vr *valueReader) pushCodeWithScope() (int64, error) { +	vr.advanceFrame() + +	vr.stack[vr.frame].mode = mCodeWithScope + +	size, err := vr.readLength() +	if err != nil { +		return 0, err +	} +	vr.stack[vr.frame].end = int64(size) + vr.offset - 4 + +	return int64(size), nil +} + +func (vr *valueReader) pop() { +	switch vr.stack[vr.frame].mode { +	case mElement, mValue: +		vr.frame-- +	case mDocument, mArray, mCodeWithScope: +		vr.frame -= 2 // we pop twice to jump over the vrElement: vrDocument -> vrElement -> vrDocument/TopLevel/etc... +	} +} + +func (vr *valueReader) invalidTransitionErr(destination mode, name string, modes []mode) error { +	te := TransitionError{ +		name:        name, +		current:     vr.stack[vr.frame].mode, +		destination: destination, +		modes:       modes, +		action:      "read", +	} +	if vr.frame != 0 { +		te.parent = vr.stack[vr.frame-1].mode +	} +	return te +} + +func (vr *valueReader) typeError(t bsontype.Type) error { +	return fmt.Errorf("positioned on %s, but attempted to read %s", vr.stack[vr.frame].vType, t) +} + +func (vr *valueReader) invalidDocumentLengthError() error { +	return fmt.Errorf("document is invalid, end byte is at %d, but null byte found at %d", vr.stack[vr.frame].end, vr.offset) +} + +func (vr *valueReader) ensureElementValue(t bsontype.Type, destination mode, callerName string) error { +	switch vr.stack[vr.frame].mode { +	case mElement, mValue: +		if vr.stack[vr.frame].vType != t { +			return vr.typeError(t) +		} +	default: +		return vr.invalidTransitionErr(destination, callerName, []mode{mElement, mValue}) +	} + +	return nil +} + +func (vr *valueReader) Type() bsontype.Type { +	return vr.stack[vr.frame].vType +} + +func (vr *valueReader) nextElementLength() (int32, error) { +	var length int32 +	var err error +	switch vr.stack[vr.frame].vType { +	case bsontype.Array, bsontype.EmbeddedDocument, bsontype.CodeWithScope: +		length, err = vr.peekLength() +	case bsontype.Binary: +		length, err = vr.peekLength() +		length += 4 + 1 // binary length + subtype byte +	case bsontype.Boolean: +		length = 1 +	case bsontype.DBPointer: +		length, err = vr.peekLength() +		length += 4 + 12 // string length + ObjectID length +	case bsontype.DateTime, bsontype.Double, bsontype.Int64, bsontype.Timestamp: +		length = 8 +	case bsontype.Decimal128: +		length = 16 +	case bsontype.Int32: +		length = 4 +	case bsontype.JavaScript, bsontype.String, bsontype.Symbol: +		length, err = vr.peekLength() +		length += 4 +	case bsontype.MaxKey, bsontype.MinKey, bsontype.Null, bsontype.Undefined: +		length = 0 +	case bsontype.ObjectID: +		length = 12 +	case bsontype.Regex: +		regex := bytes.IndexByte(vr.d[vr.offset:], 0x00) +		if regex < 0 { +			err = io.EOF +			break +		} +		pattern := bytes.IndexByte(vr.d[vr.offset+int64(regex)+1:], 0x00) +		if pattern < 0 { +			err = io.EOF +			break +		} +		length = int32(int64(regex) + 1 + int64(pattern) + 1) +	default: +		return 0, fmt.Errorf("attempted to read bytes of unknown BSON type %v", vr.stack[vr.frame].vType) +	} + +	return length, err +} + +func (vr *valueReader) ReadValueBytes(dst []byte) (bsontype.Type, []byte, error) { +	switch vr.stack[vr.frame].mode { +	case mTopLevel: +		length, err := vr.peekLength() +		if err != nil { +			return bsontype.Type(0), nil, err +		} +		dst, err = vr.appendBytes(dst, length) +		if err != nil { +			return bsontype.Type(0), nil, err +		} +		return bsontype.Type(0), dst, nil +	case mElement, mValue: +		length, err := vr.nextElementLength() +		if err != nil { +			return bsontype.Type(0), dst, err +		} + +		dst, err = vr.appendBytes(dst, length) +		t := vr.stack[vr.frame].vType +		vr.pop() +		return t, dst, err +	default: +		return bsontype.Type(0), nil, vr.invalidTransitionErr(0, "ReadValueBytes", []mode{mElement, mValue}) +	} +} + +func (vr *valueReader) Skip() error { +	switch vr.stack[vr.frame].mode { +	case mElement, mValue: +	default: +		return vr.invalidTransitionErr(0, "Skip", []mode{mElement, mValue}) +	} + +	length, err := vr.nextElementLength() +	if err != nil { +		return err +	} + +	err = vr.skipBytes(length) +	vr.pop() +	return err +} + +func (vr *valueReader) ReadArray() (ArrayReader, error) { +	if err := vr.ensureElementValue(bsontype.Array, mArray, "ReadArray"); err != nil { +		return nil, err +	} + +	err := vr.pushArray() +	if err != nil { +		return nil, err +	} + +	return vr, nil +} + +func (vr *valueReader) ReadBinary() (b []byte, btype byte, err error) { +	if err := vr.ensureElementValue(bsontype.Binary, 0, "ReadBinary"); err != nil { +		return nil, 0, err +	} + +	length, err := vr.readLength() +	if err != nil { +		return nil, 0, err +	} + +	btype, err = vr.readByte() +	if err != nil { +		return nil, 0, err +	} + +	// Check length in case it is an old binary without a length. +	if btype == 0x02 && length > 4 { +		length, err = vr.readLength() +		if err != nil { +			return nil, 0, err +		} +	} + +	b, err = vr.readBytes(length) +	if err != nil { +		return nil, 0, err +	} +	// Make a copy of the returned byte slice because it's just a subslice from the valueReader's +	// buffer and is not safe to return in the unmarshaled value. +	cp := make([]byte, len(b)) +	copy(cp, b) + +	vr.pop() +	return cp, btype, nil +} + +func (vr *valueReader) ReadBoolean() (bool, error) { +	if err := vr.ensureElementValue(bsontype.Boolean, 0, "ReadBoolean"); err != nil { +		return false, err +	} + +	b, err := vr.readByte() +	if err != nil { +		return false, err +	} + +	if b > 1 { +		return false, fmt.Errorf("invalid byte for boolean, %b", b) +	} + +	vr.pop() +	return b == 1, nil +} + +func (vr *valueReader) ReadDocument() (DocumentReader, error) { +	switch vr.stack[vr.frame].mode { +	case mTopLevel: +		// read size +		size, err := vr.readLength() +		if err != nil { +			return nil, err +		} +		if int(size) != len(vr.d) { +			return nil, fmt.Errorf("invalid document length") +		} +		vr.stack[vr.frame].end = int64(size) + vr.offset - 4 +		return vr, nil +	case mElement, mValue: +		if vr.stack[vr.frame].vType != bsontype.EmbeddedDocument { +			return nil, vr.typeError(bsontype.EmbeddedDocument) +		} +	default: +		return nil, vr.invalidTransitionErr(mDocument, "ReadDocument", []mode{mTopLevel, mElement, mValue}) +	} + +	err := vr.pushDocument() +	if err != nil { +		return nil, err +	} + +	return vr, nil +} + +func (vr *valueReader) ReadCodeWithScope() (code string, dr DocumentReader, err error) { +	if err := vr.ensureElementValue(bsontype.CodeWithScope, 0, "ReadCodeWithScope"); err != nil { +		return "", nil, err +	} + +	totalLength, err := vr.readLength() +	if err != nil { +		return "", nil, err +	} +	strLength, err := vr.readLength() +	if err != nil { +		return "", nil, err +	} +	if strLength <= 0 { +		return "", nil, fmt.Errorf("invalid string length: %d", strLength) +	} +	strBytes, err := vr.readBytes(strLength) +	if err != nil { +		return "", nil, err +	} +	code = string(strBytes[:len(strBytes)-1]) + +	size, err := vr.pushCodeWithScope() +	if err != nil { +		return "", nil, err +	} + +	// The total length should equal: +	// 4 (total length) + strLength + 4 (the length of str itself) + (document length) +	componentsLength := int64(4+strLength+4) + size +	if int64(totalLength) != componentsLength { +		return "", nil, fmt.Errorf( +			"length of CodeWithScope does not match lengths of components; total: %d; components: %d", +			totalLength, componentsLength, +		) +	} +	return code, vr, nil +} + +func (vr *valueReader) ReadDBPointer() (ns string, oid primitive.ObjectID, err error) { +	if err := vr.ensureElementValue(bsontype.DBPointer, 0, "ReadDBPointer"); err != nil { +		return "", oid, err +	} + +	ns, err = vr.readString() +	if err != nil { +		return "", oid, err +	} + +	oidbytes, err := vr.readBytes(12) +	if err != nil { +		return "", oid, err +	} + +	copy(oid[:], oidbytes) + +	vr.pop() +	return ns, oid, nil +} + +func (vr *valueReader) ReadDateTime() (int64, error) { +	if err := vr.ensureElementValue(bsontype.DateTime, 0, "ReadDateTime"); err != nil { +		return 0, err +	} + +	i, err := vr.readi64() +	if err != nil { +		return 0, err +	} + +	vr.pop() +	return i, nil +} + +func (vr *valueReader) ReadDecimal128() (primitive.Decimal128, error) { +	if err := vr.ensureElementValue(bsontype.Decimal128, 0, "ReadDecimal128"); err != nil { +		return primitive.Decimal128{}, err +	} + +	b, err := vr.readBytes(16) +	if err != nil { +		return primitive.Decimal128{}, err +	} + +	l := binary.LittleEndian.Uint64(b[0:8]) +	h := binary.LittleEndian.Uint64(b[8:16]) + +	vr.pop() +	return primitive.NewDecimal128(h, l), nil +} + +func (vr *valueReader) ReadDouble() (float64, error) { +	if err := vr.ensureElementValue(bsontype.Double, 0, "ReadDouble"); err != nil { +		return 0, err +	} + +	u, err := vr.readu64() +	if err != nil { +		return 0, err +	} + +	vr.pop() +	return math.Float64frombits(u), nil +} + +func (vr *valueReader) ReadInt32() (int32, error) { +	if err := vr.ensureElementValue(bsontype.Int32, 0, "ReadInt32"); err != nil { +		return 0, err +	} + +	vr.pop() +	return vr.readi32() +} + +func (vr *valueReader) ReadInt64() (int64, error) { +	if err := vr.ensureElementValue(bsontype.Int64, 0, "ReadInt64"); err != nil { +		return 0, err +	} + +	vr.pop() +	return vr.readi64() +} + +func (vr *valueReader) ReadJavascript() (code string, err error) { +	if err := vr.ensureElementValue(bsontype.JavaScript, 0, "ReadJavascript"); err != nil { +		return "", err +	} + +	vr.pop() +	return vr.readString() +} + +func (vr *valueReader) ReadMaxKey() error { +	if err := vr.ensureElementValue(bsontype.MaxKey, 0, "ReadMaxKey"); err != nil { +		return err +	} + +	vr.pop() +	return nil +} + +func (vr *valueReader) ReadMinKey() error { +	if err := vr.ensureElementValue(bsontype.MinKey, 0, "ReadMinKey"); err != nil { +		return err +	} + +	vr.pop() +	return nil +} + +func (vr *valueReader) ReadNull() error { +	if err := vr.ensureElementValue(bsontype.Null, 0, "ReadNull"); err != nil { +		return err +	} + +	vr.pop() +	return nil +} + +func (vr *valueReader) ReadObjectID() (primitive.ObjectID, error) { +	if err := vr.ensureElementValue(bsontype.ObjectID, 0, "ReadObjectID"); err != nil { +		return primitive.ObjectID{}, err +	} + +	oidbytes, err := vr.readBytes(12) +	if err != nil { +		return primitive.ObjectID{}, err +	} + +	var oid primitive.ObjectID +	copy(oid[:], oidbytes) + +	vr.pop() +	return oid, nil +} + +func (vr *valueReader) ReadRegex() (string, string, error) { +	if err := vr.ensureElementValue(bsontype.Regex, 0, "ReadRegex"); err != nil { +		return "", "", err +	} + +	pattern, err := vr.readCString() +	if err != nil { +		return "", "", err +	} + +	options, err := vr.readCString() +	if err != nil { +		return "", "", err +	} + +	vr.pop() +	return pattern, options, nil +} + +func (vr *valueReader) ReadString() (string, error) { +	if err := vr.ensureElementValue(bsontype.String, 0, "ReadString"); err != nil { +		return "", err +	} + +	vr.pop() +	return vr.readString() +} + +func (vr *valueReader) ReadSymbol() (symbol string, err error) { +	if err := vr.ensureElementValue(bsontype.Symbol, 0, "ReadSymbol"); err != nil { +		return "", err +	} + +	vr.pop() +	return vr.readString() +} + +func (vr *valueReader) ReadTimestamp() (t uint32, i uint32, err error) { +	if err := vr.ensureElementValue(bsontype.Timestamp, 0, "ReadTimestamp"); err != nil { +		return 0, 0, err +	} + +	i, err = vr.readu32() +	if err != nil { +		return 0, 0, err +	} + +	t, err = vr.readu32() +	if err != nil { +		return 0, 0, err +	} + +	vr.pop() +	return t, i, nil +} + +func (vr *valueReader) ReadUndefined() error { +	if err := vr.ensureElementValue(bsontype.Undefined, 0, "ReadUndefined"); err != nil { +		return err +	} + +	vr.pop() +	return nil +} + +func (vr *valueReader) ReadElement() (string, ValueReader, error) { +	switch vr.stack[vr.frame].mode { +	case mTopLevel, mDocument, mCodeWithScope: +	default: +		return "", nil, vr.invalidTransitionErr(mElement, "ReadElement", []mode{mTopLevel, mDocument, mCodeWithScope}) +	} + +	t, err := vr.readByte() +	if err != nil { +		return "", nil, err +	} + +	if t == 0 { +		if vr.offset != vr.stack[vr.frame].end { +			return "", nil, vr.invalidDocumentLengthError() +		} + +		vr.pop() +		return "", nil, ErrEOD +	} + +	name, err := vr.readCString() +	if err != nil { +		return "", nil, err +	} + +	vr.pushElement(bsontype.Type(t)) +	return name, vr, nil +} + +func (vr *valueReader) ReadValue() (ValueReader, error) { +	switch vr.stack[vr.frame].mode { +	case mArray: +	default: +		return nil, vr.invalidTransitionErr(mValue, "ReadValue", []mode{mArray}) +	} + +	t, err := vr.readByte() +	if err != nil { +		return nil, err +	} + +	if t == 0 { +		if vr.offset != vr.stack[vr.frame].end { +			return nil, vr.invalidDocumentLengthError() +		} + +		vr.pop() +		return nil, ErrEOA +	} + +	_, err = vr.readCString() +	if err != nil { +		return nil, err +	} + +	vr.pushValue(bsontype.Type(t)) +	return vr, nil +} + +// readBytes reads length bytes from the valueReader starting at the current offset. Note that the +// returned byte slice is a subslice from the valueReader buffer and must be converted or copied +// before returning in an unmarshaled value. +func (vr *valueReader) readBytes(length int32) ([]byte, error) { +	if length < 0 { +		return nil, fmt.Errorf("invalid length: %d", length) +	} + +	if vr.offset+int64(length) > int64(len(vr.d)) { +		return nil, io.EOF +	} + +	start := vr.offset +	vr.offset += int64(length) + +	return vr.d[start : start+int64(length)], nil +} + +func (vr *valueReader) appendBytes(dst []byte, length int32) ([]byte, error) { +	if vr.offset+int64(length) > int64(len(vr.d)) { +		return nil, io.EOF +	} + +	start := vr.offset +	vr.offset += int64(length) +	return append(dst, vr.d[start:start+int64(length)]...), nil +} + +func (vr *valueReader) skipBytes(length int32) error { +	if vr.offset+int64(length) > int64(len(vr.d)) { +		return io.EOF +	} + +	vr.offset += int64(length) +	return nil +} + +func (vr *valueReader) readByte() (byte, error) { +	if vr.offset+1 > int64(len(vr.d)) { +		return 0x0, io.EOF +	} + +	vr.offset++ +	return vr.d[vr.offset-1], nil +} + +func (vr *valueReader) readCString() (string, error) { +	idx := bytes.IndexByte(vr.d[vr.offset:], 0x00) +	if idx < 0 { +		return "", io.EOF +	} +	start := vr.offset +	// idx does not include the null byte +	vr.offset += int64(idx) + 1 +	return string(vr.d[start : start+int64(idx)]), nil +} + +func (vr *valueReader) readString() (string, error) { +	length, err := vr.readLength() +	if err != nil { +		return "", err +	} + +	if int64(length)+vr.offset > int64(len(vr.d)) { +		return "", io.EOF +	} + +	if length <= 0 { +		return "", fmt.Errorf("invalid string length: %d", length) +	} + +	if vr.d[vr.offset+int64(length)-1] != 0x00 { +		return "", fmt.Errorf("string does not end with null byte, but with %v", vr.d[vr.offset+int64(length)-1]) +	} + +	start := vr.offset +	vr.offset += int64(length) +	return string(vr.d[start : start+int64(length)-1]), nil +} + +func (vr *valueReader) peekLength() (int32, error) { +	if vr.offset+4 > int64(len(vr.d)) { +		return 0, io.EOF +	} + +	idx := vr.offset +	return (int32(vr.d[idx]) | int32(vr.d[idx+1])<<8 | int32(vr.d[idx+2])<<16 | int32(vr.d[idx+3])<<24), nil +} + +func (vr *valueReader) readLength() (int32, error) { return vr.readi32() } + +func (vr *valueReader) readi32() (int32, error) { +	if vr.offset+4 > int64(len(vr.d)) { +		return 0, io.EOF +	} + +	idx := vr.offset +	vr.offset += 4 +	return (int32(vr.d[idx]) | int32(vr.d[idx+1])<<8 | int32(vr.d[idx+2])<<16 | int32(vr.d[idx+3])<<24), nil +} + +func (vr *valueReader) readu32() (uint32, error) { +	if vr.offset+4 > int64(len(vr.d)) { +		return 0, io.EOF +	} + +	idx := vr.offset +	vr.offset += 4 +	return (uint32(vr.d[idx]) | uint32(vr.d[idx+1])<<8 | uint32(vr.d[idx+2])<<16 | uint32(vr.d[idx+3])<<24), nil +} + +func (vr *valueReader) readi64() (int64, error) { +	if vr.offset+8 > int64(len(vr.d)) { +		return 0, io.EOF +	} + +	idx := vr.offset +	vr.offset += 8 +	return int64(vr.d[idx]) | int64(vr.d[idx+1])<<8 | int64(vr.d[idx+2])<<16 | int64(vr.d[idx+3])<<24 | +		int64(vr.d[idx+4])<<32 | int64(vr.d[idx+5])<<40 | int64(vr.d[idx+6])<<48 | int64(vr.d[idx+7])<<56, nil +} + +func (vr *valueReader) readu64() (uint64, error) { +	if vr.offset+8 > int64(len(vr.d)) { +		return 0, io.EOF +	} + +	idx := vr.offset +	vr.offset += 8 +	return uint64(vr.d[idx]) | uint64(vr.d[idx+1])<<8 | uint64(vr.d[idx+2])<<16 | uint64(vr.d[idx+3])<<24 | +		uint64(vr.d[idx+4])<<32 | uint64(vr.d[idx+5])<<40 | uint64(vr.d[idx+6])<<48 | uint64(vr.d[idx+7])<<56, nil +} 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 new file mode 100644 index 000000000..f95a08afd --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/value_writer.go @@ -0,0 +1,606 @@ +// 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 bsonrw + +import ( +	"errors" +	"fmt" +	"io" +	"math" +	"strconv" +	"strings" +	"sync" + +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +var _ ValueWriter = (*valueWriter)(nil) + +var vwPool = sync.Pool{ +	New: func() interface{} { +		return new(valueWriter) +	}, +} + +// BSONValueWriterPool is a pool for BSON ValueWriters. +type BSONValueWriterPool struct { +	pool sync.Pool +} + +// NewBSONValueWriterPool creates a new pool for ValueWriter instances that write to BSON. +func NewBSONValueWriterPool() *BSONValueWriterPool { +	return &BSONValueWriterPool{ +		pool: sync.Pool{ +			New: func() interface{} { +				return new(valueWriter) +			}, +		}, +	} +} + +// Get retrieves a BSON ValueWriter from the pool and resets it to use w as the destination. +func (bvwp *BSONValueWriterPool) Get(w io.Writer) ValueWriter { +	vw := bvwp.pool.Get().(*valueWriter) + +	// TODO: Having to call reset here with the same buffer doesn't really make sense. +	vw.reset(vw.buf) +	vw.buf = vw.buf[:0] +	vw.w = w +	return vw +} + +// GetAtModeElement retrieves a ValueWriterFlusher from the pool and resets it to use w as the destination. +func (bvwp *BSONValueWriterPool) GetAtModeElement(w io.Writer) ValueWriterFlusher { +	vw := bvwp.Get(w).(*valueWriter) +	vw.push(mElement) +	return vw +} + +// Put inserts a ValueWriter into the pool. If the ValueWriter is not a BSON ValueWriter, nothing +// happens and ok will be false. +func (bvwp *BSONValueWriterPool) Put(vw ValueWriter) (ok bool) { +	bvw, ok := vw.(*valueWriter) +	if !ok { +		return false +	} + +	bvwp.pool.Put(bvw) +	return true +} + +// This is here so that during testing we can change it and not require +// allocating a 4GB slice. +var maxSize = math.MaxInt32 + +var errNilWriter = errors.New("cannot create a ValueWriter from a nil io.Writer") + +type errMaxDocumentSizeExceeded struct { +	size int64 +} + +func (mdse errMaxDocumentSizeExceeded) Error() string { +	return fmt.Sprintf("document size (%d) is larger than the max int32", mdse.size) +} + +type vwMode int + +const ( +	_ vwMode = iota +	vwTopLevel +	vwDocument +	vwArray +	vwValue +	vwElement +	vwCodeWithScope +) + +func (vm vwMode) String() string { +	var str string + +	switch vm { +	case vwTopLevel: +		str = "TopLevel" +	case vwDocument: +		str = "DocumentMode" +	case vwArray: +		str = "ArrayMode" +	case vwValue: +		str = "ValueMode" +	case vwElement: +		str = "ElementMode" +	case vwCodeWithScope: +		str = "CodeWithScopeMode" +	default: +		str = "UnknownMode" +	} + +	return str +} + +type vwState struct { +	mode   mode +	key    string +	arrkey int +	start  int32 +} + +type valueWriter struct { +	w   io.Writer +	buf []byte + +	stack []vwState +	frame int64 +} + +func (vw *valueWriter) advanceFrame() { +	if vw.frame+1 >= int64(len(vw.stack)) { // We need to grow the stack +		length := len(vw.stack) +		if length+1 >= cap(vw.stack) { +			// double it +			buf := make([]vwState, 2*cap(vw.stack)+1) +			copy(buf, vw.stack) +			vw.stack = buf +		} +		vw.stack = vw.stack[:length+1] +	} +	vw.frame++ +} + +func (vw *valueWriter) push(m mode) { +	vw.advanceFrame() + +	// Clean the stack +	vw.stack[vw.frame].mode = m +	vw.stack[vw.frame].key = "" +	vw.stack[vw.frame].arrkey = 0 +	vw.stack[vw.frame].start = 0 + +	vw.stack[vw.frame].mode = m +	switch m { +	case mDocument, mArray, mCodeWithScope: +		vw.reserveLength() +	} +} + +func (vw *valueWriter) reserveLength() { +	vw.stack[vw.frame].start = int32(len(vw.buf)) +	vw.buf = append(vw.buf, 0x00, 0x00, 0x00, 0x00) +} + +func (vw *valueWriter) pop() { +	switch vw.stack[vw.frame].mode { +	case mElement, mValue: +		vw.frame-- +	case mDocument, mArray, mCodeWithScope: +		vw.frame -= 2 // we pop twice to jump over the mElement: mDocument -> mElement -> mDocument/mTopLevel/etc... +	} +} + +// NewBSONValueWriter creates a ValueWriter that writes BSON to w. +// +// This ValueWriter will only write entire documents to the io.Writer and it +// will buffer the document as it is built. +func NewBSONValueWriter(w io.Writer) (ValueWriter, error) { +	if w == nil { +		return nil, errNilWriter +	} +	return newValueWriter(w), nil +} + +func newValueWriter(w io.Writer) *valueWriter { +	vw := new(valueWriter) +	stack := make([]vwState, 1, 5) +	stack[0] = vwState{mode: mTopLevel} +	vw.w = w +	vw.stack = stack + +	return vw +} + +func newValueWriterFromSlice(buf []byte) *valueWriter { +	vw := new(valueWriter) +	stack := make([]vwState, 1, 5) +	stack[0] = vwState{mode: mTopLevel} +	vw.stack = stack +	vw.buf = buf + +	return vw +} + +func (vw *valueWriter) reset(buf []byte) { +	if vw.stack == nil { +		vw.stack = make([]vwState, 1, 5) +	} +	vw.stack = vw.stack[:1] +	vw.stack[0] = vwState{mode: mTopLevel} +	vw.buf = buf +	vw.frame = 0 +	vw.w = nil +} + +func (vw *valueWriter) invalidTransitionError(destination mode, name string, modes []mode) error { +	te := TransitionError{ +		name:        name, +		current:     vw.stack[vw.frame].mode, +		destination: destination, +		modes:       modes, +		action:      "write", +	} +	if vw.frame != 0 { +		te.parent = vw.stack[vw.frame-1].mode +	} +	return te +} + +func (vw *valueWriter) writeElementHeader(t bsontype.Type, destination mode, callerName string, addmodes ...mode) error { +	switch vw.stack[vw.frame].mode { +	case mElement: +		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)) +	default: +		modes := []mode{mElement, mValue} +		if addmodes != nil { +			modes = append(modes, addmodes...) +		} +		return vw.invalidTransitionError(destination, callerName, modes) +	} + +	return nil +} + +func (vw *valueWriter) WriteValueBytes(t bsontype.Type, b []byte) error { +	if err := vw.writeElementHeader(t, mode(0), "WriteValueBytes"); err != nil { +		return err +	} +	vw.buf = append(vw.buf, b...) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteArray() (ArrayWriter, error) { +	if err := vw.writeElementHeader(bsontype.Array, mArray, "WriteArray"); err != nil { +		return nil, err +	} + +	vw.push(mArray) + +	return vw, nil +} + +func (vw *valueWriter) WriteBinary(b []byte) error { +	return vw.WriteBinaryWithSubtype(b, 0x00) +} + +func (vw *valueWriter) WriteBinaryWithSubtype(b []byte, btype byte) error { +	if err := vw.writeElementHeader(bsontype.Binary, mode(0), "WriteBinaryWithSubtype"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendBinary(vw.buf, btype, b) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteBoolean(b bool) error { +	if err := vw.writeElementHeader(bsontype.Boolean, mode(0), "WriteBoolean"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendBoolean(vw.buf, b) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteCodeWithScope(code string) (DocumentWriter, error) { +	if err := vw.writeElementHeader(bsontype.CodeWithScope, mCodeWithScope, "WriteCodeWithScope"); err != nil { +		return nil, err +	} + +	// CodeWithScope is a different than other types because we need an extra +	// frame on the stack. In the EndDocument code, we write the document +	// length, pop, write the code with scope length, and pop. To simplify the +	// pop code, we push a spacer frame that we'll always jump over. +	vw.push(mCodeWithScope) +	vw.buf = bsoncore.AppendString(vw.buf, code) +	vw.push(mSpacer) +	vw.push(mDocument) + +	return vw, nil +} + +func (vw *valueWriter) WriteDBPointer(ns string, oid primitive.ObjectID) error { +	if err := vw.writeElementHeader(bsontype.DBPointer, mode(0), "WriteDBPointer"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendDBPointer(vw.buf, ns, oid) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteDateTime(dt int64) error { +	if err := vw.writeElementHeader(bsontype.DateTime, mode(0), "WriteDateTime"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendDateTime(vw.buf, dt) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteDecimal128(d128 primitive.Decimal128) error { +	if err := vw.writeElementHeader(bsontype.Decimal128, mode(0), "WriteDecimal128"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendDecimal128(vw.buf, d128) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteDouble(f float64) error { +	if err := vw.writeElementHeader(bsontype.Double, mode(0), "WriteDouble"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendDouble(vw.buf, f) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteInt32(i32 int32) error { +	if err := vw.writeElementHeader(bsontype.Int32, mode(0), "WriteInt32"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendInt32(vw.buf, i32) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteInt64(i64 int64) error { +	if err := vw.writeElementHeader(bsontype.Int64, mode(0), "WriteInt64"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendInt64(vw.buf, i64) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteJavascript(code string) error { +	if err := vw.writeElementHeader(bsontype.JavaScript, mode(0), "WriteJavascript"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendJavaScript(vw.buf, code) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteMaxKey() error { +	if err := vw.writeElementHeader(bsontype.MaxKey, mode(0), "WriteMaxKey"); err != nil { +		return err +	} + +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteMinKey() error { +	if err := vw.writeElementHeader(bsontype.MinKey, mode(0), "WriteMinKey"); err != nil { +		return err +	} + +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteNull() error { +	if err := vw.writeElementHeader(bsontype.Null, mode(0), "WriteNull"); err != nil { +		return err +	} + +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteObjectID(oid primitive.ObjectID) error { +	if err := vw.writeElementHeader(bsontype.ObjectID, mode(0), "WriteObjectID"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendObjectID(vw.buf, oid) +	vw.pop() +	return nil +} + +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 +	} + +	vw.buf = bsoncore.AppendRegex(vw.buf, pattern, sortStringAlphebeticAscending(options)) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteString(s string) error { +	if err := vw.writeElementHeader(bsontype.String, mode(0), "WriteString"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendString(vw.buf, s) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteDocument() (DocumentWriter, error) { +	if vw.stack[vw.frame].mode == mTopLevel { +		vw.reserveLength() +		return vw, nil +	} +	if err := vw.writeElementHeader(bsontype.EmbeddedDocument, mDocument, "WriteDocument", mTopLevel); err != nil { +		return nil, err +	} + +	vw.push(mDocument) +	return vw, nil +} + +func (vw *valueWriter) WriteSymbol(symbol string) error { +	if err := vw.writeElementHeader(bsontype.Symbol, mode(0), "WriteSymbol"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendSymbol(vw.buf, symbol) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteTimestamp(t uint32, i uint32) error { +	if err := vw.writeElementHeader(bsontype.Timestamp, mode(0), "WriteTimestamp"); err != nil { +		return err +	} + +	vw.buf = bsoncore.AppendTimestamp(vw.buf, t, i) +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteUndefined() error { +	if err := vw.writeElementHeader(bsontype.Undefined, mode(0), "WriteUndefined"); err != nil { +		return err +	} + +	vw.pop() +	return nil +} + +func (vw *valueWriter) WriteDocumentElement(key string) (ValueWriter, error) { +	switch vw.stack[vw.frame].mode { +	case mTopLevel, mDocument: +	default: +		return nil, vw.invalidTransitionError(mElement, "WriteDocumentElement", []mode{mTopLevel, mDocument}) +	} + +	vw.push(mElement) +	vw.stack[vw.frame].key = key + +	return vw, nil +} + +func (vw *valueWriter) WriteDocumentEnd() error { +	switch vw.stack[vw.frame].mode { +	case mTopLevel, mDocument: +	default: +		return fmt.Errorf("incorrect mode to end document: %s", vw.stack[vw.frame].mode) +	} + +	vw.buf = append(vw.buf, 0x00) + +	err := vw.writeLength() +	if err != nil { +		return err +	} + +	if vw.stack[vw.frame].mode == mTopLevel { +		if err = vw.Flush(); err != nil { +			return err +		} +	} + +	vw.pop() + +	if vw.stack[vw.frame].mode == mCodeWithScope { +		// We ignore the error here because of the guarantee of writeLength. +		// See the docs for writeLength for more info. +		_ = vw.writeLength() +		vw.pop() +	} +	return nil +} + +func (vw *valueWriter) Flush() error { +	if vw.w == nil { +		return nil +	} + +	if _, err := vw.w.Write(vw.buf); err != nil { +		return err +	} +	// reset buffer +	vw.buf = vw.buf[:0] +	return nil +} + +func (vw *valueWriter) WriteArrayElement() (ValueWriter, error) { +	if vw.stack[vw.frame].mode != mArray { +		return nil, vw.invalidTransitionError(mValue, "WriteArrayElement", []mode{mArray}) +	} + +	arrkey := vw.stack[vw.frame].arrkey +	vw.stack[vw.frame].arrkey++ + +	vw.push(mValue) +	vw.stack[vw.frame].arrkey = arrkey + +	return vw, nil +} + +func (vw *valueWriter) WriteArrayEnd() error { +	if vw.stack[vw.frame].mode != mArray { +		return fmt.Errorf("incorrect mode to end array: %s", vw.stack[vw.frame].mode) +	} + +	vw.buf = append(vw.buf, 0x00) + +	err := vw.writeLength() +	if err != nil { +		return err +	} + +	vw.pop() +	return nil +} + +// NOTE: We assume that if we call writeLength more than once the same function +// within the same function without altering the vw.buf that this method will +// not return an error. If this changes ensure that the following methods are +// updated: +// +// - WriteDocumentEnd +func (vw *valueWriter) writeLength() error { +	length := len(vw.buf) +	if length > maxSize { +		return errMaxDocumentSizeExceeded{size: int64(len(vw.buf))} +	} +	length = length - int(vw.stack[vw.frame].start) +	start := vw.stack[vw.frame].start + +	vw.buf[start+0] = byte(length) +	vw.buf[start+1] = byte(length >> 8) +	vw.buf[start+2] = byte(length >> 16) +	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/bsonrw/writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/writer.go new file mode 100644 index 000000000..dff65f87f --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/writer.go @@ -0,0 +1,78 @@ +// 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 bsonrw + +import ( +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +) + +// ArrayWriter is the interface used to create a BSON or BSON adjacent array. +// Callers must ensure they call WriteArrayEnd when they have finished creating +// the array. +type ArrayWriter interface { +	WriteArrayElement() (ValueWriter, error) +	WriteArrayEnd() error +} + +// DocumentWriter is the interface used to create a BSON or BSON adjacent +// document. Callers must ensure they call WriteDocumentEnd when they have +// finished creating the document. +type DocumentWriter interface { +	WriteDocumentElement(string) (ValueWriter, error) +	WriteDocumentEnd() error +} + +// ValueWriter is the interface used to write BSON values. Implementations of +// this interface handle creating BSON or BSON adjacent representations of the +// values. +type ValueWriter interface { +	WriteArray() (ArrayWriter, error) +	WriteBinary(b []byte) error +	WriteBinaryWithSubtype(b []byte, btype byte) error +	WriteBoolean(bool) error +	WriteCodeWithScope(code string) (DocumentWriter, error) +	WriteDBPointer(ns string, oid primitive.ObjectID) error +	WriteDateTime(dt int64) error +	WriteDecimal128(primitive.Decimal128) error +	WriteDouble(float64) error +	WriteInt32(int32) error +	WriteInt64(int64) error +	WriteJavascript(code string) error +	WriteMaxKey() error +	WriteMinKey() error +	WriteNull() error +	WriteObjectID(primitive.ObjectID) error +	WriteRegex(pattern, options string) error +	WriteString(string) error +	WriteDocument() (DocumentWriter, error) +	WriteSymbol(symbol string) error +	WriteTimestamp(t, i uint32) error +	WriteUndefined() error +} + +// ValueWriterFlusher is a superset of ValueWriter that exposes functionality to flush to the underlying buffer. +type ValueWriterFlusher interface { +	ValueWriter +	Flush() error +} + +// BytesWriter is the interface used to write BSON bytes to a ValueWriter. +// This interface is meant to be a superset of ValueWriter, so that types that +// implement ValueWriter may also implement this interface. +type BytesWriter interface { +	WriteValueBytes(t bsontype.Type, b []byte) error +} + +// SliceWriter allows a pointer to a slice of bytes to be used as an io.Writer. +type SliceWriter []byte + +func (sw *SliceWriter) Write(p []byte) (int, error) { +	written := len(p) +	*sw = append(*sw, p...) +	return written, nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go b/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go new file mode 100644 index 000000000..7c91ae518 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsontype/bsontype.go @@ -0,0 +1,97 @@ +// 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 bsontype is a utility package that contains types for each BSON type and the +// a stringifier for the Type to enable easier debugging when working with BSON. +package bsontype // import "go.mongodb.org/mongo-driver/bson/bsontype" + +// These constants uniquely refer to each BSON type. +const ( +	Double           Type = 0x01 +	String           Type = 0x02 +	EmbeddedDocument Type = 0x03 +	Array            Type = 0x04 +	Binary           Type = 0x05 +	Undefined        Type = 0x06 +	ObjectID         Type = 0x07 +	Boolean          Type = 0x08 +	DateTime         Type = 0x09 +	Null             Type = 0x0A +	Regex            Type = 0x0B +	DBPointer        Type = 0x0C +	JavaScript       Type = 0x0D +	Symbol           Type = 0x0E +	CodeWithScope    Type = 0x0F +	Int32            Type = 0x10 +	Timestamp        Type = 0x11 +	Int64            Type = 0x12 +	Decimal128       Type = 0x13 +	MinKey           Type = 0xFF +	MaxKey           Type = 0x7F + +	BinaryGeneric     byte = 0x00 +	BinaryFunction    byte = 0x01 +	BinaryBinaryOld   byte = 0x02 +	BinaryUUIDOld     byte = 0x03 +	BinaryUUID        byte = 0x04 +	BinaryMD5         byte = 0x05 +	BinaryEncrypted   byte = 0x06 +	BinaryColumn      byte = 0x07 +	BinaryUserDefined byte = 0x80 +) + +// Type represents a BSON type. +type Type byte + +// String returns the string representation of the BSON type's name. +func (bt Type) String() string { +	switch bt { +	case '\x01': +		return "double" +	case '\x02': +		return "string" +	case '\x03': +		return "embedded document" +	case '\x04': +		return "array" +	case '\x05': +		return "binary" +	case '\x06': +		return "undefined" +	case '\x07': +		return "objectID" +	case '\x08': +		return "boolean" +	case '\x09': +		return "UTC datetime" +	case '\x0A': +		return "null" +	case '\x0B': +		return "regex" +	case '\x0C': +		return "dbPointer" +	case '\x0D': +		return "javascript" +	case '\x0E': +		return "symbol" +	case '\x0F': +		return "code with scope" +	case '\x10': +		return "32-bit integer" +	case '\x11': +		return "timestamp" +	case '\x12': +		return "64-bit integer" +	case '\x13': +		return "128-bit decimal" +	case '\xFF': +		return "min key" +	case '\x7F': +		return "max key" +	default: +		return "invalid" +	} +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/decoder.go b/vendor/go.mongodb.org/mongo-driver/bson/decoder.go new file mode 100644 index 000000000..6e189fa58 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/decoder.go @@ -0,0 +1,141 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"errors" +	"fmt" +	"reflect" +	"sync" + +	"go.mongodb.org/mongo-driver/bson/bsoncodec" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +) + +// ErrDecodeToNil is the error returned when trying to decode to a nil value +var ErrDecodeToNil = errors.New("cannot Decode to nil value") + +// This pool is used to keep the allocations of Decoders down. This is only used for the Marshal* +// methods and is not consumable from outside of this package. The Decoders retrieved from this pool +// must have both Reset and SetRegistry called on them. +var decPool = sync.Pool{ +	New: func() interface{} { +		return new(Decoder) +	}, +} + +// A Decoder reads and decodes BSON documents from a stream. It reads from a bsonrw.ValueReader as +// the source of BSON data. +type Decoder struct { +	dc bsoncodec.DecodeContext +	vr bsonrw.ValueReader + +	// We persist defaultDocumentM and defaultDocumentD on the Decoder to prevent overwriting from +	// (*Decoder).SetContext. +	defaultDocumentM bool +	defaultDocumentD bool +} + +// NewDecoder returns a new decoder that uses the DefaultRegistry to read from vr. +func NewDecoder(vr bsonrw.ValueReader) (*Decoder, error) { +	if vr == nil { +		return nil, errors.New("cannot create a new Decoder with a nil ValueReader") +	} + +	return &Decoder{ +		dc: bsoncodec.DecodeContext{Registry: DefaultRegistry}, +		vr: vr, +	}, nil +} + +// NewDecoderWithContext returns a new decoder that uses DecodeContext dc to read from vr. +func NewDecoderWithContext(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader) (*Decoder, error) { +	if dc.Registry == nil { +		dc.Registry = DefaultRegistry +	} +	if vr == nil { +		return nil, errors.New("cannot create a new Decoder with a nil ValueReader") +	} + +	return &Decoder{ +		dc: dc, +		vr: vr, +	}, nil +} + +// Decode reads the next BSON document from the stream and decodes it into the +// value pointed to by val. +// +// The documentation for Unmarshal contains details about of BSON into a Go +// value. +func (d *Decoder) Decode(val interface{}) error { +	if unmarshaler, ok := val.(Unmarshaler); ok { +		// TODO(skriptble): Reuse a []byte here and use the AppendDocumentBytes method. +		buf, err := bsonrw.Copier{}.CopyDocumentToBytes(d.vr) +		if err != nil { +			return err +		} +		return unmarshaler.UnmarshalBSON(buf) +	} + +	rval := reflect.ValueOf(val) +	switch rval.Kind() { +	case reflect.Ptr: +		if rval.IsNil() { +			return ErrDecodeToNil +		} +		rval = rval.Elem() +	case reflect.Map: +		if rval.IsNil() { +			return ErrDecodeToNil +		} +	default: +		return fmt.Errorf("argument to Decode must be a pointer or a map, but got %v", rval) +	} +	decoder, err := d.dc.LookupDecoder(rval.Type()) +	if err != nil { +		return err +	} +	if d.defaultDocumentM { +		d.dc.DefaultDocumentM() +	} +	if d.defaultDocumentD { +		d.dc.DefaultDocumentD() +	} +	return decoder.DecodeValue(d.dc, d.vr, rval) +} + +// Reset will reset the state of the decoder, using the same *DecodeContext used in +// the original construction but using vr for reading. +func (d *Decoder) Reset(vr bsonrw.ValueReader) error { +	d.vr = vr +	return nil +} + +// SetRegistry replaces the current registry of the decoder with r. +func (d *Decoder) SetRegistry(r *bsoncodec.Registry) error { +	d.dc.Registry = r +	return nil +} + +// SetContext replaces the current registry of the decoder with dc. +func (d *Decoder) SetContext(dc bsoncodec.DecodeContext) error { +	d.dc = dc +	return nil +} + +// DefaultDocumentM will decode empty documents using the primitive.M type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (d *Decoder) DefaultDocumentM() { +	d.defaultDocumentM = true +} + +// DefaultDocumentD will decode empty documents using the primitive.D type. This behavior is restricted to data typed as +// "interface{}" or "map[string]interface{}". +func (d *Decoder) DefaultDocumentD() { +	d.defaultDocumentD = true +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/doc.go new file mode 100644 index 000000000..0134006d8 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/doc.go @@ -0,0 +1,141 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +// Package bson is a library for reading, writing, and manipulating BSON. BSON is a binary serialization format used to +// store documents and make remote procedure calls in MongoDB. The BSON specification is located at https://bsonspec.org. +// The BSON library handles marshalling and unmarshalling of values through a configurable codec system. For a description +// of the codec system and examples of registering custom codecs, see the bsoncodec package. +// +// # Raw BSON +// +// The Raw family of types is used to validate and retrieve elements from a slice of bytes. This +// type is most useful when you want do lookups on BSON bytes without unmarshaling it into another +// type. +// +// Example: +// +//	var raw bson.Raw = ... // bytes from somewhere +//	err := raw.Validate() +//	if err != nil { return err } +//	val := raw.Lookup("foo") +//	i32, ok := val.Int32OK() +//	// do something with i32... +// +// # Native Go Types +// +// The D and M types defined in this package can be used to build representations of BSON using native Go types. D is a +// slice and M is a map. For more information about the use cases for these types, see the documentation on the type +// definitions. +// +// Note that a D should not be constructed with duplicate key names, as that can cause undefined server behavior. +// +// Example: +// +//	bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}} +//	bson.M{"foo": "bar", "hello": "world", "pi": 3.14159} +// +// When decoding BSON to a D or M, the following type mappings apply when unmarshalling: +// +//  1. BSON int32 unmarshals to an int32. +//  2. BSON int64 unmarshals to an int64. +//  3. BSON double unmarshals to a float64. +//  4. BSON string unmarshals to a string. +//  5. BSON boolean unmarshals to a bool. +//  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. +//  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. +//  13. BSON code with scope unmarshals to a primitive.CodeWithScope. +//  14. BSON timestamp unmarshals to an primitive.Timestamp. +//  15. BSON 128-bit decimal unmarshals to an primitive.Decimal128. +//  16. BSON min key unmarshals to an primitive.MinKey. +//  17. BSON max key unmarshals to an primitive.MaxKey. +//  18. BSON undefined unmarshals to a primitive.Undefined. +//  19. BSON null unmarshals to nil. +//  20. BSON DBPointer unmarshals to a primitive.DBPointer. +//  21. BSON symbol unmarshals to a primitive.Symbol. +// +// The above mappings also apply when marshalling a D or M to BSON. Some other useful marshalling mappings are: +// +//  1. time.Time marshals to a BSON datetime. +//  2. int8, int16, and int32 marshal to a BSON int32. +//  3. int marshals to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32, inclusive, and a BSON int64 +//     otherwise. +//  4. int64 marshals to BSON int64. +//  5. uint8 and uint16 marshal to a BSON int32. +//  6. uint, uint32, and uint64 marshal to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32, +//     inclusive, and BSON int64 otherwise. +//  7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshalling a BSON null or +//     undefined value into a string will yield the empty string.). +// +// # Structs +// +// Structs can be marshalled/unmarshalled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended +// JSON, the following rules apply: +// +//  1. Only exported fields in structs will be marshalled or unmarshalled. +// +//  2. When marshalling a struct, each field will be lowercased to generate the key for the corresponding BSON element. +//     For example, a struct field named "Foo" will generate key "foo". This can be overridden via a struct tag (e.g. +//     `bson:"fooField"` to generate key "fooField" instead). +// +//  3. An embedded struct field is marshalled as a subdocument. The key will be the lowercased name of the field's type. +// +//  4. A pointer field is marshalled as the underlying type if the pointer is non-nil. If the pointer is nil, it is +//     marshalled as a BSON null value. +// +//  5. When unmarshalling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents +//     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. +// +// 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. 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 +//     types, this tag is ignored. +// +//  3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles unmarshalled +//     into that field will be truncated at the decimal point. For example, if 3.14 is unmarshalled into a field of type int, +//     it will be unmarshalled as 3. If this tag is not specified, the decoder will throw an error if the value cannot be +//     decoded without losing precision. For float64 or non-numeric types, this tag is ignored. +// +//  4. inline: If the inline struct tag is specified for a struct or map field, the field will be "flattened" when +//     marshalling and "un-flattened" when unmarshalling. This means that all of the fields in that struct/map will be +//     pulled up one level and will become top-level fields rather than being fields in a nested document. For example, if a +//     map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will be +//     {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If there are +//     duplicated fields in the resulting document when an inlined struct is marshalled, the inlined field will be overwritten. +//     If there are duplicated fields in the resulting document when an inlined map is marshalled, an error will be returned. +//     This tag can be used with fields that are pointers to structs. If an inlined pointer field is nil, it will not be +//     marshalled. For fields that are not maps or structs, this tag is ignored. +// +// # Marshalling and Unmarshalling +// +// Manually marshalling and unmarshalling can be done with the Marshal and Unmarshal family of functions. +package bson diff --git a/vendor/go.mongodb.org/mongo-driver/bson/encoder.go b/vendor/go.mongodb.org/mongo-driver/bson/encoder.go new file mode 100644 index 000000000..fe5125d08 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/encoder.go @@ -0,0 +1,99 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"errors" +	"reflect" +	"sync" + +	"go.mongodb.org/mongo-driver/bson/bsoncodec" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +) + +// This pool is used to keep the allocations of Encoders down. This is only used for the Marshal* +// methods and is not consumable from outside of this package. The Encoders retrieved from this pool +// must have both Reset and SetRegistry called on them. +var encPool = sync.Pool{ +	New: func() interface{} { +		return new(Encoder) +	}, +} + +// An Encoder writes a serialization format to an output stream. It writes to a bsonrw.ValueWriter +// as the destination of BSON data. +type Encoder struct { +	ec bsoncodec.EncodeContext +	vw bsonrw.ValueWriter +} + +// NewEncoder returns a new encoder that uses the DefaultRegistry to write to vw. +func NewEncoder(vw bsonrw.ValueWriter) (*Encoder, error) { +	if vw == nil { +		return nil, errors.New("cannot create a new Encoder with a nil ValueWriter") +	} + +	return &Encoder{ +		ec: bsoncodec.EncodeContext{Registry: DefaultRegistry}, +		vw: vw, +	}, nil +} + +// NewEncoderWithContext returns a new encoder that uses EncodeContext ec to write to vw. +func NewEncoderWithContext(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter) (*Encoder, error) { +	if ec.Registry == nil { +		ec = bsoncodec.EncodeContext{Registry: DefaultRegistry} +	} +	if vw == nil { +		return nil, errors.New("cannot create a new Encoder with a nil ValueWriter") +	} + +	return &Encoder{ +		ec: ec, +		vw: vw, +	}, nil +} + +// Encode writes the BSON encoding of val to the stream. +// +// The documentation for Marshal contains details about the conversion of Go +// values to BSON. +func (e *Encoder) Encode(val interface{}) error { +	if marshaler, ok := val.(Marshaler); ok { +		// TODO(skriptble): Should we have a MarshalAppender interface so that we can have []byte reuse? +		buf, err := marshaler.MarshalBSON() +		if err != nil { +			return err +		} +		return bsonrw.Copier{}.CopyDocumentFromBytes(e.vw, buf) +	} + +	encoder, err := e.ec.LookupEncoder(reflect.TypeOf(val)) +	if err != nil { +		return err +	} +	return encoder.EncodeValue(e.ec, e.vw, reflect.ValueOf(val)) +} + +// Reset will reset the state of the encoder, using the same *EncodeContext used in +// the original construction but using vw. +func (e *Encoder) Reset(vw bsonrw.ValueWriter) error { +	e.vw = vw +	return nil +} + +// SetRegistry replaces the current registry of the encoder with r. +func (e *Encoder) SetRegistry(r *bsoncodec.Registry) error { +	e.ec.Registry = r +	return nil +} + +// SetContext replaces the current EncodeContext of the encoder with er. +func (e *Encoder) SetContext(ec bsoncodec.EncodeContext) error { +	e.ec = ec +	return nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/marshal.go b/vendor/go.mongodb.org/mongo-driver/bson/marshal.go new file mode 100644 index 000000000..db8d8ee92 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/marshal.go @@ -0,0 +1,248 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"bytes" +	"encoding/json" + +	"go.mongodb.org/mongo-driver/bson/bsoncodec" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +const defaultDstCap = 256 + +var bvwPool = bsonrw.NewBSONValueWriterPool() +var extjPool = bsonrw.NewExtJSONValueWriterPool() + +// Marshaler is an interface implemented by types that can marshal themselves +// into a BSON document represented as bytes. The bytes returned must be a valid +// BSON document if the error is nil. +type Marshaler interface { +	MarshalBSON() ([]byte, error) +} + +// ValueMarshaler is an interface implemented by types that can marshal +// themselves into a BSON value as bytes. The type must be the valid type for +// the bytes returned. The bytes and byte type together must be valid if the +// error is nil. +type ValueMarshaler interface { +	MarshalBSONValue() (bsontype.Type, []byte, error) +} + +// Marshal returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed into a +// document, MarshalValue should be used instead. +// +// Marshal will use the default registry created by NewRegistry to recursively +// marshal val into a []byte. Marshal will inspect struct tags and alter the +// marshaling process accordingly. +func Marshal(val interface{}) ([]byte, error) { +	return MarshalWithRegistry(DefaultRegistry, val) +} + +// MarshalAppend will encode val as a BSON document and append the bytes to dst. If dst is not large enough to hold the +// bytes, it will be grown. If val is not a type that can be transformed into a document, MarshalValueAppend should be +// used instead. +func MarshalAppend(dst []byte, val interface{}) ([]byte, error) { +	return MarshalAppendWithRegistry(DefaultRegistry, dst, val) +} + +// MarshalWithRegistry returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed +// into a document, MarshalValueWithRegistry should be used instead. +func MarshalWithRegistry(r *bsoncodec.Registry, val interface{}) ([]byte, error) { +	dst := make([]byte, 0) +	return MarshalAppendWithRegistry(r, dst, val) +} + +// MarshalWithContext returns the BSON encoding of val as a BSON document using EncodeContext ec. If val is not a type +// that can be transformed into a document, MarshalValueWithContext should be used instead. +func MarshalWithContext(ec bsoncodec.EncodeContext, val interface{}) ([]byte, error) { +	dst := make([]byte, 0) +	return MarshalAppendWithContext(ec, dst, val) +} + +// MarshalAppendWithRegistry will encode val as a BSON document using Registry r and append the bytes to dst. If dst is +// not large enough to hold the bytes, it will be grown. If val is not a type that can be transformed into a document, +// MarshalValueAppendWithRegistry should be used instead. +func MarshalAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) ([]byte, error) { +	return MarshalAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val) +} + +// MarshalAppendWithContext will encode val as a BSON document using Registry r and EncodeContext ec and append the +// bytes to dst. If dst is not large enough to hold the bytes, it will be grown. If val is not a type that can be +// transformed into a document, MarshalValueAppendWithContext should be used instead. +func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) ([]byte, error) { +	sw := new(bsonrw.SliceWriter) +	*sw = dst +	vw := bvwPool.Get(sw) +	defer bvwPool.Put(vw) + +	enc := encPool.Get().(*Encoder) +	defer encPool.Put(enc) + +	err := enc.Reset(vw) +	if err != nil { +		return nil, err +	} +	err = enc.SetContext(ec) +	if err != nil { +		return nil, err +	} + +	err = enc.Encode(val) +	if err != nil { +		return nil, err +	} + +	return *sw, nil +} + +// MarshalValue returns the BSON encoding of val. +// +// MarshalValue will use bson.DefaultRegistry to transform val into a BSON value. If val is a struct, this function will +// inspect struct tags and alter the marshalling process accordingly. +func MarshalValue(val interface{}) (bsontype.Type, []byte, error) { +	return MarshalValueWithRegistry(DefaultRegistry, val) +} + +// MarshalValueAppend will append the BSON encoding of val to dst. If dst is not large enough to hold the BSON encoding +// of val, dst will be grown. +func MarshalValueAppend(dst []byte, val interface{}) (bsontype.Type, []byte, error) { +	return MarshalValueAppendWithRegistry(DefaultRegistry, dst, val) +} + +// MarshalValueWithRegistry returns the BSON encoding of val using Registry r. +func MarshalValueWithRegistry(r *bsoncodec.Registry, val interface{}) (bsontype.Type, []byte, error) { +	dst := make([]byte, 0) +	return MarshalValueAppendWithRegistry(r, dst, val) +} + +// MarshalValueWithContext returns the BSON encoding of val using EncodeContext ec. +func MarshalValueWithContext(ec bsoncodec.EncodeContext, val interface{}) (bsontype.Type, []byte, error) { +	dst := make([]byte, 0) +	return MarshalValueAppendWithContext(ec, dst, val) +} + +// MarshalValueAppendWithRegistry will append the BSON encoding of val to dst using Registry r. If dst is not large +// enough to hold the BSON encoding of val, dst will be grown. +func MarshalValueAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) (bsontype.Type, []byte, error) { +	return MarshalValueAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val) +} + +// MarshalValueAppendWithContext will append the BSON encoding of val to dst using EncodeContext ec. If dst is not large +// enough to hold the BSON encoding of val, dst will be grown. +func MarshalValueAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) (bsontype.Type, []byte, error) { +	// get a ValueWriter configured to write to dst +	sw := new(bsonrw.SliceWriter) +	*sw = dst +	vwFlusher := bvwPool.GetAtModeElement(sw) + +	// get an Encoder and encode the value +	enc := encPool.Get().(*Encoder) +	defer encPool.Put(enc) +	if err := enc.Reset(vwFlusher); err != nil { +		return 0, nil, err +	} +	if err := enc.SetContext(ec); err != nil { +		return 0, nil, err +	} +	if err := enc.Encode(val); err != nil { +		return 0, nil, err +	} + +	// flush the bytes written because we cannot guarantee that a full document has been written +	// after the flush, *sw will be in the format +	// [value type, 0 (null byte to indicate end of empty element name), value bytes..] +	if err := vwFlusher.Flush(); err != nil { +		return 0, nil, err +	} +	buffer := *sw +	return bsontype.Type(buffer[0]), buffer[2:], nil +} + +// MarshalExtJSON returns the extended JSON encoding of val. +func MarshalExtJSON(val interface{}, canonical, escapeHTML bool) ([]byte, error) { +	return MarshalExtJSONWithRegistry(DefaultRegistry, val, canonical, escapeHTML) +} + +// MarshalExtJSONAppend will append the extended JSON encoding of val to dst. +// If dst is not large enough to hold the extended JSON encoding of val, dst +// will be grown. +func MarshalExtJSONAppend(dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) { +	return MarshalExtJSONAppendWithRegistry(DefaultRegistry, dst, val, canonical, escapeHTML) +} + +// MarshalExtJSONWithRegistry returns the extended JSON encoding of val using Registry r. +func MarshalExtJSONWithRegistry(r *bsoncodec.Registry, val interface{}, canonical, escapeHTML bool) ([]byte, error) { +	dst := make([]byte, 0, defaultDstCap) +	return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML) +} + +// MarshalExtJSONWithContext returns the extended JSON encoding of val using Registry r. +func MarshalExtJSONWithContext(ec bsoncodec.EncodeContext, val interface{}, canonical, escapeHTML bool) ([]byte, error) { +	dst := make([]byte, 0, defaultDstCap) +	return MarshalExtJSONAppendWithContext(ec, dst, val, canonical, escapeHTML) +} + +// MarshalExtJSONAppendWithRegistry will append the extended JSON encoding of +// val to dst using Registry r. If dst is not large enough to hold the BSON +// encoding of val, dst will be grown. +func MarshalExtJSONAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) { +	return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML) +} + +// MarshalExtJSONAppendWithContext will append the extended JSON encoding of +// val to dst using Registry r. If dst is not large enough to hold the BSON +// encoding of val, dst will be grown. +func MarshalExtJSONAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) { +	sw := new(bsonrw.SliceWriter) +	*sw = dst +	ejvw := extjPool.Get(sw, canonical, escapeHTML) +	defer extjPool.Put(ejvw) + +	enc := encPool.Get().(*Encoder) +	defer encPool.Put(enc) + +	err := enc.Reset(ejvw) +	if err != nil { +		return nil, err +	} +	err = enc.SetContext(ec) +	if err != nil { +		return nil, err +	} + +	err = enc.Encode(val) +	if err != nil { +		return nil, err +	} + +	return *sw, nil +} + +// IndentExtJSON will prefix and indent the provided extended JSON src and append it to dst. +func IndentExtJSON(dst *bytes.Buffer, src []byte, prefix, indent string) error { +	return json.Indent(dst, src, prefix, indent) +} + +// MarshalExtJSONIndent returns the extended JSON encoding of val with each line with prefixed +// and indented. +func MarshalExtJSONIndent(val interface{}, canonical, escapeHTML bool, prefix, indent string) ([]byte, error) { +	marshaled, err := MarshalExtJSON(val, canonical, escapeHTML) +	if err != nil { +		return nil, err +	} + +	var buf bytes.Buffer +	err = IndentExtJSON(&buf, marshaled, prefix, indent) +	if err != nil { +		return nil, err +	} + +	return buf.Bytes(), nil +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go new file mode 100644 index 000000000..ba7c9112e --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go @@ -0,0 +1,423 @@ +// 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 +// +// Based on gopkg.in/mgo.v2/bson by Gustavo Niemeyer +// See THIRD-PARTY-NOTICES for original license terms. + +package primitive + +import ( +	"encoding/json" +	"errors" +	"fmt" +	"math/big" +	"regexp" +	"strconv" +	"strings" +) + +// These constants are the maximum and minimum values for the exponent field in a decimal128 value. +const ( +	MaxDecimal128Exp = 6111 +	MinDecimal128Exp = -6176 +) + +// These errors are returned when an invalid value is parsed as a big.Int. +var ( +	ErrParseNaN    = errors.New("cannot parse NaN as a *big.Int") +	ErrParseInf    = errors.New("cannot parse Infinity as a *big.Int") +	ErrParseNegInf = errors.New("cannot parse -Infinity as a *big.Int") +) + +// Decimal128 holds decimal128 BSON values. +type Decimal128 struct { +	h, l uint64 +} + +// NewDecimal128 creates a Decimal128 using the provide high and low uint64s. +func NewDecimal128(h, l uint64) Decimal128 { +	return Decimal128{h: h, l: l} +} + +// GetBytes returns the underlying bytes of the BSON decimal value as two uint64 values. The first +// contains the most first 8 bytes of the value and the second contains the latter. +func (d Decimal128) GetBytes() (uint64, uint64) { +	return d.h, d.l +} + +// String returns a string representation of the decimal value. +func (d Decimal128) String() string { +	var posSign int      // positive sign +	var exp int          // exponent +	var high, low uint64 // significand high/low + +	if d.h>>63&1 == 0 { +		posSign = 1 +	} + +	switch d.h >> 58 & (1<<5 - 1) { +	case 0x1F: +		return "NaN" +	case 0x1E: +		return "-Infinity"[posSign:] +	} + +	low = d.l +	if d.h>>61&3 == 3 { +		// Bits: 1*sign 2*ignored 14*exponent 111*significand. +		// Implicit 0b100 prefix in significand. +		exp = int(d.h >> 47 & (1<<14 - 1)) +		//high = 4<<47 | d.h&(1<<47-1) +		// Spec says all of these values are out of range. +		high, low = 0, 0 +	} else { +		// Bits: 1*sign 14*exponent 113*significand +		exp = int(d.h >> 49 & (1<<14 - 1)) +		high = d.h & (1<<49 - 1) +	} +	exp += MinDecimal128Exp + +	// Would be handled by the logic below, but that's trivial and common. +	if high == 0 && low == 0 && exp == 0 { +		return "-0"[posSign:] +	} + +	var repr [48]byte // Loop 5 times over 9 digits plus dot, negative sign, and leading zero. +	var last = len(repr) +	var i = len(repr) +	var dot = len(repr) + exp +	var rem uint32 +Loop: +	for d9 := 0; d9 < 5; d9++ { +		high, low, rem = divmod(high, low, 1e9) +		for d1 := 0; d1 < 9; d1++ { +			// Handle "-0.0", "0.00123400", "-1.00E-6", "1.050E+3", etc. +			if i < len(repr) && (dot == i || low == 0 && high == 0 && rem > 0 && rem < 10 && (dot < i-6 || exp > 0)) { +				exp += len(repr) - i +				i-- +				repr[i] = '.' +				last = i - 1 +				dot = len(repr) // Unmark. +			} +			c := '0' + byte(rem%10) +			rem /= 10 +			i-- +			repr[i] = c +			// Handle "0E+3", "1E+3", etc. +			if low == 0 && high == 0 && rem == 0 && i == len(repr)-1 && (dot < i-5 || exp > 0) { +				last = i +				break Loop +			} +			if c != '0' { +				last = i +			} +			// Break early. Works without it, but why. +			if dot > i && low == 0 && high == 0 && rem == 0 { +				break Loop +			} +		} +	} +	repr[last-1] = '-' +	last-- + +	if exp > 0 { +		return string(repr[last+posSign:]) + "E+" + strconv.Itoa(exp) +	} +	if exp < 0 { +		return string(repr[last+posSign:]) + "E" + strconv.Itoa(exp) +	} +	return string(repr[last+posSign:]) +} + +// BigInt returns significand as big.Int and exponent, bi * 10 ^ exp. +func (d Decimal128) BigInt() (*big.Int, int, error) { +	high, low := d.GetBytes() +	posSign := high>>63&1 == 0 // positive sign + +	switch high >> 58 & (1<<5 - 1) { +	case 0x1F: +		return nil, 0, ErrParseNaN +	case 0x1E: +		if posSign { +			return nil, 0, ErrParseInf +		} +		return nil, 0, ErrParseNegInf +	} + +	var exp int +	if high>>61&3 == 3 { +		// Bits: 1*sign 2*ignored 14*exponent 111*significand. +		// Implicit 0b100 prefix in significand. +		exp = int(high >> 47 & (1<<14 - 1)) +		//high = 4<<47 | d.h&(1<<47-1) +		// Spec says all of these values are out of range. +		high, low = 0, 0 +	} else { +		// Bits: 1*sign 14*exponent 113*significand +		exp = int(high >> 49 & (1<<14 - 1)) +		high = high & (1<<49 - 1) +	} +	exp += MinDecimal128Exp + +	// Would be handled by the logic below, but that's trivial and common. +	if high == 0 && low == 0 && exp == 0 { +		if posSign { +			return new(big.Int), 0, nil +		} +		return new(big.Int), 0, nil +	} + +	bi := big.NewInt(0) +	const host32bit = ^uint(0)>>32 == 0 +	if host32bit { +		bi.SetBits([]big.Word{big.Word(low), big.Word(low >> 32), big.Word(high), big.Word(high >> 32)}) +	} else { +		bi.SetBits([]big.Word{big.Word(low), big.Word(high)}) +	} + +	if !posSign { +		return bi.Neg(bi), exp, nil +	} +	return bi, exp, nil +} + +// IsNaN returns whether d is NaN. +func (d Decimal128) IsNaN() bool { +	return d.h>>58&(1<<5-1) == 0x1F +} + +// IsInf returns: +// +//	+1 d == Infinity +//	 0 other case +//	-1 d == -Infinity +func (d Decimal128) IsInf() int { +	if d.h>>58&(1<<5-1) != 0x1E { +		return 0 +	} + +	if d.h>>63&1 == 0 { +		return 1 +	} +	return -1 +} + +// IsZero returns true if d is the empty Decimal128. +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 +	aq := a / div64 +	ar := a % div64 +	b := ar<<32 + h&(1<<32-1) +	bq := b / div64 +	br := b % div64 +	c := br<<32 + l>>32 +	cq := c / div64 +	cr := c % div64 +	d := cr<<32 + l&(1<<32-1) +	dq := d / div64 +	dr := d % div64 +	return (aq<<32 | bq), (cq<<32 | dq), uint32(dr) +} + +var dNaN = Decimal128{0x1F << 58, 0} +var dPosInf = Decimal128{0x1E << 58, 0} +var dNegInf = Decimal128{0x3E << 58, 0} + +func dErr(s string) (Decimal128, error) { +	return dNaN, fmt.Errorf("cannot parse %q as a decimal128", s) +} + +// match scientific notation number, example -10.15e-18 +var normalNumber = regexp.MustCompile(`^(?P<int>[-+]?\d*)?(?:\.(?P<dec>\d*))?(?:[Ee](?P<exp>[-+]?\d+))?$`) + +// ParseDecimal128 takes the given string and attempts to parse it into a valid +// Decimal128 value. +func ParseDecimal128(s string) (Decimal128, error) { +	if s == "" { +		return dErr(s) +	} + +	matches := normalNumber.FindStringSubmatch(s) +	if len(matches) == 0 { +		orig := s +		neg := s[0] == '-' +		if neg || s[0] == '+' { +			s = s[1:] +		} + +		if s == "NaN" || s == "nan" || strings.EqualFold(s, "nan") { +			return dNaN, nil +		} +		if s == "Inf" || s == "inf" || strings.EqualFold(s, "inf") || strings.EqualFold(s, "infinity") { +			if neg { +				return dNegInf, nil +			} +			return dPosInf, nil +		} +		return dErr(orig) +	} + +	intPart := matches[1] +	decPart := matches[2] +	expPart := matches[3] + +	var err error +	exp := 0 +	if expPart != "" { +		exp, err = strconv.Atoi(expPart) +		if err != nil { +			return dErr(s) +		} +	} +	if decPart != "" { +		exp -= len(decPart) +	} + +	if len(strings.Trim(intPart+decPart, "-0")) > 35 { +		return dErr(s) +	} + +	bi, ok := new(big.Int).SetString(intPart+decPart, 10) +	if !ok { +		return dErr(s) +	} + +	d, ok := ParseDecimal128FromBigInt(bi, exp) +	if !ok { +		return dErr(s) +	} + +	if bi.Sign() == 0 && s[0] == '-' { +		d.h |= 1 << 63 +	} + +	return d, nil +} + +var ( +	ten  = big.NewInt(10) +	zero = new(big.Int) + +	maxS, _ = new(big.Int).SetString("9999999999999999999999999999999999", 10) +) + +// ParseDecimal128FromBigInt attempts to parse the given significand and exponent into a valid Decimal128 value. +func ParseDecimal128FromBigInt(bi *big.Int, exp int) (Decimal128, bool) { +	//copy +	bi = new(big.Int).Set(bi) + +	q := new(big.Int) +	r := new(big.Int) + +	for bigIntCmpAbs(bi, maxS) == 1 { +		bi, _ = q.QuoRem(bi, ten, r) +		if r.Cmp(zero) != 0 { +			return Decimal128{}, false +		} +		exp++ +		if exp > MaxDecimal128Exp { +			return Decimal128{}, false +		} +	} + +	for exp < MinDecimal128Exp { +		// Subnormal. +		bi, _ = q.QuoRem(bi, ten, r) +		if r.Cmp(zero) != 0 { +			return Decimal128{}, false +		} +		exp++ +	} +	for exp > MaxDecimal128Exp { +		// Clamped. +		bi.Mul(bi, ten) +		if bigIntCmpAbs(bi, maxS) == 1 { +			return Decimal128{}, false +		} +		exp-- +	} + +	b := bi.Bytes() +	var h, l uint64 +	for i := 0; i < len(b); i++ { +		if i < len(b)-8 { +			h = h<<8 | uint64(b[i]) +			continue +		} +		l = l<<8 | uint64(b[i]) +	} + +	h |= uint64(exp-MinDecimal128Exp) & uint64(1<<14-1) << 49 +	if bi.Sign() == -1 { +		h |= 1 << 63 +	} + +	return Decimal128{h: h, l: l}, true +} + +// bigIntCmpAbs computes big.Int.Cmp(absoluteValue(x), absoluteValue(y)). +func bigIntCmpAbs(x, y *big.Int) int { +	xAbs := bigIntAbsValue(x) +	yAbs := bigIntAbsValue(y) +	return xAbs.Cmp(yAbs) +} + +// bigIntAbsValue returns a big.Int containing the absolute value of b. +// If b is already a non-negative number, it is returned without any changes or copies. +func bigIntAbsValue(b *big.Int) *big.Int { +	if b.Sign() >= 0 { +		return b // already positive +	} +	return new(big.Int).Abs(b) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go new file mode 100644 index 000000000..ded367316 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go @@ -0,0 +1,206 @@ +// 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 +// +// Based on gopkg.in/mgo.v2/bson by Gustavo Niemeyer +// See THIRD-PARTY-NOTICES for original license terms. + +package primitive + +import ( +	"crypto/rand" +	"encoding" +	"encoding/binary" +	"encoding/hex" +	"encoding/json" +	"errors" +	"fmt" +	"io" +	"sync/atomic" +	"time" +) + +// ErrInvalidHex indicates that a hex string cannot be converted to an ObjectID. +var ErrInvalidHex = errors.New("the provided hex string is not a valid ObjectID") + +// ObjectID is the BSON ObjectID type. +type ObjectID [12]byte + +// NilObjectID is the zero value for ObjectID. +var NilObjectID ObjectID + +var objectIDCounter = readRandomUint32() +var processUnique = processUniqueBytes() + +var _ encoding.TextMarshaler = ObjectID{} +var _ encoding.TextUnmarshaler = &ObjectID{} + +// NewObjectID generates a new ObjectID. +func NewObjectID() ObjectID { +	return NewObjectIDFromTimestamp(time.Now()) +} + +// NewObjectIDFromTimestamp generates a new ObjectID based on the given time. +func NewObjectIDFromTimestamp(timestamp time.Time) ObjectID { +	var b [12]byte + +	binary.BigEndian.PutUint32(b[0:4], uint32(timestamp.Unix())) +	copy(b[4:9], processUnique[:]) +	putUint24(b[9:12], atomic.AddUint32(&objectIDCounter, 1)) + +	return b +} + +// Timestamp extracts the time part of the ObjectId. +func (id ObjectID) Timestamp() time.Time { +	unixSecs := binary.BigEndian.Uint32(id[0:4]) +	return time.Unix(int64(unixSecs), 0).UTC() +} + +// Hex returns the hex encoding of the ObjectID as a string. +func (id ObjectID) Hex() string { +	var buf [24]byte +	hex.Encode(buf[:], id[:]) +	return string(buf[:]) +} + +func (id ObjectID) String() string { +	return fmt.Sprintf("ObjectID(%q)", id.Hex()) +} + +// IsZero returns true if id is the empty ObjectID. +func (id ObjectID) IsZero() bool { +	return id == NilObjectID +} + +// ObjectIDFromHex creates a new ObjectID from a hex string. It returns an error if the hex string is not a +// valid ObjectID. +func ObjectIDFromHex(s string) (ObjectID, error) { +	if len(s) != 24 { +		return NilObjectID, ErrInvalidHex +	} + +	b, err := hex.DecodeString(s) +	if err != nil { +		return NilObjectID, err +	} + +	var oid [12]byte +	copy(oid[:], b) + +	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 +} + +// MarshalText returns the ObjectID as UTF-8-encoded text. Implementing this allows us to use ObjectID +// as a map key when marshalling JSON. See https://pkg.go.dev/encoding#TextMarshaler +func (id ObjectID) MarshalText() ([]byte, error) { +	return []byte(id.Hex()), nil +} + +// UnmarshalText populates the byte slice with the ObjectID. Implementing this allows us to use ObjectID +// as a map key when unmarshalling JSON. See https://pkg.go.dev/encoding#TextUnmarshaler +func (id *ObjectID) UnmarshalText(b []byte) error { +	oid, err := ObjectIDFromHex(string(b)) +	if err != nil { +		return err +	} +	*id = oid +	return nil +} + +// MarshalJSON returns the ObjectID as a string +func (id ObjectID) MarshalJSON() ([]byte, error) { +	return json.Marshal(id.Hex()) +} + +// UnmarshalJSON populates the byte slice with the ObjectID. If the byte slice is 24 bytes long, it +// will be populated with the hex representation of the ObjectID. If the byte slice is twelve bytes +// long, it will be populated with the BSON representation of the ObjectID. This method also accepts empty strings and +// decodes them as NilObjectID. For any other inputs, an error will be returned. +func (id *ObjectID) UnmarshalJSON(b []byte) error { +	// Ignore "null" to keep parity with the standard library. Decoding a JSON null into a non-pointer ObjectID 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 err error +	switch len(b) { +	case 12: +		copy(id[:], b) +	default: +		// Extended JSON +		var res interface{} +		err := json.Unmarshal(b, &res) +		if err != nil { +			return err +		} +		str, ok := res.(string) +		if !ok { +			m, ok := res.(map[string]interface{}) +			if !ok { +				return errors.New("not an extended JSON ObjectID") +			} +			oid, ok := m["$oid"] +			if !ok { +				return errors.New("not an extended JSON ObjectID") +			} +			str, ok = oid.(string) +			if !ok { +				return errors.New("not an extended JSON ObjectID") +			} +		} + +		// An empty string is not a valid ObjectID, but we treat it as a special value that decodes as NilObjectID. +		if len(str) == 0 { +			copy(id[:], NilObjectID[:]) +			return nil +		} + +		if len(str) != 24 { +			return fmt.Errorf("cannot unmarshal into an ObjectID, the length must be 24 but it is %d", len(str)) +		} + +		_, err = hex.Decode(id[:], []byte(str)) +		if err != nil { +			return err +		} +	} + +	return err +} + +func processUniqueBytes() [5]byte { +	var b [5]byte +	_, err := io.ReadFull(rand.Reader, b[:]) +	if err != nil { +		panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err)) +	} + +	return b +} + +func readRandomUint32() uint32 { +	var b [4]byte +	_, err := io.ReadFull(rand.Reader, b[:]) +	if err != nil { +		panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err)) +	} + +	return (uint32(b[0]) << 0) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) +} + +func putUint24(b []byte, v uint32) { +	b[0] = byte(v >> 16) +	b[1] = byte(v >> 8) +	b[2] = byte(v) +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/primitive.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/primitive.go new file mode 100644 index 000000000..c72ccc1c4 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/primitive.go @@ -0,0 +1,217 @@ +// 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 primitive contains types similar to Go primitives for BSON types that do not have direct +// Go primitive representations. +package primitive // import "go.mongodb.org/mongo-driver/bson/primitive" + +import ( +	"bytes" +	"encoding/json" +	"fmt" +	"time" +) + +// Binary represents a BSON binary value. +type Binary struct { +	Subtype byte +	Data    []byte +} + +// Equal compares bp to bp2 and returns true if they are equal. +func (bp Binary) Equal(bp2 Binary) bool { +	if bp.Subtype != bp2.Subtype { +		return false +	} +	return bytes.Equal(bp.Data, bp2.Data) +} + +// IsZero returns if bp is the empty Binary. +func (bp Binary) IsZero() bool { +	return bp.Subtype == 0 && len(bp.Data) == 0 +} + +// Undefined represents the BSON undefined value type. +type Undefined struct{} + +// DateTime represents the BSON datetime value. +type DateTime int64 + +var _ json.Marshaler = DateTime(0) +var _ json.Unmarshaler = (*DateTime)(nil) + +// MarshalJSON marshal to time type. +func (d DateTime) MarshalJSON() ([]byte, error) { +	return json.Marshal(d.Time()) +} + +// UnmarshalJSON creates a primitive.DateTime from a JSON string. +func (d *DateTime) UnmarshalJSON(data []byte) error { +	// Ignore "null" to keep parity with the time.Time type and the standard library. Decoding "null" into a non-pointer +	// DateTime field will leave the field unchanged. For pointer values, the encoding/json will set the pointer to nil +	// and will not defer to the UnmarshalJSON hook. +	if string(data) == "null" { +		return nil +	} + +	var tempTime time.Time +	if err := json.Unmarshal(data, &tempTime); err != nil { +		return err +	} + +	*d = NewDateTimeFromTime(tempTime) +	return nil +} + +// Time returns the date as a time type. +func (d DateTime) Time() time.Time { +	return time.Unix(int64(d)/1000, int64(d)%1000*1000000) +} + +// NewDateTimeFromTime creates a new DateTime from a Time. +func NewDateTimeFromTime(t time.Time) DateTime { +	return DateTime(t.Unix()*1e3 + int64(t.Nanosecond())/1e6) +} + +// Null represents the BSON null value. +type Null struct{} + +// Regex represents a BSON regex value. +type Regex struct { +	Pattern string +	Options string +} + +func (rp Regex) String() string { +	return fmt.Sprintf(`{"pattern": "%s", "options": "%s"}`, rp.Pattern, rp.Options) +} + +// Equal compares rp to rp2 and returns true if they are equal. +func (rp Regex) Equal(rp2 Regex) bool { +	return rp.Pattern == rp2.Pattern && rp.Options == rp2.Options +} + +// IsZero returns if rp is the empty Regex. +func (rp Regex) IsZero() bool { +	return rp.Pattern == "" && rp.Options == "" +} + +// DBPointer represents a BSON dbpointer value. +type DBPointer struct { +	DB      string +	Pointer ObjectID +} + +func (d DBPointer) String() string { +	return fmt.Sprintf(`{"db": "%s", "pointer": "%s"}`, d.DB, d.Pointer) +} + +// Equal compares d to d2 and returns true if they are equal. +func (d DBPointer) Equal(d2 DBPointer) bool { +	return d == d2 +} + +// IsZero returns if d is the empty DBPointer. +func (d DBPointer) IsZero() bool { +	return d.DB == "" && d.Pointer.IsZero() +} + +// JavaScript represents a BSON JavaScript code value. +type JavaScript string + +// Symbol represents a BSON symbol value. +type Symbol string + +// CodeWithScope represents a BSON JavaScript code with scope value. +type CodeWithScope struct { +	Code  JavaScript +	Scope interface{} +} + +func (cws CodeWithScope) String() string { +	return fmt.Sprintf(`{"code": "%s", "scope": %v}`, cws.Code, cws.Scope) +} + +// Timestamp represents a BSON timestamp value. +type Timestamp struct { +	T uint32 +	I uint32 +} + +// Equal compares tp to tp2 and returns true if they are equal. +func (tp Timestamp) Equal(tp2 Timestamp) bool { +	return tp.T == tp2.T && tp.I == tp2.I +} + +// IsZero returns if tp is the zero Timestamp. +func (tp Timestamp) IsZero() bool { +	return tp.T == 0 && tp.I == 0 +} + +// CompareTimestamp returns an integer comparing two Timestamps, where T is compared first, followed by I. +// Returns 0 if tp = tp2, 1 if tp > tp2, -1 if tp < tp2. +func CompareTimestamp(tp, tp2 Timestamp) int { +	if tp.Equal(tp2) { +		return 0 +	} + +	if tp.T > tp2.T { +		return 1 +	} +	if tp.T < tp2.T { +		return -1 +	} +	// Compare I values because T values are equal +	if tp.I > tp2.I { +		return 1 +	} +	return -1 +} + +// MinKey represents the BSON minkey value. +type MinKey struct{} + +// MaxKey represents the BSON maxkey value. +type MaxKey struct{} + +// D is an ordered representation of a BSON document. This type should be used when the order of the elements matters, +// such as MongoDB command documents. If the order of the elements does not matter, an M should be used instead. +// +// Example usage: +// +//	bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}} +type D []E + +// Map creates a map from the elements of the D. +func (d D) Map() M { +	m := make(M, len(d)) +	for _, e := range d { +		m[e.Key] = e.Value +	} +	return m +} + +// E represents a BSON element for a D. It is usually used inside a D. +type E struct { +	Key   string +	Value interface{} +} + +// M is an unordered representation of a BSON document. This type should be used when the order of the elements does not +// matter. This type is handled as a regular map[string]interface{} when encoding and decoding. Elements will be +// serialized in an undefined, random order. If the order of the elements matters, a D should be used instead. +// +// Example usage: +// +//	bson.M{"foo": "bar", "hello": "world", "pi": 3.14159} +type M map[string]interface{} + +// An A is an ordered representation of a BSON array. +// +// Example usage: +// +//	bson.A{"bar", "world", 3.14159, bson.D{{"qux", 12345}}} +type A []interface{} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive_codecs.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive_codecs.go new file mode 100644 index 000000000..1cbe3884d --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive_codecs.go @@ -0,0 +1,92 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"errors" +	"reflect" + +	"go.mongodb.org/mongo-driver/bson/bsoncodec" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +) + +var tRawValue = reflect.TypeOf(RawValue{}) +var tRaw = reflect.TypeOf(Raw(nil)) + +var primitiveCodecs PrimitiveCodecs + +// PrimitiveCodecs is a namespace for all of the default bsoncodec.Codecs for the primitive types +// defined in this package. +type PrimitiveCodecs struct{} + +// RegisterPrimitiveCodecs will register the encode and decode methods attached to PrimitiveCodecs +// with the provided RegistryBuilder. if rb is nil, a new empty RegistryBuilder will be created. +func (pc PrimitiveCodecs) RegisterPrimitiveCodecs(rb *bsoncodec.RegistryBuilder) { +	if rb == nil { +		panic(errors.New("argument to RegisterPrimitiveCodecs must not be nil")) +	} + +	rb. +		RegisterTypeEncoder(tRawValue, bsoncodec.ValueEncoderFunc(pc.RawValueEncodeValue)). +		RegisterTypeEncoder(tRaw, bsoncodec.ValueEncoderFunc(pc.RawEncodeValue)). +		RegisterTypeDecoder(tRawValue, bsoncodec.ValueDecoderFunc(pc.RawValueDecodeValue)). +		RegisterTypeDecoder(tRaw, bsoncodec.ValueDecoderFunc(pc.RawDecodeValue)) +} + +// RawValueEncodeValue is the ValueEncoderFunc for RawValue. +func (PrimitiveCodecs) RawValueEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tRawValue { +		return bsoncodec.ValueEncoderError{Name: "RawValueEncodeValue", Types: []reflect.Type{tRawValue}, Received: val} +	} + +	rawvalue := val.Interface().(RawValue) + +	return bsonrw.Copier{}.CopyValueFromBytes(vw, rawvalue.Type, rawvalue.Value) +} + +// RawValueDecodeValue is the ValueDecoderFunc for RawValue. +func (PrimitiveCodecs) RawValueDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tRawValue { +		return bsoncodec.ValueDecoderError{Name: "RawValueDecodeValue", Types: []reflect.Type{tRawValue}, Received: val} +	} + +	t, value, err := bsonrw.Copier{}.CopyValueToBytes(vr) +	if err != nil { +		return err +	} + +	val.Set(reflect.ValueOf(RawValue{Type: t, Value: value})) +	return nil +} + +// RawEncodeValue is the ValueEncoderFunc for Reader. +func (PrimitiveCodecs) RawEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error { +	if !val.IsValid() || val.Type() != tRaw { +		return bsoncodec.ValueEncoderError{Name: "RawEncodeValue", Types: []reflect.Type{tRaw}, Received: val} +	} + +	rdr := val.Interface().(Raw) + +	return bsonrw.Copier{}.CopyDocumentFromBytes(vw, rdr) +} + +// RawDecodeValue is the ValueDecoderFunc for Reader. +func (PrimitiveCodecs) RawDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error { +	if !val.CanSet() || val.Type() != tRaw { +		return bsoncodec.ValueDecoderError{Name: "RawDecodeValue", Types: []reflect.Type{tRaw}, Received: val} +	} + +	if val.IsNil() { +		val.Set(reflect.MakeSlice(val.Type(), 0, 0)) +	} + +	val.SetLen(0) + +	rdr, err := bsonrw.Copier{}.AppendDocumentBytes(val.Interface().(Raw), vr) +	val.Set(reflect.ValueOf(rdr)) +	return err +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/raw.go b/vendor/go.mongodb.org/mongo-driver/bson/raw.go new file mode 100644 index 000000000..efd705daa --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/raw.go @@ -0,0 +1,85 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"errors" +	"io" + +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +// ErrNilReader indicates that an operation was attempted on a nil bson.Reader. +var ErrNilReader = errors.New("nil reader") + +// Raw is a wrapper around a byte slice. It will interpret the slice as a +// BSON document. This type is a wrapper around a bsoncore.Document. Errors returned from the +// methods on this type and associated types come from the bsoncore package. +type Raw []byte + +// NewFromIOReader reads in a document from the given io.Reader and constructs a Raw from +// it. +func NewFromIOReader(r io.Reader) (Raw, error) { +	doc, err := bsoncore.NewDocumentFromReader(r) +	return Raw(doc), err +} + +// Validate validates the document. This method only validates the first document in +// the slice, to validate other documents, the slice must be resliced. +func (r Raw) Validate() (err error) { return bsoncore.Document(r).Validate() } + +// Lookup search the document, potentially recursively, for the given key. If +// there are multiple keys provided, this method will recurse down, as long as +// the top and intermediate nodes are either documents or arrays.If an error +// occurs or if the value doesn't exist, an empty RawValue is returned. +func (r Raw) Lookup(key ...string) RawValue { +	return convertFromCoreValue(bsoncore.Document(r).Lookup(key...)) +} + +// LookupErr searches the document and potentially subdocuments or arrays for the +// provided key. Each key provided to this method represents a layer of depth. +func (r Raw) LookupErr(key ...string) (RawValue, error) { +	val, err := bsoncore.Document(r).LookupErr(key...) +	return convertFromCoreValue(val), err +} + +// Elements returns this document as a slice of elements. The returned slice will contain valid +// elements. If the document is not valid, the elements up to the invalid point will be returned +// along with an error. +func (r Raw) Elements() ([]RawElement, error) { +	elems, err := bsoncore.Document(r).Elements() +	relems := make([]RawElement, 0, len(elems)) +	for _, elem := range elems { +		relems = append(relems, RawElement(elem)) +	} +	return relems, err +} + +// Values returns this document as a slice of values. The returned slice will contain valid values. +// If the document is not valid, the values up to the invalid point will be returned along with an +// error. +func (r Raw) Values() ([]RawValue, error) { +	vals, err := bsoncore.Document(r).Values() +	rvals := make([]RawValue, 0, len(vals)) +	for _, val := range vals { +		rvals = append(rvals, convertFromCoreValue(val)) +	} +	return rvals, err +} + +// Index searches for and retrieves the element at the given index. This method will panic if +// the document is invalid or if the index is out of bounds. +func (r Raw) Index(index uint) RawElement { return RawElement(bsoncore.Document(r).Index(index)) } + +// IndexErr searches for and retrieves the element at the given index. +func (r Raw) IndexErr(index uint) (RawElement, error) { +	elem, err := bsoncore.Document(r).IndexErr(index) +	return RawElement(elem), err +} + +// String implements the fmt.Stringer interface. +func (r Raw) String() string { return bsoncore.Document(r).String() } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/raw_element.go b/vendor/go.mongodb.org/mongo-driver/bson/raw_element.go new file mode 100644 index 000000000..006f503a3 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/raw_element.go @@ -0,0 +1,51 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +// RawElement represents a BSON element in byte form. This type provides a simple way to +// transform a slice of bytes into a BSON element and extract information from it. +// +// RawElement is a thin wrapper around a bsoncore.Element. +type RawElement []byte + +// Key returns the key for this element. If the element is not valid, this method returns an empty +// string. If knowing if the element is valid is important, use KeyErr. +func (re RawElement) Key() string { return bsoncore.Element(re).Key() } + +// KeyErr returns the key for this element, returning an error if the element is not valid. +func (re RawElement) KeyErr() (string, error) { return bsoncore.Element(re).KeyErr() } + +// Value returns the value of this element. If the element is not valid, this method returns an +// empty Value. If knowing if the element is valid is important, use ValueErr. +func (re RawElement) Value() RawValue { return convertFromCoreValue(bsoncore.Element(re).Value()) } + +// ValueErr returns the value for this element, returning an error if the element is not valid. +func (re RawElement) ValueErr() (RawValue, error) { +	val, err := bsoncore.Element(re).ValueErr() +	return convertFromCoreValue(val), err +} + +// Validate ensures re is a valid BSON element. +func (re RawElement) Validate() error { return bsoncore.Element(re).Validate() } + +// String implements the fmt.Stringer interface. The output will be in extended JSON format. +func (re RawElement) String() string { +	doc := bsoncore.BuildDocument(nil, re) +	j, err := MarshalExtJSON(Raw(doc), true, false) +	if err != nil { +		return "<malformed>" +	} +	return string(j) +} + +// DebugString outputs a human readable version of RawElement. It will attempt to stringify the +// valid components of the element even if the entire element is not valid. +func (re RawElement) DebugString() string { return bsoncore.Element(re).DebugString() } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go b/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go new file mode 100644 index 000000000..75297f30f --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/raw_value.go @@ -0,0 +1,309 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"bytes" +	"errors" +	"fmt" +	"reflect" +	"time" + +	"go.mongodb.org/mongo-driver/bson/bsoncodec" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +	"go.mongodb.org/mongo-driver/bson/primitive" +	"go.mongodb.org/mongo-driver/x/bsonx/bsoncore" +) + +// ErrNilContext is returned when the provided DecodeContext is nil. +var ErrNilContext = errors.New("DecodeContext cannot be nil") + +// ErrNilRegistry is returned when the provided registry is nil. +var ErrNilRegistry = errors.New("Registry cannot be nil") + +// RawValue represents a BSON value in byte form. It can be used to hold unprocessed BSON or to +// defer processing of BSON. Type is the BSON type of the value and Value are the raw bytes that +// represent the element. +// +// This type wraps bsoncore.Value for most of it's functionality. +type RawValue struct { +	Type  bsontype.Type +	Value []byte + +	r *bsoncodec.Registry +} + +// Unmarshal deserializes BSON into the provided val. If RawValue cannot be unmarshaled into val, an +// error is returned. This method will use the registry used to create the RawValue, if the RawValue +// was created from partial BSON processing, or it will use the default registry. Users wishing to +// specify the registry to use should use UnmarshalWithRegistry. +func (rv RawValue) Unmarshal(val interface{}) error { +	reg := rv.r +	if reg == nil { +		reg = DefaultRegistry +	} +	return rv.UnmarshalWithRegistry(reg, val) +} + +// Equal compares rv and rv2 and returns true if they are equal. +func (rv RawValue) Equal(rv2 RawValue) bool { +	if rv.Type != rv2.Type { +		return false +	} + +	if !bytes.Equal(rv.Value, rv2.Value) { +		return false +	} + +	return true +} + +// UnmarshalWithRegistry performs the same unmarshalling as Unmarshal but uses the provided registry +// instead of the one attached or the default registry. +func (rv RawValue) UnmarshalWithRegistry(r *bsoncodec.Registry, val interface{}) error { +	if r == nil { +		return ErrNilRegistry +	} + +	vr := bsonrw.NewBSONValueReader(rv.Type, rv.Value) +	rval := reflect.ValueOf(val) +	if rval.Kind() != reflect.Ptr { +		return fmt.Errorf("argument to Unmarshal* must be a pointer to a type, but got %v", rval) +	} +	rval = rval.Elem() +	dec, err := r.LookupDecoder(rval.Type()) +	if err != nil { +		return err +	} +	return dec.DecodeValue(bsoncodec.DecodeContext{Registry: r}, vr, rval) +} + +// UnmarshalWithContext performs the same unmarshalling as Unmarshal but uses the provided DecodeContext +// instead of the one attached or the default registry. +func (rv RawValue) UnmarshalWithContext(dc *bsoncodec.DecodeContext, val interface{}) error { +	if dc == nil { +		return ErrNilContext +	} + +	vr := bsonrw.NewBSONValueReader(rv.Type, rv.Value) +	rval := reflect.ValueOf(val) +	if rval.Kind() != reflect.Ptr { +		return fmt.Errorf("argument to Unmarshal* must be a pointer to a type, but got %v", rval) +	} +	rval = rval.Elem() +	dec, err := dc.LookupDecoder(rval.Type()) +	if err != nil { +		return err +	} +	return dec.DecodeValue(*dc, vr, rval) +} + +func convertFromCoreValue(v bsoncore.Value) RawValue { return RawValue{Type: v.Type, Value: v.Data} } +func convertToCoreValue(v RawValue) bsoncore.Value { +	return bsoncore.Value{Type: v.Type, Data: v.Value} +} + +// Validate ensures the value is a valid BSON value. +func (rv RawValue) Validate() error { return convertToCoreValue(rv).Validate() } + +// IsNumber returns true if the type of v is a numeric BSON type. +func (rv RawValue) IsNumber() bool { return convertToCoreValue(rv).IsNumber() } + +// String implements the fmt.String interface. This method will return values in extended JSON +// format. If the value is not valid, this returns an empty string +func (rv RawValue) String() string { return convertToCoreValue(rv).String() } + +// DebugString outputs a human readable version of Document. It will attempt to stringify the +// valid components of the document even if the entire document is not valid. +func (rv RawValue) DebugString() string { return convertToCoreValue(rv).DebugString() } + +// Double returns the float64 value for this element. +// It panics if e's BSON type is not bsontype.Double. +func (rv RawValue) Double() float64 { return convertToCoreValue(rv).Double() } + +// DoubleOK is the same as Double, but returns a boolean instead of panicking. +func (rv RawValue) DoubleOK() (float64, bool) { return convertToCoreValue(rv).DoubleOK() } + +// StringValue returns the string value for this element. +// It panics if e's BSON type is not bsontype.String. +// +// NOTE: This method is called StringValue to avoid a collision with the String method which +// implements the fmt.Stringer interface. +func (rv RawValue) StringValue() string { return convertToCoreValue(rv).StringValue() } + +// StringValueOK is the same as StringValue, but returns a boolean instead of +// panicking. +func (rv RawValue) StringValueOK() (string, bool) { return convertToCoreValue(rv).StringValueOK() } + +// Document returns the BSON document the Value represents as a Document. It panics if the +// value is a BSON type other than document. +func (rv RawValue) Document() Raw { return Raw(convertToCoreValue(rv).Document()) } + +// DocumentOK is the same as Document, except it returns a boolean +// instead of panicking. +func (rv RawValue) DocumentOK() (Raw, bool) { +	doc, ok := convertToCoreValue(rv).DocumentOK() +	return Raw(doc), ok +} + +// Array returns the BSON array the Value represents as an Array. It panics if the +// value is a BSON type other than array. +func (rv RawValue) Array() Raw { return Raw(convertToCoreValue(rv).Array()) } + +// ArrayOK is the same as Array, except it returns a boolean instead +// of panicking. +func (rv RawValue) ArrayOK() (Raw, bool) { +	doc, ok := convertToCoreValue(rv).ArrayOK() +	return Raw(doc), ok +} + +// Binary returns the BSON binary value the Value represents. It panics if the value is a BSON type +// other than binary. +func (rv RawValue) Binary() (subtype byte, data []byte) { return convertToCoreValue(rv).Binary() } + +// BinaryOK is the same as Binary, except it returns a boolean instead of +// panicking. +func (rv RawValue) BinaryOK() (subtype byte, data []byte, ok bool) { +	return convertToCoreValue(rv).BinaryOK() +} + +// ObjectID returns the BSON objectid value the Value represents. It panics if the value is a BSON +// type other than objectid. +func (rv RawValue) ObjectID() primitive.ObjectID { return convertToCoreValue(rv).ObjectID() } + +// ObjectIDOK is the same as ObjectID, except it returns a boolean instead of +// panicking. +func (rv RawValue) ObjectIDOK() (primitive.ObjectID, bool) { +	return convertToCoreValue(rv).ObjectIDOK() +} + +// Boolean returns the boolean value the Value represents. It panics if the +// value is a BSON type other than boolean. +func (rv RawValue) Boolean() bool { return convertToCoreValue(rv).Boolean() } + +// BooleanOK is the same as Boolean, except it returns a boolean instead of +// panicking. +func (rv RawValue) BooleanOK() (bool, bool) { return convertToCoreValue(rv).BooleanOK() } + +// DateTime returns the BSON datetime value the Value represents as a +// unix timestamp. It panics if the value is a BSON type other than datetime. +func (rv RawValue) DateTime() int64 { return convertToCoreValue(rv).DateTime() } + +// DateTimeOK is the same as DateTime, except it returns a boolean instead of +// panicking. +func (rv RawValue) DateTimeOK() (int64, bool) { return convertToCoreValue(rv).DateTimeOK() } + +// Time returns the BSON datetime value the Value represents. It panics if the value is a BSON +// type other than datetime. +func (rv RawValue) Time() time.Time { return convertToCoreValue(rv).Time() } + +// TimeOK is the same as Time, except it returns a boolean instead of +// panicking. +func (rv RawValue) TimeOK() (time.Time, bool) { return convertToCoreValue(rv).TimeOK() } + +// Regex returns the BSON regex value the Value represents. It panics if the value is a BSON +// type other than regex. +func (rv RawValue) Regex() (pattern, options string) { return convertToCoreValue(rv).Regex() } + +// RegexOK is the same as Regex, except it returns a boolean instead of +// panicking. +func (rv RawValue) RegexOK() (pattern, options string, ok bool) { +	return convertToCoreValue(rv).RegexOK() +} + +// DBPointer returns the BSON dbpointer value the Value represents. It panics if the value is a BSON +// type other than DBPointer. +func (rv RawValue) DBPointer() (string, primitive.ObjectID) { +	return convertToCoreValue(rv).DBPointer() +} + +// DBPointerOK is the same as DBPoitner, except that it returns a boolean +// instead of panicking. +func (rv RawValue) DBPointerOK() (string, primitive.ObjectID, bool) { +	return convertToCoreValue(rv).DBPointerOK() +} + +// JavaScript returns the BSON JavaScript code value the Value represents. It panics if the value is +// a BSON type other than JavaScript code. +func (rv RawValue) JavaScript() string { return convertToCoreValue(rv).JavaScript() } + +// JavaScriptOK is the same as Javascript, excepti that it returns a boolean +// instead of panicking. +func (rv RawValue) JavaScriptOK() (string, bool) { return convertToCoreValue(rv).JavaScriptOK() } + +// Symbol returns the BSON symbol value the Value represents. It panics if the value is a BSON +// type other than symbol. +func (rv RawValue) Symbol() string { return convertToCoreValue(rv).Symbol() } + +// SymbolOK is the same as Symbol, excepti that it returns a boolean +// instead of panicking. +func (rv RawValue) SymbolOK() (string, bool) { return convertToCoreValue(rv).SymbolOK() } + +// CodeWithScope returns the BSON JavaScript code with scope the Value represents. +// It panics if the value is a BSON type other than JavaScript code with scope. +func (rv RawValue) CodeWithScope() (string, Raw) { +	code, scope := convertToCoreValue(rv).CodeWithScope() +	return code, Raw(scope) +} + +// CodeWithScopeOK is the same as CodeWithScope, except that it returns a boolean instead of +// panicking. +func (rv RawValue) CodeWithScopeOK() (string, Raw, bool) { +	code, scope, ok := convertToCoreValue(rv).CodeWithScopeOK() +	return code, Raw(scope), ok +} + +// Int32 returns the int32 the Value represents. It panics if the value is a BSON type other than +// int32. +func (rv RawValue) Int32() int32 { return convertToCoreValue(rv).Int32() } + +// Int32OK is the same as Int32, except that it returns a boolean instead of +// 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() } + +// TimestampOK is the same as Timestamp, except that it returns a boolean +// instead of panicking. +func (rv RawValue) TimestampOK() (t, i uint32, ok bool) { return convertToCoreValue(rv).TimestampOK() } + +// Int64 returns the int64 the Value represents. It panics if the value is a BSON type other than +// int64. +func (rv RawValue) Int64() int64 { return convertToCoreValue(rv).Int64() } + +// Int64OK is the same as Int64, except that it returns a boolean instead of +// 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() } + +// Decimal128OK is the same as Decimal128, except that it returns a boolean +// instead of panicking. +func (rv RawValue) Decimal128OK() (primitive.Decimal128, bool) { +	return convertToCoreValue(rv).Decimal128OK() +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/registry.go b/vendor/go.mongodb.org/mongo-driver/bson/registry.go new file mode 100644 index 000000000..16d7573e7 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/registry.go @@ -0,0 +1,24 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import "go.mongodb.org/mongo-driver/bson/bsoncodec" + +// DefaultRegistry is the default bsoncodec.Registry. It contains the default codecs and the +// primitive codecs. +var DefaultRegistry = NewRegistryBuilder().Build() + +// NewRegistryBuilder creates a new RegistryBuilder configured with the default encoders and +// decoders from the bsoncodec.DefaultValueEncoders and bsoncodec.DefaultValueDecoders types and the +// PrimitiveCodecs type in this package. +func NewRegistryBuilder() *bsoncodec.RegistryBuilder { +	rb := bsoncodec.NewRegistryBuilder() +	bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb) +	bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb) +	primitiveCodecs.RegisterPrimitiveCodecs(rb) +	return rb +} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/types.go b/vendor/go.mongodb.org/mongo-driver/bson/types.go new file mode 100644 index 000000000..13a1c35cf --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/types.go @@ -0,0 +1,36 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +// These constants uniquely refer to each BSON type. +const ( +	TypeDouble           = bsontype.Double +	TypeString           = bsontype.String +	TypeEmbeddedDocument = bsontype.EmbeddedDocument +	TypeArray            = bsontype.Array +	TypeBinary           = bsontype.Binary +	TypeUndefined        = bsontype.Undefined +	TypeObjectID         = bsontype.ObjectID +	TypeBoolean          = bsontype.Boolean +	TypeDateTime         = bsontype.DateTime +	TypeNull             = bsontype.Null +	TypeRegex            = bsontype.Regex +	TypeDBPointer        = bsontype.DBPointer +	TypeJavaScript       = bsontype.JavaScript +	TypeSymbol           = bsontype.Symbol +	TypeCodeWithScope    = bsontype.CodeWithScope +	TypeInt32            = bsontype.Int32 +	TypeTimestamp        = bsontype.Timestamp +	TypeInt64            = bsontype.Int64 +	TypeDecimal128       = bsontype.Decimal128 +	TypeMinKey           = bsontype.MinKey +	TypeMaxKey           = bsontype.MaxKey +) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/unmarshal.go b/vendor/go.mongodb.org/mongo-driver/bson/unmarshal.go new file mode 100644 index 000000000..f936ba183 --- /dev/null +++ b/vendor/go.mongodb.org/mongo-driver/bson/unmarshal.go @@ -0,0 +1,101 @@ +// Copyright (C) MongoDB, Inc. 2017-present. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + +package bson + +import ( +	"bytes" + +	"go.mongodb.org/mongo-driver/bson/bsoncodec" +	"go.mongodb.org/mongo-driver/bson/bsonrw" +	"go.mongodb.org/mongo-driver/bson/bsontype" +) + +// Unmarshaler is an interface implemented by types that can unmarshal a BSON +// document representation of themselves. The BSON bytes can be assumed to be +// valid. UnmarshalBSON must copy the BSON bytes if it wishes to retain the data +// after returning. +type Unmarshaler interface { +	UnmarshalBSON([]byte) error +} + +// ValueUnmarshaler is an interface implemented by types that can unmarshal a +// BSON value representation of themselves. The BSON bytes and type can be +// assumed to be valid. UnmarshalBSONValue must copy the BSON value bytes if it +// wishes to retain the data after returning. +type ValueUnmarshaler interface { +	UnmarshalBSONValue(bsontype.Type, []byte) error +} + +// Unmarshal parses the BSON-encoded data and stores the result in the value +// pointed to by val. If val is nil or not a pointer, Unmarshal returns +// InvalidUnmarshalError. +func Unmarshal(data []byte, val interface{}) error { +	return UnmarshalWithRegistry(DefaultRegistry, data, val) +} + +// UnmarshalWithRegistry parses the BSON-encoded data using Registry r and +// stores the result in the value pointed to by val. If val is nil or not +// a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. +func UnmarshalWithRegistry(r *bsoncodec.Registry, data []byte, val interface{}) error { +	vr := bsonrw.NewBSONDocumentReader(data) +	return unmarshalFromReader(bsoncodec.DecodeContext{Registry: r}, vr, val) +} + +// UnmarshalWithContext parses the BSON-encoded data using DecodeContext dc and +// stores the result in the value pointed to by val. If val is nil or not +// a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. +func UnmarshalWithContext(dc bsoncodec.DecodeContext, data []byte, val interface{}) error { +	vr := bsonrw.NewBSONDocumentReader(data) +	return unmarshalFromReader(dc, vr, val) +} + +// UnmarshalExtJSON parses the extended JSON-encoded data and stores the result +// in the value pointed to by val. If val is nil or not a pointer, Unmarshal +// returns InvalidUnmarshalError. +func UnmarshalExtJSON(data []byte, canonical bool, val interface{}) error { +	return UnmarshalExtJSONWithRegistry(DefaultRegistry, data, canonical, val) +} + +// UnmarshalExtJSONWithRegistry parses the extended JSON-encoded data using +// Registry r and stores the result in the value pointed to by val. If val is +// nil or not a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. +func UnmarshalExtJSONWithRegistry(r *bsoncodec.Registry, data []byte, canonical bool, val interface{}) error { +	ejvr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), canonical) +	if err != nil { +		return err +	} + +	return unmarshalFromReader(bsoncodec.DecodeContext{Registry: r}, ejvr, val) +} + +// UnmarshalExtJSONWithContext parses the extended JSON-encoded data using +// DecodeContext dc and stores the result in the value pointed to by val. If val is +// nil or not a pointer, UnmarshalWithRegistry returns InvalidUnmarshalError. +func UnmarshalExtJSONWithContext(dc bsoncodec.DecodeContext, data []byte, canonical bool, val interface{}) error { +	ejvr, err := bsonrw.NewExtJSONValueReader(bytes.NewReader(data), canonical) +	if err != nil { +		return err +	} + +	return unmarshalFromReader(dc, ejvr, val) +} + +func unmarshalFromReader(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val interface{}) error { +	dec := decPool.Get().(*Decoder) +	defer decPool.Put(dec) + +	err := dec.Reset(vr) +	if err != nil { +		return err +	} +	err = dec.SetContext(dc) +	if err != nil { +		return err +	} + +	return dec.Decode(val) +}  | 
