seba-365 - implemented dep
Change-Id: Ia6226d50e7615935a0c8876809a687427ff88c22
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/array.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/array.go
new file mode 100644
index 0000000..8001d70
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/array.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 bsonx
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "strconv"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+ "github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+)
+
+// ErrNilArray indicates that an operation was attempted on a nil *Array.
+var ErrNilArray = errors.New("array is nil")
+
+// Arr represents an array in BSON.
+type Arr []Val
+
+// String implements the fmt.Stringer interface.
+func (a Arr) String() string {
+ var buf bytes.Buffer
+ buf.Write([]byte("bson.Array["))
+ for idx, val := range a {
+ if idx > 0 {
+ buf.Write([]byte(", "))
+ }
+ fmt.Fprintf(&buf, "%s", val)
+ }
+ buf.WriteByte(']')
+
+ return buf.String()
+}
+
+// MarshalBSONValue implements the bsoncodec.ValueMarshaler interface.
+func (a Arr) MarshalBSONValue() (bsontype.Type, []byte, error) {
+ if a == nil {
+ // TODO: Should we do this?
+ return bsontype.Null, nil, nil
+ }
+
+ idx, dst := bsoncore.ReserveLength(nil)
+ for idx, value := range a {
+ t, data, _ := value.MarshalBSONValue() // marshalBSONValue never returns an error.
+ dst = append(dst, byte(t))
+ dst = append(dst, strconv.Itoa(idx)...)
+ dst = append(dst, 0x00)
+ dst = append(dst, data...)
+ }
+ dst = append(dst, 0x00)
+ dst = bsoncore.UpdateLength(dst, idx, int32(len(dst[idx:])))
+ return bsontype.Array, dst, nil
+}
+
+// UnmarshalBSONValue implements the bsoncodec.ValueUnmarshaler interface.
+func (a *Arr) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
+ if a == nil {
+ return ErrNilArray
+ }
+ *a = (*a)[:0]
+
+ elements, err := bsoncore.Document(data).Elements()
+ if err != nil {
+ return err
+ }
+
+ for _, elem := range elements {
+ var val Val
+ rawval := elem.Value()
+ err = val.UnmarshalBSONValue(rawval.Type, rawval.Data)
+ if err != nil {
+ return err
+ }
+ *a = append(*a, val)
+ }
+ return nil
+}
+
+// Equal compares this document to another, returning true if they are equal.
+func (a Arr) Equal(a2 Arr) bool {
+ if len(a) != len(a2) {
+ return false
+ }
+ for idx := range a {
+ if !a[idx].Equal(a2[idx]) {
+ return false
+ }
+ }
+ return true
+}
+
+func (Arr) idoc() {}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/bsoncore.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/bsoncore.go
new file mode 100644
index 0000000..8d2946a
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/bsoncore.go
@@ -0,0 +1,791 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+// Package bsoncore contains functions that can be used to encode and decode BSON
+// elements and values to or from a slice of bytes. These functions are aimed at
+// allowing low level manipulation of BSON and can be used to build a higher
+// level BSON library.
+//
+// The Read* functions within this package return the values of the element and
+// a boolean indicating if the values are valid. A boolean was used instead of
+// an error because any error that would be returned would be the same: not
+// enough bytes. This library attempts to do no validation, it will only return
+// false if there are not enough bytes for an item to be read. For example, the
+// ReadDocument function checks the length, if that length is larger than the
+// number of bytes availble, it will return false, if there are enough bytes, it
+// will return those bytes and true. It is the consumers responsibility to
+// validate those bytes.
+//
+// The Append* functions within this package will append the type value to the
+// given dst slice. If the slice has enough capacity, it will not grow the
+// slice. The Append*Element functions within this package operate in the same
+// way, but additionally append the BSON type and the key before the value.
+package bsoncore
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "time"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+ "github.com/mongodb/mongo-go-driver/bson/primitive"
+)
+
+// AppendType will append t to dst and return the extended buffer.
+func AppendType(dst []byte, t bsontype.Type) []byte { return append(dst, byte(t)) }
+
+// AppendKey will append key to dst and return the extended buffer.
+func AppendKey(dst []byte, key string) []byte { return append(dst, key+string(0x00)...) }
+
+// AppendHeader will append Type t and key to dst and return the extended
+// buffer.
+func AppendHeader(dst []byte, t bsontype.Type, key string) []byte {
+ dst = AppendType(dst, t)
+ dst = append(dst, key...)
+ return append(dst, 0x00)
+ // return append(AppendType(dst, t), key+string(0x00)...)
+}
+
+// TODO(skriptble): All of the Read* functions should return src resliced to start just after what
+// was read.
+
+// ReadType will return the first byte of the provided []byte as a type. If
+// there is no availble byte, false is returned.
+func ReadType(src []byte) (bsontype.Type, []byte, bool) {
+ if len(src) < 1 {
+ return 0, src, false
+ }
+ return bsontype.Type(src[0]), src[1:], true
+}
+
+// ReadKey will read a key from src. The 0x00 byte will not be present
+// in the returned string. If there are not enough bytes available, false is
+// returned.
+func ReadKey(src []byte) (string, []byte, bool) { return readcstring(src) }
+
+// ReadKeyBytes will read a key from src as bytes. The 0x00 byte will
+// not be present in the returned string. If there are not enough bytes
+// available, false is returned.
+func ReadKeyBytes(src []byte) ([]byte, []byte, bool) { return readcstringbytes(src) }
+
+// ReadHeader will read a type byte and a key from src. If both of these
+// values cannot be read, false is returned.
+func ReadHeader(src []byte) (t bsontype.Type, key string, rem []byte, ok bool) {
+ t, rem, ok = ReadType(src)
+ if !ok {
+ return 0, "", src, false
+ }
+ key, rem, ok = ReadKey(rem)
+ if !ok {
+ return 0, "", src, false
+ }
+
+ return t, key, rem, true
+}
+
+// ReadHeaderBytes will read a type and a key from src and the remainder of the bytes
+// are returned as rem. If either the type or key cannot be red, ok will be false.
+func ReadHeaderBytes(src []byte) (header []byte, rem []byte, ok bool) {
+ if len(src) < 1 {
+ return nil, src, false
+ }
+ idx := bytes.IndexByte(src[1:], 0x00)
+ if idx == -1 {
+ return nil, src, false
+ }
+ return src[:idx], src[idx+1:], true
+}
+
+// ReadElement reads the next full element from src. It returns the element, the remaining bytes in
+// the slice, and a boolean indicating if the read was successful.
+func ReadElement(src []byte) (Element, []byte, bool) {
+ if len(src) < 1 {
+ return nil, src, false
+ }
+ t := bsontype.Type(src[0])
+ idx := bytes.IndexByte(src[1:], 0x00)
+ if idx == -1 {
+ return nil, src, false
+ }
+ length, ok := valueLength(src[idx+2:], t) // We add 2 here because we called IndexByte with src[1:]
+ if !ok {
+ return nil, src, false
+ }
+ elemLength := 1 + idx + 1 + int(length)
+ if elemLength > len(src) {
+ return nil, src, false
+ }
+ return src[:elemLength], src[elemLength:], true
+}
+
+// ReadValue reads the next value as the provided types and returns a Value, the remaining bytes,
+// and a boolean indicating if the read was successful.
+func ReadValue(src []byte, t bsontype.Type) (Value, []byte, bool) {
+ data, rem, ok := readValue(src, t)
+ if !ok {
+ return Value{}, src, false
+ }
+ return Value{Type: t, Data: data}, rem, true
+}
+
+// AppendDouble will append f to dst and return the extended buffer.
+func AppendDouble(dst []byte, f float64) []byte {
+ return appendu64(dst, math.Float64bits(f))
+}
+
+// AppendDoubleElement will append a BSON double element using key and f to dst
+// and return the extended buffer.
+func AppendDoubleElement(dst []byte, key string, f float64) []byte {
+ return AppendDouble(AppendHeader(dst, bsontype.Double, key), f)
+}
+
+// ReadDouble will read a float64 from src. If there are not enough bytes it
+// will return false.
+func ReadDouble(src []byte) (float64, []byte, bool) {
+ bits, src, ok := readu64(src)
+ if !ok {
+ return 0, src, false
+ }
+ return math.Float64frombits(bits), src, true
+}
+
+// AppendString will append s to dst and return the extended buffer.
+func AppendString(dst []byte, s string) []byte {
+ return appendstring(dst, s)
+}
+
+// AppendStringElement will append a BSON string element using key and val to dst
+// and return the extended buffer.
+func AppendStringElement(dst []byte, key, val string) []byte {
+ return AppendString(AppendHeader(dst, bsontype.String, key), val)
+}
+
+// ReadString will read a string from src. If there are not enough bytes it
+// will return false.
+func ReadString(src []byte) (string, []byte, bool) {
+ return readstring(src)
+}
+
+// AppendDocumentStart reserves a document's length and returns the index where the length begins.
+// This index can later be used to write the length of the document.
+//
+// TODO(skriptble): We really need AppendDocumentStart and AppendDocumentEnd.
+// AppendDocumentStart would handle calling ReserveLength and providing the index of the start of
+// the document. AppendDocumentEnd would handle taking that start index, adding the null byte,
+// calculating the length, and filling in the length at the start of the document.
+func AppendDocumentStart(dst []byte) (index int32, b []byte) { return ReserveLength(dst) }
+
+// AppendDocumentStartInline functions the same as AppendDocumentStart but takes a pointer to the
+// index int32 which allows this function to be used inline.
+func AppendDocumentStartInline(dst []byte, index *int32) []byte {
+ idx, doc := AppendDocumentStart(dst)
+ *index = idx
+ return doc
+}
+
+// AppendDocumentElementStart writes a document element header and then reserves the length bytes.
+func AppendDocumentElementStart(dst []byte, key string) (index int32, b []byte) {
+ return AppendDocumentStart(AppendHeader(dst, bsontype.EmbeddedDocument, key))
+}
+
+// AppendDocumentEnd writes the null byte for a document and updates the length of the document.
+// The index should be the beginning of the document's length bytes.
+func AppendDocumentEnd(dst []byte, index int32) ([]byte, error) {
+ if int(index) > len(dst)-4 {
+ return dst, fmt.Errorf("not enough bytes available after index to write length")
+ }
+ dst = append(dst, 0x00)
+ dst = UpdateLength(dst, index, int32(len(dst[index:])))
+ return dst, nil
+}
+
+// AppendDocument will append doc to dst and return the extended buffer.
+func AppendDocument(dst []byte, doc []byte) []byte { return append(dst, doc...) }
+
+// AppendDocumentElement will append a BSON embeded document element using key
+// and doc to dst and return the extended buffer.
+func AppendDocumentElement(dst []byte, key string, doc []byte) []byte {
+ return AppendDocument(AppendHeader(dst, bsontype.EmbeddedDocument, key), doc)
+}
+
+// BuildDocument will create a document with the given elements and will append it to dst.
+func BuildDocument(dst []byte, elems []byte) []byte {
+ idx, dst := ReserveLength(dst)
+ dst = append(dst, elems...)
+ dst = append(dst, 0x00)
+ dst = UpdateLength(dst, idx, int32(len(dst[idx:])))
+ return dst
+}
+
+// ReadDocument will read a document from src. If there are not enough bytes it
+// will return false.
+func ReadDocument(src []byte) (doc Document, rem []byte, ok bool) { return readLengthBytes(src) }
+
+// AppendArrayStart appends the length bytes to an array and then returns the index of the start
+// of those length bytes.
+func AppendArrayStart(dst []byte) (index int32, b []byte) { return ReserveLength(dst) }
+
+// AppendArrayElementStart appends an array element header and then the length bytes for an array,
+// returning the index where the length starts.
+func AppendArrayElementStart(dst []byte, key string) (index int32, b []byte) {
+ return AppendArrayStart(AppendHeader(dst, bsontype.Array, key))
+}
+
+// AppendArrayEnd appends the null byte to an array and calculates the length, inserting that
+// calculated length starting at index.
+func AppendArrayEnd(dst []byte, index int32) ([]byte, error) { return AppendDocumentEnd(dst, index) }
+
+// AppendArray will append arr to dst and return the extended buffer.
+func AppendArray(dst []byte, arr []byte) []byte { return append(dst, arr...) }
+
+// AppendArrayElement will append a BSON array element using key and arr to dst
+// and return the extended buffer.
+func AppendArrayElement(dst []byte, key string, arr []byte) []byte {
+ return AppendArray(AppendHeader(dst, bsontype.Array, key), arr)
+}
+
+// ReadArray will read an array from src. If there are not enough bytes it
+// will return false.
+func ReadArray(src []byte) (arr Document, rem []byte, ok bool) { return readLengthBytes(src) }
+
+// AppendBinary will append subtype and b to dst and return the extended buffer.
+func AppendBinary(dst []byte, subtype byte, b []byte) []byte {
+ if subtype == 0x02 {
+ return appendBinarySubtype2(dst, subtype, b)
+ }
+ dst = append(appendLength(dst, int32(len(b))), subtype)
+ return append(dst, b...)
+}
+
+// AppendBinaryElement will append a BSON binary element using key, subtype, and
+// b to dst and return the extended buffer.
+func AppendBinaryElement(dst []byte, key string, subtype byte, b []byte) []byte {
+ return AppendBinary(AppendHeader(dst, bsontype.Binary, key), subtype, b)
+}
+
+// ReadBinary will read a subtype and bin from src. If there are not enough bytes it
+// will return false.
+func ReadBinary(src []byte) (subtype byte, bin []byte, rem []byte, ok bool) {
+ length, rem, ok := ReadLength(src)
+ if !ok {
+ return 0x00, nil, src, false
+ }
+ if len(rem) < 1 { // subtype
+ return 0x00, nil, src, false
+ }
+ subtype, rem = rem[0], rem[1:]
+
+ if len(rem) < int(length) {
+ return 0x00, nil, src, false
+ }
+
+ if subtype == 0x02 {
+ length, rem, ok = ReadLength(rem)
+ if !ok || len(rem) < int(length) {
+ return 0x00, nil, src, false
+ }
+ }
+
+ return subtype, rem[:length], rem[length:], true
+}
+
+// AppendUndefinedElement will append a BSON undefined element using key to dst
+// and return the extended buffer.
+func AppendUndefinedElement(dst []byte, key string) []byte {
+ return AppendHeader(dst, bsontype.Undefined, key)
+}
+
+// AppendObjectID will append oid to dst and return the extended buffer.
+func AppendObjectID(dst []byte, oid primitive.ObjectID) []byte { return append(dst, oid[:]...) }
+
+// AppendObjectIDElement will append a BSON ObjectID element using key and oid to dst
+// and return the extended buffer.
+func AppendObjectIDElement(dst []byte, key string, oid primitive.ObjectID) []byte {
+ return AppendObjectID(AppendHeader(dst, bsontype.ObjectID, key), oid)
+}
+
+// ReadObjectID will read an ObjectID from src. If there are not enough bytes it
+// will return false.
+func ReadObjectID(src []byte) (primitive.ObjectID, []byte, bool) {
+ if len(src) < 12 {
+ return primitive.ObjectID{}, src, false
+ }
+ var oid primitive.ObjectID
+ copy(oid[:], src[0:12])
+ return oid, src[12:], true
+}
+
+// AppendBoolean will append b to dst and return the extended buffer.
+func AppendBoolean(dst []byte, b bool) []byte {
+ if b {
+ return append(dst, 0x01)
+ }
+ return append(dst, 0x00)
+}
+
+// AppendBooleanElement will append a BSON boolean element using key and b to dst
+// and return the extended buffer.
+func AppendBooleanElement(dst []byte, key string, b bool) []byte {
+ return AppendBoolean(AppendHeader(dst, bsontype.Boolean, key), b)
+}
+
+// ReadBoolean will read a bool from src. If there are not enough bytes it
+// will return false.
+func ReadBoolean(src []byte) (bool, []byte, bool) {
+ if len(src) < 1 {
+ return false, src, false
+ }
+
+ return src[0] == 0x01, src[1:], true
+}
+
+// AppendDateTime will append dt to dst and return the extended buffer.
+func AppendDateTime(dst []byte, dt int64) []byte { return appendi64(dst, dt) }
+
+// AppendDateTimeElement will append a BSON datetime element using key and dt to dst
+// and return the extended buffer.
+func AppendDateTimeElement(dst []byte, key string, dt int64) []byte {
+ return AppendDateTime(AppendHeader(dst, bsontype.DateTime, key), dt)
+}
+
+// ReadDateTime will read an int64 datetime from src. If there are not enough bytes it
+// will return false.
+func ReadDateTime(src []byte) (int64, []byte, bool) { return readi64(src) }
+
+// AppendTime will append time as a BSON DateTime to dst and return the extended buffer.
+func AppendTime(dst []byte, t time.Time) []byte {
+ return AppendDateTime(dst, t.Unix()*1000+int64(t.Nanosecond()/1e6))
+}
+
+// AppendTimeElement will append a BSON datetime element using key and dt to dst
+// and return the extended buffer.
+func AppendTimeElement(dst []byte, key string, t time.Time) []byte {
+ return AppendTime(AppendHeader(dst, bsontype.DateTime, key), t)
+}
+
+// ReadTime will read an time.Time datetime from src. If there are not enough bytes it
+// will return false.
+func ReadTime(src []byte) (time.Time, []byte, bool) {
+ dt, rem, ok := readi64(src)
+ return time.Unix(dt/1e3, dt%1e3*1e6), rem, ok
+}
+
+// AppendNullElement will append a BSON null element using key to dst
+// and return the extended buffer.
+func AppendNullElement(dst []byte, key string) []byte { return AppendHeader(dst, bsontype.Null, key) }
+
+// AppendRegex will append pattern and options to dst and return the extended buffer.
+func AppendRegex(dst []byte, pattern, options string) []byte {
+ return append(dst, pattern+string(0x00)+options+string(0x00)...)
+}
+
+// AppendRegexElement will append a BSON regex element using key, pattern, and
+// options to dst and return the extended buffer.
+func AppendRegexElement(dst []byte, key, pattern, options string) []byte {
+ return AppendRegex(AppendHeader(dst, bsontype.Regex, key), pattern, options)
+}
+
+// ReadRegex will read a pattern and options from src. If there are not enough bytes it
+// will return false.
+func ReadRegex(src []byte) (pattern, options string, rem []byte, ok bool) {
+ pattern, rem, ok = readcstring(src)
+ if !ok {
+ return "", "", src, false
+ }
+ options, rem, ok = readcstring(rem)
+ if !ok {
+ return "", "", src, false
+ }
+ return pattern, options, rem, true
+}
+
+// AppendDBPointer will append ns and oid to dst and return the extended buffer.
+func AppendDBPointer(dst []byte, ns string, oid primitive.ObjectID) []byte {
+ return append(appendstring(dst, ns), oid[:]...)
+}
+
+// AppendDBPointerElement will append a BSON DBPointer element using key, ns,
+// and oid to dst and return the extended buffer.
+func AppendDBPointerElement(dst []byte, key, ns string, oid primitive.ObjectID) []byte {
+ return AppendDBPointer(AppendHeader(dst, bsontype.DBPointer, key), ns, oid)
+}
+
+// ReadDBPointer will read a ns and oid from src. If there are not enough bytes it
+// will return false.
+func ReadDBPointer(src []byte) (ns string, oid primitive.ObjectID, rem []byte, ok bool) {
+ ns, rem, ok = readstring(src)
+ if !ok {
+ return "", primitive.ObjectID{}, src, false
+ }
+ oid, rem, ok = ReadObjectID(rem)
+ if !ok {
+ return "", primitive.ObjectID{}, src, false
+ }
+ return ns, oid, rem, true
+}
+
+// AppendJavaScript will append js to dst and return the extended buffer.
+func AppendJavaScript(dst []byte, js string) []byte { return appendstring(dst, js) }
+
+// AppendJavaScriptElement will append a BSON JavaScript element using key and
+// js to dst and return the extended buffer.
+func AppendJavaScriptElement(dst []byte, key, js string) []byte {
+ return AppendJavaScript(AppendHeader(dst, bsontype.JavaScript, key), js)
+}
+
+// ReadJavaScript will read a js string from src. If there are not enough bytes it
+// will return false.
+func ReadJavaScript(src []byte) (js string, rem []byte, ok bool) { return readstring(src) }
+
+// AppendSymbol will append symbol to dst and return the extended buffer.
+func AppendSymbol(dst []byte, symbol string) []byte { return appendstring(dst, symbol) }
+
+// AppendSymbolElement will append a BSON symbol element using key and symbol to dst
+// and return the extended buffer.
+func AppendSymbolElement(dst []byte, key, symbol string) []byte {
+ return AppendSymbol(AppendHeader(dst, bsontype.Symbol, key), symbol)
+}
+
+// ReadSymbol will read a symbol string from src. If there are not enough bytes it
+// will return false.
+func ReadSymbol(src []byte) (symbol string, rem []byte, ok bool) { return readstring(src) }
+
+// AppendCodeWithScope will append code and scope to dst and return the extended buffer.
+func AppendCodeWithScope(dst []byte, code string, scope []byte) []byte {
+ length := int32(4 + 4 + len(code) + 1 + len(scope)) // length of cws, length of code, code, 0x00, scope
+ dst = appendLength(dst, length)
+
+ return append(appendstring(dst, code), scope...)
+}
+
+// AppendCodeWithScopeElement will append a BSON code with scope element using
+// key, code, and scope to dst
+// and return the extended buffer.
+func AppendCodeWithScopeElement(dst []byte, key, code string, scope []byte) []byte {
+ return AppendCodeWithScope(AppendHeader(dst, bsontype.CodeWithScope, key), code, scope)
+}
+
+// ReadCodeWithScope will read code and scope from src. If there are not enough bytes it
+// will return false.
+func ReadCodeWithScope(src []byte) (code string, scope []byte, rem []byte, ok bool) {
+ length, rem, ok := ReadLength(src)
+ if !ok || len(src) < int(length) {
+ return "", nil, src, false
+ }
+
+ code, rem, ok = readstring(rem)
+ if !ok {
+ return "", nil, src, false
+ }
+
+ scope, rem, ok = ReadDocument(rem)
+ if !ok {
+ return "", nil, src, false
+ }
+ return code, scope, rem, true
+}
+
+// AppendInt32 will append i32 to dst and return the extended buffer.
+func AppendInt32(dst []byte, i32 int32) []byte { return appendi32(dst, i32) }
+
+// AppendInt32Element will append a BSON int32 element using key and i32 to dst
+// and return the extended buffer.
+func AppendInt32Element(dst []byte, key string, i32 int32) []byte {
+ return AppendInt32(AppendHeader(dst, bsontype.Int32, key), i32)
+}
+
+// ReadInt32 will read an int32 from src. If there are not enough bytes it
+// will return false.
+func ReadInt32(src []byte) (int32, []byte, bool) { return readi32(src) }
+
+// AppendTimestamp will append t and i to dst and return the extended buffer.
+func AppendTimestamp(dst []byte, t, i uint32) []byte {
+ return appendu32(appendu32(dst, i), t) // i is the lower 4 bytes, t is the higher 4 bytes
+}
+
+// AppendTimestampElement will append a BSON timestamp element using key, t, and
+// i to dst and return the extended buffer.
+func AppendTimestampElement(dst []byte, key string, t, i uint32) []byte {
+ return AppendTimestamp(AppendHeader(dst, bsontype.Timestamp, key), t, i)
+}
+
+// ReadTimestamp will read t and i from src. If there are not enough bytes it
+// will return false.
+func ReadTimestamp(src []byte) (t, i uint32, rem []byte, ok bool) {
+ i, rem, ok = readu32(src)
+ if !ok {
+ return 0, 0, src, false
+ }
+ t, rem, ok = readu32(rem)
+ if !ok {
+ return 0, 0, src, false
+ }
+ return t, i, rem, true
+}
+
+// AppendInt64 will append i64 to dst and return the extended buffer.
+func AppendInt64(dst []byte, i64 int64) []byte { return appendi64(dst, i64) }
+
+// AppendInt64Element will append a BSON int64 element using key and i64 to dst
+// and return the extended buffer.
+func AppendInt64Element(dst []byte, key string, i64 int64) []byte {
+ return AppendInt64(AppendHeader(dst, bsontype.Int64, key), i64)
+}
+
+// ReadInt64 will read an int64 from src. If there are not enough bytes it
+// will return false.
+func ReadInt64(src []byte) (int64, []byte, bool) { return readi64(src) }
+
+// AppendDecimal128 will append d128 to dst and return the extended buffer.
+func AppendDecimal128(dst []byte, d128 primitive.Decimal128) []byte {
+ high, low := d128.GetBytes()
+ return appendu64(appendu64(dst, low), high)
+}
+
+// AppendDecimal128Element will append a BSON primitive.28 element using key and
+// d128 to dst and return the extended buffer.
+func AppendDecimal128Element(dst []byte, key string, d128 primitive.Decimal128) []byte {
+ return AppendDecimal128(AppendHeader(dst, bsontype.Decimal128, key), d128)
+}
+
+// ReadDecimal128 will read a primitive.Decimal128 from src. If there are not enough bytes it
+// will return false.
+func ReadDecimal128(src []byte) (primitive.Decimal128, []byte, bool) {
+ l, rem, ok := readu64(src)
+ if !ok {
+ return primitive.Decimal128{}, src, false
+ }
+
+ h, rem, ok := readu64(rem)
+ if !ok {
+ return primitive.Decimal128{}, src, false
+ }
+
+ return primitive.NewDecimal128(h, l), rem, true
+}
+
+// AppendMaxKeyElement will append a BSON max key element using key to dst
+// and return the extended buffer.
+func AppendMaxKeyElement(dst []byte, key string) []byte {
+ return AppendHeader(dst, bsontype.MaxKey, key)
+}
+
+// AppendMinKeyElement will append a BSON min key element using key to dst
+// and return the extended buffer.
+func AppendMinKeyElement(dst []byte, key string) []byte {
+ return AppendHeader(dst, bsontype.MinKey, key)
+}
+
+// EqualValue will return true if the two values are equal.
+func EqualValue(t1, t2 bsontype.Type, v1, v2 []byte) bool {
+ if t1 != t2 {
+ return false
+ }
+ v1, _, ok := readValue(v1, t1)
+ if !ok {
+ return false
+ }
+ v2, _, ok = readValue(v2, t2)
+ if !ok {
+ return false
+ }
+ return bytes.Equal(v1, v2)
+}
+
+// valueLength will determine the length of the next value contained in src as if it
+// is type t. The returned bool will be false if there are not enough bytes in src for
+// a value of type t.
+func valueLength(src []byte, t bsontype.Type) (int32, bool) {
+ var length int32
+ ok := true
+ switch t {
+ case bsontype.Array, bsontype.EmbeddedDocument, bsontype.CodeWithScope:
+ length, _, ok = ReadLength(src)
+ case bsontype.Binary:
+ length, _, ok = ReadLength(src)
+ length += 4 + 1 // binary length + subtype byte
+ case bsontype.Boolean:
+ length = 1
+ case bsontype.DBPointer:
+ length, _, ok = ReadLength(src)
+ 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, _, ok = ReadLength(src)
+ length += 4
+ case bsontype.MaxKey, bsontype.MinKey, bsontype.Null, bsontype.Undefined:
+ length = 0
+ case bsontype.ObjectID:
+ length = 12
+ case bsontype.Regex:
+ regex := bytes.IndexByte(src, 0x00)
+ if regex < 0 {
+ ok = false
+ break
+ }
+ pattern := bytes.IndexByte(src[regex+1:], 0x00)
+ if pattern < 0 {
+ ok = false
+ break
+ }
+ length = int32(int64(regex) + 1 + int64(pattern) + 1)
+ default:
+ ok = false
+ }
+
+ return length, ok
+}
+
+func readValue(src []byte, t bsontype.Type) ([]byte, []byte, bool) {
+ length, ok := valueLength(src, t)
+ if !ok || int(length) > len(src) {
+ return nil, src, false
+ }
+
+ return src[:length], src[length:], true
+}
+
+// ReserveLength reserves the space required for length and returns the index where to write the length
+// and the []byte with reserved space.
+func ReserveLength(dst []byte) (int32, []byte) {
+ index := len(dst)
+ return int32(index), append(dst, 0x00, 0x00, 0x00, 0x00)
+}
+
+// UpdateLength updates the length at index with length and returns the []byte.
+func UpdateLength(dst []byte, index, length int32) []byte {
+ dst[index] = byte(length)
+ dst[index+1] = byte(length >> 8)
+ dst[index+2] = byte(length >> 16)
+ dst[index+3] = byte(length >> 24)
+ return dst
+}
+
+func appendLength(dst []byte, l int32) []byte { return appendi32(dst, l) }
+
+func appendi32(dst []byte, i32 int32) []byte {
+ return append(dst, byte(i32), byte(i32>>8), byte(i32>>16), byte(i32>>24))
+}
+
+// ReadLength reads an int32 length from src and returns the length and the remaining bytes. If
+// there aren't enough bytes to read a valid length, src is returned unomdified and the returned
+// bool will be false.
+func ReadLength(src []byte) (int32, []byte, bool) { return readi32(src) }
+
+func readi32(src []byte) (int32, []byte, bool) {
+ if len(src) < 4 {
+ return 0, src, false
+ }
+
+ return (int32(src[0]) | int32(src[1])<<8 | int32(src[2])<<16 | int32(src[3])<<24), src[4:], true
+}
+
+func appendi64(dst []byte, i64 int64) []byte {
+ return append(dst,
+ byte(i64), byte(i64>>8), byte(i64>>16), byte(i64>>24),
+ byte(i64>>32), byte(i64>>40), byte(i64>>48), byte(i64>>56),
+ )
+}
+
+func readi64(src []byte) (int64, []byte, bool) {
+ if len(src) < 8 {
+ return 0, src, false
+ }
+ i64 := (int64(src[0]) | int64(src[1])<<8 | int64(src[2])<<16 | int64(src[3])<<24 |
+ int64(src[4])<<32 | int64(src[5])<<40 | int64(src[6])<<48 | int64(src[7])<<56)
+ return i64, src[8:], true
+}
+
+func appendu32(dst []byte, u32 uint32) []byte {
+ return append(dst, byte(u32), byte(u32>>8), byte(u32>>16), byte(u32>>24))
+}
+
+func readu32(src []byte) (uint32, []byte, bool) {
+ if len(src) < 4 {
+ return 0, src, false
+ }
+
+ return (uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24), src[4:], true
+}
+
+func appendu64(dst []byte, u64 uint64) []byte {
+ return append(dst,
+ byte(u64), byte(u64>>8), byte(u64>>16), byte(u64>>24),
+ byte(u64>>32), byte(u64>>40), byte(u64>>48), byte(u64>>56),
+ )
+}
+
+func readu64(src []byte) (uint64, []byte, bool) {
+ if len(src) < 8 {
+ return 0, src, false
+ }
+ u64 := (uint64(src[0]) | uint64(src[1])<<8 | uint64(src[2])<<16 | uint64(src[3])<<24 |
+ uint64(src[4])<<32 | uint64(src[5])<<40 | uint64(src[6])<<48 | uint64(src[7])<<56)
+ return u64, src[8:], true
+}
+
+// keep in sync with readcstringbytes
+func readcstring(src []byte) (string, []byte, bool) {
+ idx := bytes.IndexByte(src, 0x00)
+ if idx < 0 {
+ return "", src, false
+ }
+ return string(src[:idx]), src[idx+1:], true
+}
+
+// keep in sync with readcstring
+func readcstringbytes(src []byte) ([]byte, []byte, bool) {
+ idx := bytes.IndexByte(src, 0x00)
+ if idx < 0 {
+ return nil, src, false
+ }
+ return src[:idx], src[idx+1:], true
+}
+
+func appendstring(dst []byte, s string) []byte {
+ l := int32(len(s) + 1)
+ dst = appendLength(dst, l)
+ dst = append(dst, s...)
+ return append(dst, 0x00)
+}
+
+func readstring(src []byte) (string, []byte, bool) {
+ l, rem, ok := ReadLength(src)
+ if !ok {
+ return "", src, false
+ }
+ if len(src[4:]) < int(l) {
+ return "", src, false
+ }
+
+ return string(rem[:l-1]), rem[l:], true
+}
+
+// readLengthBytes attempts to read a length and that number of bytes. This
+// function requires that the length include the four bytes for itself.
+func readLengthBytes(src []byte) ([]byte, []byte, bool) {
+ l, _, ok := ReadLength(src)
+ if !ok {
+ return nil, src, false
+ }
+ if len(src) < int(l) {
+ return nil, src, false
+ }
+ return src[:l], src[l:], true
+}
+
+func appendBinarySubtype2(dst []byte, subtype byte, b []byte) []byte {
+ dst = appendLength(dst, int32(len(b)+4)) // The bytes we'll encode need to be 4 larger for the length bytes
+ dst = append(dst, subtype)
+ dst = appendLength(dst, int32(len(b)))
+ return append(dst, b...)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/document.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/document.go
new file mode 100644
index 0000000..e655a51
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/document.go
@@ -0,0 +1,396 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package bsoncore
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "strconv"
+
+ "github.com/go-stack/stack"
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+)
+
+// DocumentValidationError is an error type returned when attempting to validate a document.
+type DocumentValidationError string
+
+func (dve DocumentValidationError) Error() string { return string(dve) }
+
+// NewDocumentLengthError creates and returns an error for when the length of a document exceeds the
+// bytes available.
+func NewDocumentLengthError(length, rem int) error {
+ return DocumentValidationError(
+ fmt.Sprintf("document length exceeds available bytes. length=%d remainingBytes=%d", length, rem),
+ )
+}
+
+// InsufficientBytesError indicates that there were not enough bytes to read the next component.
+type InsufficientBytesError struct {
+ Source []byte
+ Remaining []byte
+ Stack stack.CallStack
+}
+
+// NewInsufficientBytesError creates a new InsufficientBytesError with the given Document, remaining
+// bytes, and the current stack.
+func NewInsufficientBytesError(src, rem []byte) InsufficientBytesError {
+ return InsufficientBytesError{Source: src, Remaining: rem, Stack: stack.Trace().TrimRuntime()}
+}
+
+// Error implements the error interface.
+func (ibe InsufficientBytesError) Error() string {
+ return "too few bytes to read next component"
+}
+
+// ErrorStack returns a string representing the stack at the point where the error occurred.
+func (ibe InsufficientBytesError) ErrorStack() string {
+ s := bytes.NewBufferString("too few bytes to read next component: [")
+
+ for i, call := range ibe.Stack {
+ if i != 0 {
+ s.WriteString(", ")
+ }
+
+ // go vet doesn't like %k even though it's part of stack's API, so we move the format
+ // string so it doesn't complain. (We also can't make it a constant, or go vet still
+ // complains.)
+ callFormat := "%k.%n %v"
+
+ s.WriteString(fmt.Sprintf(callFormat, call, call, call))
+ }
+
+ s.WriteRune(']')
+
+ return s.String()
+}
+
+// Equal checks that err2 also is an ErrTooSmall.
+func (ibe InsufficientBytesError) Equal(err2 error) bool {
+ switch err2.(type) {
+ case InsufficientBytesError:
+ return true
+ default:
+ return false
+ }
+}
+
+// InvalidDepthTraversalError is returned when attempting a recursive Lookup when one component of
+// the path is neither an embedded document nor an array.
+type InvalidDepthTraversalError struct {
+ Key string
+ Type bsontype.Type
+}
+
+func (idte InvalidDepthTraversalError) Error() string {
+ return fmt.Sprintf(
+ "attempt to traverse into %s, but it's type is %s, not %s nor %s",
+ idte.Key, idte.Type, bsontype.EmbeddedDocument, bsontype.Array,
+ )
+}
+
+// ErrMissingNull is returned when a document's last byte is not null.
+const ErrMissingNull DocumentValidationError = "document end is missing null byte"
+
+// ErrNilReader indicates that an operation was attempted on a nil io.Reader.
+var ErrNilReader = errors.New("nil reader")
+
+// ErrInvalidLength indicates that a length in a binary representation of a BSON document is invalid.
+var ErrInvalidLength = errors.New("document length is invalid")
+
+// ErrEmptyKey indicates that no key was provided to a Lookup method.
+var ErrEmptyKey = errors.New("empty key provided")
+
+// ErrElementNotFound indicates that an Element matching a certain condition does not exist.
+var ErrElementNotFound = errors.New("element not found")
+
+// ErrOutOfBounds indicates that an index provided to access something was invalid.
+var ErrOutOfBounds = errors.New("out of bounds")
+
+// Document is a raw bytes representation of a BSON document.
+type Document []byte
+
+// NewDocumentFromReader reads a document from r. This function will only validate the length is
+// correct and that the document ends with a null byte.
+func NewDocumentFromReader(r io.Reader) (Document, error) {
+ if r == nil {
+ return nil, ErrNilReader
+ }
+
+ var lengthBytes [4]byte
+
+ // ReadFull guarantees that we will have read at least len(lengthBytes) if err == nil
+ _, err := io.ReadFull(r, lengthBytes[:])
+ if err != nil {
+ return nil, err
+ }
+
+ length, _, _ := readi32(lengthBytes[:]) // ignore ok since we always have enough bytes to read a length
+ if length < 0 {
+ return nil, ErrInvalidLength
+ }
+ document := make([]byte, length)
+
+ copy(document, lengthBytes[:])
+
+ _, err = io.ReadFull(r, document[4:])
+ if err != nil {
+ return nil, err
+ }
+
+ if document[length-1] != 0x00 {
+ return nil, ErrMissingNull
+ }
+
+ return document, nil
+}
+
+// Lookup searches 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 Value is
+// returned.
+func (d Document) Lookup(key ...string) Value {
+ val, _ := d.LookupErr(key...)
+ return val
+}
+
+// LookupErr is the same as Lookup, except it returns an error in addition to an empty Value.
+func (d Document) LookupErr(key ...string) (Value, error) {
+ if len(key) < 1 {
+ return Value{}, ErrEmptyKey
+ }
+ length, rem, ok := ReadLength(d)
+ if !ok {
+ return Value{}, NewInsufficientBytesError(d, rem)
+ }
+
+ length -= 4
+
+ var elem Element
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return Value{}, NewInsufficientBytesError(d, rem)
+ }
+ if elem.Key() != key[0] {
+ continue
+ }
+ if len(key) > 1 {
+ tt := bsontype.Type(elem[0])
+ switch tt {
+ case bsontype.EmbeddedDocument:
+ val, err := elem.Value().Document().LookupErr(key[1:]...)
+ if err != nil {
+ return Value{}, err
+ }
+ return val, nil
+ case bsontype.Array:
+ val, err := elem.Value().Array().LookupErr(key[1:]...)
+ if err != nil {
+ return Value{}, err
+ }
+ return val, nil
+ default:
+ return Value{}, InvalidDepthTraversalError{Key: elem.Key(), Type: tt}
+ }
+ }
+ return elem.ValueErr()
+ }
+ return Value{}, ErrElementNotFound
+}
+
+// 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 (d Document) Index(index uint) Element {
+ elem, err := d.IndexErr(index)
+ if err != nil {
+ panic(err)
+ }
+ return elem
+}
+
+// IndexErr searches for and retrieves the element at the given index.
+func (d Document) IndexErr(index uint) (Element, error) {
+ length, rem, ok := ReadLength(d)
+ if !ok {
+ return nil, NewInsufficientBytesError(d, rem)
+ }
+
+ length -= 4
+
+ var current uint
+ var elem Element
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return nil, NewInsufficientBytesError(d, rem)
+ }
+ if current != index {
+ current++
+ continue
+ }
+ return elem, nil
+ }
+ return nil, ErrOutOfBounds
+}
+
+// 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 (d Document) DebugString() string {
+ if len(d) < 5 {
+ return "<malformed>"
+ }
+ var buf bytes.Buffer
+ buf.WriteString("Document")
+ length, rem, _ := ReadLength(d) // We know we have enough bytes to read the length
+ buf.WriteByte('(')
+ buf.WriteString(strconv.Itoa(int(length)))
+ length -= 4
+ buf.WriteString("){")
+ var elem Element
+ var ok bool
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ buf.WriteString(fmt.Sprintf("<malformed (%d)>", length))
+ break
+ }
+ fmt.Fprintf(&buf, "%s ", elem.DebugString())
+ }
+ buf.WriteByte('}')
+
+ return buf.String()
+}
+
+// String outputs an ExtendedJSON version of Document. If the document is not valid, this method
+// returns an empty string.
+func (d Document) String() string {
+ if len(d) < 5 {
+ return ""
+ }
+ var buf bytes.Buffer
+ buf.WriteByte('{')
+
+ length, rem, _ := ReadLength(d) // We know we have enough bytes to read the length
+
+ length -= 4
+
+ var elem Element
+ var ok bool
+ first := true
+ for length > 1 {
+ if !first {
+ buf.WriteByte(',')
+ }
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return ""
+ }
+ fmt.Fprintf(&buf, "%s", elem.String())
+ first = false
+ }
+ buf.WriteByte('}')
+
+ return buf.String()
+}
+
+// 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 (d Document) Elements() ([]Element, error) {
+ length, rem, ok := ReadLength(d)
+ if !ok {
+ return nil, NewInsufficientBytesError(d, rem)
+ }
+
+ length -= 4
+
+ var elem Element
+ var elems []Element
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return elems, NewInsufficientBytesError(d, rem)
+ }
+ if err := elem.Validate(); err != nil {
+ return elems, err
+ }
+ elems = append(elems, elem)
+ }
+ return elems, nil
+}
+
+// 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 (d Document) Values() ([]Value, error) {
+ length, rem, ok := ReadLength(d)
+ if !ok {
+ return nil, NewInsufficientBytesError(d, rem)
+ }
+
+ length -= 4
+
+ var elem Element
+ var vals []Value
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return vals, NewInsufficientBytesError(d, rem)
+ }
+ if err := elem.Value().Validate(); err != nil {
+ return vals, err
+ }
+ vals = append(vals, elem.Value())
+ }
+ return vals, nil
+}
+
+// Validate validates the document and ensures the elements contained within are valid.
+func (d Document) Validate() error {
+ length, rem, ok := ReadLength(d)
+ if !ok {
+ return NewInsufficientBytesError(d, rem)
+ }
+ if int(length) > len(d) {
+ return d.lengtherror(int(length), len(d))
+ }
+ if d[length-1] != 0x00 {
+ return ErrMissingNull
+ }
+
+ length -= 4
+ var elem Element
+
+ for length > 1 {
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return NewInsufficientBytesError(d, rem)
+ }
+ err := elem.Validate()
+ if err != nil {
+ return err
+ }
+ }
+
+ if len(rem) < 1 || rem[0] != 0x00 {
+ return ErrMissingNull
+ }
+ return nil
+}
+
+func (Document) lengtherror(length, rem int) error {
+ return DocumentValidationError(fmt.Sprintf("document length exceeds available bytes. length=%d remainingBytes=%d", length, rem))
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/element.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/element.go
new file mode 100644
index 0000000..ccf9075
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/element.go
@@ -0,0 +1,152 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package bsoncore
+
+import (
+ "bytes"
+ "fmt"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+)
+
+// MalformedElementError represents a class of errors that RawElement methods return.
+type MalformedElementError string
+
+func (mee MalformedElementError) Error() string { return string(mee) }
+
+// ErrElementMissingKey is returned when a RawElement is missing a key.
+const ErrElementMissingKey MalformedElementError = "element is missing key"
+
+// ErrElementMissingType is returned when a RawElement is missing a type.
+const ErrElementMissingType MalformedElementError = "element is missing type"
+
+// Element is a raw bytes representation of a BSON element.
+type Element []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 (e Element) Key() string {
+ key, _ := e.KeyErr()
+ return key
+}
+
+// KeyBytes returns the key for this element as a []byte. If the element is not valid, this method
+// returns an empty string. If knowing if the element is valid is important, use KeyErr. This method
+// will not include the null byte at the end of the key in the slice of bytes.
+func (e Element) KeyBytes() []byte {
+ key, _ := e.KeyBytesErr()
+ return key
+}
+
+// KeyErr returns the key for this element, returning an error if the element is not valid.
+func (e Element) KeyErr() (string, error) {
+ key, err := e.KeyBytesErr()
+ return string(key), err
+}
+
+// KeyBytesErr returns the key for this element as a []byte, returning an error if the element is
+// not valid.
+func (e Element) KeyBytesErr() ([]byte, error) {
+ if len(e) <= 0 {
+ return nil, ErrElementMissingType
+ }
+ idx := bytes.IndexByte(e[1:], 0x00)
+ if idx == -1 {
+ return nil, ErrElementMissingKey
+ }
+ return e[1 : idx+1], nil
+}
+
+// Validate ensures the element is a valid BSON element.
+func (e Element) Validate() error {
+ if len(e) < 1 {
+ return ErrElementMissingType
+ }
+ idx := bytes.IndexByte(e[1:], 0x00)
+ if idx == -1 {
+ return ErrElementMissingKey
+ }
+ return Value{Type: bsontype.Type(e[0]), Data: e[idx+2:]}.Validate()
+}
+
+// CompareKey will compare this element's key to key. This method makes it easy to compare keys
+// without needing to allocate a string. The key may be null terminated. If a valid key cannot be
+// read this method will return false.
+func (e Element) CompareKey(key []byte) bool {
+ if len(e) < 2 {
+ return false
+ }
+ idx := bytes.IndexByte(e[1:], 0x00)
+ if idx == -1 {
+ return false
+ }
+ if index := bytes.IndexByte(key, 0x00); index > -1 {
+ key = key[:index]
+ }
+ return bytes.Equal(e[1:idx+1], key)
+}
+
+// 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 (e Element) Value() Value {
+ val, _ := e.ValueErr()
+ return val
+}
+
+// ValueErr returns the value for this element, returning an error if the element is not valid.
+func (e Element) ValueErr() (Value, error) {
+ if len(e) <= 0 {
+ return Value{}, ErrElementMissingType
+ }
+ idx := bytes.IndexByte(e[1:], 0x00)
+ if idx == -1 {
+ return Value{}, ErrElementMissingKey
+ }
+
+ val, rem, exists := ReadValue(e[idx+2:], bsontype.Type(e[0]))
+ if !exists {
+ return Value{}, NewInsufficientBytesError(e, rem)
+ }
+ return val, nil
+}
+
+// String implements the fmt.String interface. The output will be in extended JSON format.
+func (e Element) String() string {
+ if len(e) <= 0 {
+ return ""
+ }
+ t := bsontype.Type(e[0])
+ idx := bytes.IndexByte(e[1:], 0x00)
+ if idx == -1 {
+ return ""
+ }
+ key, valBytes := []byte(e[1:idx+1]), []byte(e[idx+2:])
+ val, _, valid := ReadValue(valBytes, t)
+ if !valid {
+ return ""
+ }
+ return fmt.Sprintf(`"%s": %v`, key, val)
+}
+
+// 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 (e Element) DebugString() string {
+ if len(e) <= 0 {
+ return "<malformed>"
+ }
+ t := bsontype.Type(e[0])
+ idx := bytes.IndexByte(e[1:], 0x00)
+ if idx == -1 {
+ return fmt.Sprintf(`bson.Element{[%s]<malformed>}`, t)
+ }
+ key, valBytes := []byte(e[1:idx+1]), []byte(e[idx+2:])
+ val, _, valid := ReadValue(valBytes, t)
+ if !valid {
+ return fmt.Sprintf(`bson.Element{[%s]"%s": <malformed>}`, t, key)
+ }
+ return fmt.Sprintf(`bson.Element{[%s]"%s": %v}`, t, key, val)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/tables.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/tables.go
new file mode 100644
index 0000000..9fd903f
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/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 bsoncore
+
+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/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/value.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/value.go
new file mode 100644
index 0000000..f0593d2
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore/value.go
@@ -0,0 +1,901 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package bsoncore
+
+import (
+ "bytes"
+ "encoding/base64"
+ "fmt"
+ "math"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+ "github.com/mongodb/mongo-go-driver/bson/primitive"
+)
+
+// ElementTypeError specifies that a method to obtain a BSON value an incorrect type was called on a bson.Value.
+type ElementTypeError struct {
+ Method string
+ Type bsontype.Type
+}
+
+// Error implements the error interface.
+func (ete ElementTypeError) Error() string {
+ return "Call of " + ete.Method + " on " + ete.Type.String() + " type"
+}
+
+// Value represents a BSON value with a type and raw bytes.
+type Value struct {
+ Type bsontype.Type
+ Data []byte
+}
+
+// Validate ensures the value is a valid BSON value.
+func (v Value) Validate() error {
+ _, _, valid := readValue(v.Data, v.Type)
+ if !valid {
+ return NewInsufficientBytesError(v.Data, v.Data)
+ }
+ return nil
+}
+
+// IsNumber returns true if the type of v is a numeric BSON type.
+func (v Value) IsNumber() bool {
+ switch v.Type {
+ case bsontype.Double, bsontype.Int32, bsontype.Int64, bsontype.Decimal128:
+ return true
+ default:
+ return false
+ }
+}
+
+// AsInt32 returns a BSON number as an int32. If the BSON type is not a numeric one, this method
+// will panic.
+//
+// TODO(skriptble): Add support for Decimal128.
+func (v Value) AsInt32() int32 { return 0 }
+
+// AsInt32OK functions the same as AsInt32 but returns a boolean instead of panicking. False
+// indicates an error.
+//
+// TODO(skriptble): Add support for Decimal128.
+func (v Value) AsInt32OK() (int32, bool) { return 0, false }
+
+// AsInt64 returns a BSON number as an int64. If the BSON type is not a numeric one, this method
+// will panic.
+//
+// TODO(skriptble): Add support for Decimal128.
+func (v Value) AsInt64() int64 { return 0 }
+
+// AsInt64OK functions the same as AsInt64 but returns a boolean instead of panicking. False
+// indicates an error.
+//
+// TODO(skriptble): Add support for Decimal128.
+func (v Value) AsInt64OK() (int64, bool) { return 0, false }
+
+// AsFloat64 returns a BSON number as an float64. If the BSON type is not a numeric one, this method
+// will panic.
+//
+// TODO(skriptble): Add support for Decimal128.
+func (v Value) AsFloat64() float64 { return 0 }
+
+// AsFloat64OK functions the same as AsFloat64 but returns a boolean instead of panicking. False
+// indicates an error.
+//
+// TODO(skriptble): Add support for Decimal128.
+func (v Value) AsFloat64OK() (float64, bool) { return 0, false }
+
+// Add will add this value to another. This is currently only implemented for strings and numbers.
+// If either value is a string, the other type is coerced into a string and added to the other.
+//
+// This method will alter v and will attempt to reuse the []byte of v. If the []byte is too small,
+// it will be expanded.
+func (v *Value) Add(v2 Value) error { return nil }
+
+// Equal compaes v to v2 and returns true if they are equal.
+func (v Value) Equal(v2 Value) bool {
+ if v.Type != v2.Type {
+ return false
+ }
+
+ return bytes.Equal(v.Data, v2.Data)
+}
+
+// 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 (v Value) String() string {
+ switch v.Type {
+ case bsontype.Double:
+ f64, ok := v.DoubleOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$numberDouble":"%s"}`, formatDouble(f64))
+ case bsontype.String:
+ str, ok := v.StringValueOK()
+ if !ok {
+ return ""
+ }
+ return escapeString(str)
+ case bsontype.EmbeddedDocument:
+ doc, ok := v.DocumentOK()
+ if !ok {
+ return ""
+ }
+ return doc.String()
+ case bsontype.Array:
+ arr, ok := v.ArrayOK()
+ if !ok {
+ return ""
+ }
+ return docAsArray(arr, false)
+ case bsontype.Binary:
+ subtype, data, ok := v.BinaryOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$binary":{"base64":"%s","subType":"%02x"}}`, base64.StdEncoding.EncodeToString(data), subtype)
+ case bsontype.Undefined:
+ return `{"$undefined":true}`
+ case bsontype.ObjectID:
+ oid, ok := v.ObjectIDOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$oid":%s}`, oid.Hex())
+ case bsontype.Boolean:
+ b, ok := v.BooleanOK()
+ if !ok {
+ return ""
+ }
+ return strconv.FormatBool(b)
+ case bsontype.DateTime:
+ dt, ok := v.DateTimeOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$date":{"$numberLong":"%d"}}`, dt)
+ case bsontype.Null:
+ return "null"
+ case bsontype.Regex:
+ pattern, options, ok := v.RegexOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(
+ `{"$regularExpression":{"pattern":%s,"options":"%s"}}`,
+ escapeString(pattern), sortStringAlphebeticAscending(options),
+ )
+ case bsontype.DBPointer:
+ ns, pointer, ok := v.DBPointerOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$dbPointer":{"$ref":%s,"$id":{"$oid":"%s"}}}`, escapeString(ns), pointer.Hex())
+ case bsontype.JavaScript:
+ js, ok := v.JavaScriptOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$code":%s}`, escapeString(js))
+ case bsontype.Symbol:
+ symbol, ok := v.SymbolOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$symbol":%s}`, escapeString(symbol))
+ case bsontype.CodeWithScope:
+ code, scope, ok := v.CodeWithScopeOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$code":%s,"$scope":%s}`, code, scope)
+ case bsontype.Int32:
+ i32, ok := v.Int32OK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$numberInt":"%d"}`, i32)
+ case bsontype.Timestamp:
+ t, i, ok := v.TimestampOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$timestamp":{"t":"%s","i":"%s"}}`, strconv.FormatUint(uint64(t), 10), strconv.FormatUint(uint64(i), 10))
+ case bsontype.Int64:
+ i64, ok := v.Int64OK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$numberLong":"%d"}`, i64)
+ case bsontype.Decimal128:
+ d128, ok := v.Decimal128OK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$numberDecimal":"%s"}`, d128.String())
+ case bsontype.MinKey:
+ return `{"$minKey":1}`
+ case bsontype.MaxKey:
+ return `{"$maxKey":1}`
+ default:
+ return ""
+ }
+}
+
+// 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 (v Value) DebugString() string {
+ switch v.Type {
+ case bsontype.String:
+ str, ok := v.StringValueOK()
+ if !ok {
+ return "<malformed>"
+ }
+ return escapeString(str)
+ case bsontype.EmbeddedDocument:
+ doc, ok := v.DocumentOK()
+ if !ok {
+ return "<malformed>"
+ }
+ return doc.DebugString()
+ case bsontype.Array:
+ arr, ok := v.ArrayOK()
+ if !ok {
+ return "<malformed>"
+ }
+ return docAsArray(arr, true)
+ case bsontype.CodeWithScope:
+ code, scope, ok := v.CodeWithScopeOK()
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf(`{"$code":%s,"$scope":%s}`, code, scope.DebugString())
+ default:
+ str := v.String()
+ if str == "" {
+ return "<malformed>"
+ }
+ return str
+ }
+}
+
+// Double returns the float64 value for this element.
+// It panics if e's BSON type is not bsontype.Double.
+func (v Value) Double() float64 {
+ if v.Type != bsontype.Double {
+ panic(ElementTypeError{"bsoncore.Value.Double", v.Type})
+ }
+ f64, _, ok := ReadDouble(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return f64
+}
+
+// DoubleOK is the same as Double, but returns a boolean instead of panicking.
+func (v Value) DoubleOK() (float64, bool) {
+ if v.Type != bsontype.Double {
+ return 0, false
+ }
+ f64, _, ok := ReadDouble(v.Data)
+ if !ok {
+ return 0, false
+ }
+ return f64, true
+}
+
+// StringValue returns the string balue 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 (v Value) StringValue() string {
+ if v.Type != bsontype.String {
+ panic(ElementTypeError{"bsoncore.Value.StringValue", v.Type})
+ }
+ str, _, ok := ReadString(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return str
+}
+
+// StringValueOK is the same as StringValue, but returns a boolean instead of
+// panicking.
+func (v Value) StringValueOK() (string, bool) {
+ if v.Type != bsontype.String {
+ return "", false
+ }
+ str, _, ok := ReadString(v.Data)
+ if !ok {
+ return "", false
+ }
+ return str, true
+}
+
+// Document returns the BSON document the Value represents as a Document. It panics if the
+// value is a BSON type other than document.
+func (v Value) Document() Document {
+ if v.Type != bsontype.EmbeddedDocument {
+ panic(ElementTypeError{"bsoncore.Value.Document", v.Type})
+ }
+ doc, _, ok := ReadDocument(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return doc
+}
+
+// DocumentOK is the same as Document, except it returns a boolean
+// instead of panicking.
+func (v Value) DocumentOK() (Document, bool) {
+ if v.Type != bsontype.EmbeddedDocument {
+ return nil, false
+ }
+ doc, _, ok := ReadDocument(v.Data)
+ if !ok {
+ return nil, false
+ }
+ return doc, true
+}
+
+// Array returns the BSON array the Value represents as an Array. It panics if the
+// value is a BSON type other than array.
+func (v Value) Array() Document {
+ if v.Type != bsontype.Array {
+ panic(ElementTypeError{"bsoncore.Value.Array", v.Type})
+ }
+ arr, _, ok := ReadArray(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return arr
+}
+
+// ArrayOK is the same as Array, except it returns a boolean instead
+// of panicking.
+func (v Value) ArrayOK() (Document, bool) {
+ if v.Type != bsontype.Array {
+ return nil, false
+ }
+ arr, _, ok := ReadArray(v.Data)
+ if !ok {
+ return nil, false
+ }
+ return arr, true
+}
+
+// Binary returns the BSON binary value the Value represents. It panics if the value is a BSON type
+// other than binary.
+func (v Value) Binary() (subtype byte, data []byte) {
+ if v.Type != bsontype.Binary {
+ panic(ElementTypeError{"bsoncore.Value.Binary", v.Type})
+ }
+ subtype, data, _, ok := ReadBinary(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return subtype, data
+}
+
+// BinaryOK is the same as Binary, except it returns a boolean instead of
+// panicking.
+func (v Value) BinaryOK() (subtype byte, data []byte, ok bool) {
+ if v.Type != bsontype.Binary {
+ return 0x00, nil, false
+ }
+ subtype, data, _, ok = ReadBinary(v.Data)
+ if !ok {
+ return 0x00, nil, false
+ }
+ return subtype, data, true
+}
+
+// ObjectID returns the BSON objectid value the Value represents. It panics if the value is a BSON
+// type other than objectid.
+func (v Value) ObjectID() primitive.ObjectID {
+ if v.Type != bsontype.ObjectID {
+ panic(ElementTypeError{"bsoncore.Value.ObjectID", v.Type})
+ }
+ oid, _, ok := ReadObjectID(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return oid
+}
+
+// ObjectIDOK is the same as ObjectID, except it returns a boolean instead of
+// panicking.
+func (v Value) ObjectIDOK() (primitive.ObjectID, bool) {
+ if v.Type != bsontype.ObjectID {
+ return primitive.ObjectID{}, false
+ }
+ oid, _, ok := ReadObjectID(v.Data)
+ if !ok {
+ return primitive.ObjectID{}, false
+ }
+ return oid, true
+}
+
+// Boolean returns the boolean value the Value represents. It panics if the
+// value is a BSON type other than boolean.
+func (v Value) Boolean() bool {
+ if v.Type != bsontype.Boolean {
+ panic(ElementTypeError{"bsoncore.Value.Boolean", v.Type})
+ }
+ b, _, ok := ReadBoolean(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return b
+}
+
+// BooleanOK is the same as Boolean, except it returns a boolean instead of
+// panicking.
+func (v Value) BooleanOK() (bool, bool) {
+ if v.Type != bsontype.Boolean {
+ return false, false
+ }
+ b, _, ok := ReadBoolean(v.Data)
+ if !ok {
+ return false, false
+ }
+ return b, true
+}
+
+// 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 (v Value) DateTime() int64 {
+ if v.Type != bsontype.DateTime {
+ panic(ElementTypeError{"bsoncore.Value.DateTime", v.Type})
+ }
+ dt, _, ok := ReadDateTime(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return dt
+}
+
+// DateTimeOK is the same as DateTime, except it returns a boolean instead of
+// panicking.
+func (v Value) DateTimeOK() (int64, bool) {
+ if v.Type != bsontype.DateTime {
+ return 0, false
+ }
+ dt, _, ok := ReadDateTime(v.Data)
+ if !ok {
+ return 0, false
+ }
+ return dt, true
+}
+
+// Time returns the BSON datetime value the Value represents. It panics if the value is a BSON
+// type other than datetime.
+func (v Value) Time() time.Time {
+ if v.Type != bsontype.DateTime {
+ panic(ElementTypeError{"bsoncore.Value.Time", v.Type})
+ }
+ dt, _, ok := ReadDateTime(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return time.Unix(int64(dt)/1000, int64(dt)%1000*1000000)
+}
+
+// TimeOK is the same as Time, except it returns a boolean instead of
+// panicking.
+func (v Value) TimeOK() (time.Time, bool) {
+ if v.Type != bsontype.DateTime {
+ return time.Time{}, false
+ }
+ dt, _, ok := ReadDateTime(v.Data)
+ if !ok {
+ return time.Time{}, false
+ }
+ return time.Unix(int64(dt)/1000, int64(dt)%1000*1000000), true
+}
+
+// Regex returns the BSON regex value the Value represents. It panics if the value is a BSON
+// type other than regex.
+func (v Value) Regex() (pattern, options string) {
+ if v.Type != bsontype.Regex {
+ panic(ElementTypeError{"bsoncore.Value.Regex", v.Type})
+ }
+ pattern, options, _, ok := ReadRegex(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return pattern, options
+}
+
+// RegexOK is the same as Regex, except it returns a boolean instead of
+// panicking.
+func (v Value) RegexOK() (pattern, options string, ok bool) {
+ if v.Type != bsontype.Regex {
+ return "", "", false
+ }
+ pattern, options, _, ok = ReadRegex(v.Data)
+ if !ok {
+ return "", "", false
+ }
+ return pattern, options, true
+}
+
+// DBPointer returns the BSON dbpointer value the Value represents. It panics if the value is a BSON
+// type other than DBPointer.
+func (v Value) DBPointer() (string, primitive.ObjectID) {
+ if v.Type != bsontype.DBPointer {
+ panic(ElementTypeError{"bsoncore.Value.DBPointer", v.Type})
+ }
+ ns, pointer, _, ok := ReadDBPointer(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return ns, pointer
+}
+
+// DBPointerOK is the same as DBPoitner, except that it returns a boolean
+// instead of panicking.
+func (v Value) DBPointerOK() (string, primitive.ObjectID, bool) {
+ if v.Type != bsontype.DBPointer {
+ return "", primitive.ObjectID{}, false
+ }
+ ns, pointer, _, ok := ReadDBPointer(v.Data)
+ if !ok {
+ return "", primitive.ObjectID{}, false
+ }
+ return ns, pointer, true
+}
+
+// JavaScript returns the BSON JavaScript code value the Value represents. It panics if the value is
+// a BSON type other than JavaScript code.
+func (v Value) JavaScript() string {
+ if v.Type != bsontype.JavaScript {
+ panic(ElementTypeError{"bsoncore.Value.JavaScript", v.Type})
+ }
+ js, _, ok := ReadJavaScript(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return js
+}
+
+// JavaScriptOK is the same as Javascript, excepti that it returns a boolean
+// instead of panicking.
+func (v Value) JavaScriptOK() (string, bool) {
+ if v.Type != bsontype.JavaScript {
+ return "", false
+ }
+ js, _, ok := ReadJavaScript(v.Data)
+ if !ok {
+ return "", false
+ }
+ return js, true
+}
+
+// Symbol returns the BSON symbol value the Value represents. It panics if the value is a BSON
+// type other than symbol.
+func (v Value) Symbol() string {
+ if v.Type != bsontype.Symbol {
+ panic(ElementTypeError{"bsoncore.Value.Symbol", v.Type})
+ }
+ symbol, _, ok := ReadSymbol(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return symbol
+}
+
+// SymbolOK is the same as Symbol, excepti that it returns a boolean
+// instead of panicking.
+func (v Value) SymbolOK() (string, bool) {
+ if v.Type != bsontype.Symbol {
+ return "", false
+ }
+ symbol, _, ok := ReadSymbol(v.Data)
+ if !ok {
+ return "", false
+ }
+ return symbol, true
+}
+
+// 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 (v Value) CodeWithScope() (string, Document) {
+ if v.Type != bsontype.CodeWithScope {
+ panic(ElementTypeError{"bsoncore.Value.CodeWithScope", v.Type})
+ }
+ code, scope, _, ok := ReadCodeWithScope(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return code, scope
+}
+
+// CodeWithScopeOK is the same as CodeWithScope, except that it returns a boolean instead of
+// panicking.
+func (v Value) CodeWithScopeOK() (string, Document, bool) {
+ if v.Type != bsontype.CodeWithScope {
+ return "", nil, false
+ }
+ code, scope, _, ok := ReadCodeWithScope(v.Data)
+ if !ok {
+ return "", nil, false
+ }
+ return code, scope, true
+}
+
+// Int32 returns the int32 the Value represents. It panics if the value is a BSON type other than
+// int32.
+func (v Value) Int32() int32 {
+ if v.Type != bsontype.Int32 {
+ panic(ElementTypeError{"bsoncore.Value.Int32", v.Type})
+ }
+ i32, _, ok := ReadInt32(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return i32
+}
+
+// Int32OK is the same as Int32, except that it returns a boolean instead of
+// panicking.
+func (v Value) Int32OK() (int32, bool) {
+ if v.Type != bsontype.Int32 {
+ return 0, false
+ }
+ i32, _, ok := ReadInt32(v.Data)
+ if !ok {
+ return 0, false
+ }
+ return i32, true
+}
+
+// Timestamp returns the BSON timestamp value the Value represents. It panics if the value is a
+// BSON type other than timestamp.
+func (v Value) Timestamp() (t, i uint32) {
+ if v.Type != bsontype.Timestamp {
+ panic(ElementTypeError{"bsoncore.Value.Timestamp", v.Type})
+ }
+ t, i, _, ok := ReadTimestamp(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return t, i
+}
+
+// TimestampOK is the same as Timestamp, except that it returns a boolean
+// instead of panicking.
+func (v Value) TimestampOK() (t, i uint32, ok bool) {
+ if v.Type != bsontype.Timestamp {
+ return 0, 0, false
+ }
+ t, i, _, ok = ReadTimestamp(v.Data)
+ if !ok {
+ return 0, 0, false
+ }
+ return t, i, true
+}
+
+// Int64 returns the int64 the Value represents. It panics if the value is a BSON type other than
+// int64.
+func (v Value) Int64() int64 {
+ if v.Type != bsontype.Int64 {
+ panic(ElementTypeError{"bsoncore.Value.Int64", v.Type})
+ }
+ i64, _, ok := ReadInt64(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return i64
+}
+
+// Int64OK is the same as Int64, except that it returns a boolean instead of
+// panicking.
+func (v Value) Int64OK() (int64, bool) {
+ if v.Type != bsontype.Int64 {
+ return 0, false
+ }
+ i64, _, ok := ReadInt64(v.Data)
+ if !ok {
+ return 0, false
+ }
+ return i64, true
+}
+
+// Decimal128 returns the decimal the Value represents. It panics if the value is a BSON type other than
+// decimal.
+func (v Value) Decimal128() primitive.Decimal128 {
+ if v.Type != bsontype.Decimal128 {
+ panic(ElementTypeError{"bsoncore.Value.Decimal128", v.Type})
+ }
+ d128, _, ok := ReadDecimal128(v.Data)
+ if !ok {
+ panic(NewInsufficientBytesError(v.Data, v.Data))
+ }
+ return d128
+}
+
+// Decimal128OK is the same as Decimal128, except that it returns a boolean
+// instead of panicking.
+func (v Value) Decimal128OK() (primitive.Decimal128, bool) {
+ if v.Type != bsontype.Decimal128 {
+ return primitive.Decimal128{}, false
+ }
+ d128, _, ok := ReadDecimal128(v.Data)
+ if !ok {
+ return primitive.Decimal128{}, false
+ }
+ return d128, true
+}
+
+var hexChars = "0123456789abcdef"
+
+func escapeString(s string) string {
+ escapeHTML := true
+ var buf bytes.Buffer
+ 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('"')
+ return buf.String()
+}
+
+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, '.') {
+ s += ".0"
+ }
+ }
+
+ return s
+}
+
+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))
+}
+
+func docAsArray(d Document, debug bool) string {
+ if len(d) < 5 {
+ return ""
+ }
+ var buf bytes.Buffer
+ buf.WriteByte('[')
+
+ length, rem, _ := ReadLength(d) // We know we have enough bytes to read the length
+
+ length -= 4
+
+ var elem Element
+ var ok bool
+ first := true
+ for length > 1 {
+ if !first {
+ buf.WriteByte(',')
+ }
+ elem, rem, ok = ReadElement(rem)
+ length -= int32(len(elem))
+ if !ok {
+ return ""
+ }
+ if debug {
+ fmt.Fprintf(&buf, "%s ", elem.Value().DebugString())
+ } else {
+ fmt.Fprintf(&buf, "%s", elem.Value())
+ }
+ first = false
+ }
+ buf.WriteByte(']')
+
+ return buf.String()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/constructor.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/constructor.go
new file mode 100644
index 0000000..28374ba
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/constructor.go
@@ -0,0 +1,166 @@
+// 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 bsonx
+
+import (
+ "encoding/binary"
+ "math"
+ "time"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+ "github.com/mongodb/mongo-go-driver/bson/primitive"
+)
+
+// IDoc is the interface implemented by Doc and MDoc. It allows either of these types to be provided
+// to the Document function to create a Value.
+type IDoc interface {
+ idoc()
+}
+
+// Double constructs a BSON double Value.
+func Double(f64 float64) Val {
+ v := Val{t: bsontype.Double}
+ binary.LittleEndian.PutUint64(v.bootstrap[0:8], math.Float64bits(f64))
+ return v
+}
+
+// String constructs a BSON string Value.
+func String(str string) Val { return Val{t: bsontype.String}.writestring(str) }
+
+// Document constructs a Value from the given IDoc. If nil is provided, a BSON Null value will be
+// returned.
+func Document(doc IDoc) Val {
+ var v Val
+ switch tt := doc.(type) {
+ case Doc:
+ if tt == nil {
+ v.t = bsontype.Null
+ break
+ }
+ v.t = bsontype.EmbeddedDocument
+ v.primitive = tt
+ case MDoc:
+ if tt == nil {
+ v.t = bsontype.Null
+ break
+ }
+ v.t = bsontype.EmbeddedDocument
+ v.primitive = tt
+ default:
+ v.t = bsontype.Null
+ }
+ return v
+}
+
+// Array constructs a Value from arr. If arr is nil, a BSON Null value is returned.
+func Array(arr Arr) Val {
+ if arr == nil {
+ return Val{t: bsontype.Null}
+ }
+ return Val{t: bsontype.Array, primitive: arr}
+}
+
+// Binary constructs a BSON binary Value.
+func Binary(subtype byte, data []byte) Val {
+ return Val{t: bsontype.Binary, primitive: primitive.Binary{Subtype: subtype, Data: data}}
+}
+
+// Undefined constructs a BSON binary Value.
+func Undefined() Val { return Val{t: bsontype.Undefined} }
+
+// ObjectID constructs a BSON objectid Value.
+func ObjectID(oid primitive.ObjectID) Val {
+ v := Val{t: bsontype.ObjectID}
+ copy(v.bootstrap[0:12], oid[:])
+ return v
+}
+
+// Boolean constructs a BSON boolean Value.
+func Boolean(b bool) Val {
+ v := Val{t: bsontype.Boolean}
+ if b {
+ v.bootstrap[0] = 0x01
+ }
+ return v
+}
+
+// DateTime constructs a BSON datetime Value.
+func DateTime(dt int64) Val { return Val{t: bsontype.DateTime}.writei64(dt) }
+
+// Time constructs a BSON datetime Value.
+func Time(t time.Time) Val {
+ return Val{t: bsontype.DateTime}.writei64(t.Unix()*1e3 + int64(t.Nanosecond()/1e6))
+}
+
+// Null constructs a BSON binary Value.
+func Null() Val { return Val{t: bsontype.Null} }
+
+// Regex constructs a BSON regex Value.
+func Regex(pattern, options string) Val {
+ regex := primitive.Regex{Pattern: pattern, Options: options}
+ return Val{t: bsontype.Regex, primitive: regex}
+}
+
+// DBPointer constructs a BSON dbpointer Value.
+func DBPointer(ns string, ptr primitive.ObjectID) Val {
+ dbptr := primitive.DBPointer{DB: ns, Pointer: ptr}
+ return Val{t: bsontype.DBPointer, primitive: dbptr}
+}
+
+// JavaScript constructs a BSON javascript Value.
+func JavaScript(js string) Val {
+ return Val{t: bsontype.JavaScript}.writestring(js)
+}
+
+// Symbol constructs a BSON symbol Value.
+func Symbol(symbol string) Val {
+ return Val{t: bsontype.Symbol}.writestring(symbol)
+}
+
+// CodeWithScope constructs a BSON code with scope Value.
+func CodeWithScope(code string, scope IDoc) Val {
+ cws := primitive.CodeWithScope{Code: primitive.JavaScript(code), Scope: scope}
+ return Val{t: bsontype.CodeWithScope, primitive: cws}
+}
+
+// Int32 constructs a BSON int32 Value.
+func Int32(i32 int32) Val {
+ v := Val{t: bsontype.Int32}
+ v.bootstrap[0] = byte(i32)
+ v.bootstrap[1] = byte(i32 >> 8)
+ v.bootstrap[2] = byte(i32 >> 16)
+ v.bootstrap[3] = byte(i32 >> 24)
+ return v
+}
+
+// Timestamp constructs a BSON timestamp Value.
+func Timestamp(t, i uint32) Val {
+ v := Val{t: bsontype.Timestamp}
+ v.bootstrap[0] = byte(i)
+ v.bootstrap[1] = byte(i >> 8)
+ v.bootstrap[2] = byte(i >> 16)
+ v.bootstrap[3] = byte(i >> 24)
+ v.bootstrap[4] = byte(t)
+ v.bootstrap[5] = byte(t >> 8)
+ v.bootstrap[6] = byte(t >> 16)
+ v.bootstrap[7] = byte(t >> 24)
+ return v
+}
+
+// Int64 constructs a BSON int64 Value.
+func Int64(i64 int64) Val { return Val{t: bsontype.Int64}.writei64(i64) }
+
+// Decimal128 constructs a BSON decimal128 Value.
+func Decimal128(d128 primitive.Decimal128) Val {
+ return Val{t: bsontype.Decimal128, primitive: d128}
+}
+
+// MinKey constructs a BSON minkey Value.
+func MinKey() Val { return Val{t: bsontype.MinKey} }
+
+// MaxKey constructs a BSON maxkey Value.
+func MaxKey() Val { return Val{t: bsontype.MaxKey} }
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/document.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/document.go
new file mode 100644
index 0000000..f2209a0
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/document.go
@@ -0,0 +1,305 @@
+// 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 bsonx
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+ "github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+)
+
+// ErrNilDocument indicates that an operation was attempted on a nil *bson.Document.
+var ErrNilDocument = errors.New("document is nil")
+
+// KeyNotFound is an error type returned from the Lookup methods on Document. This type contains
+// information about which key was not found and if it was actually not found or if a component of
+// the key except the last was not a document nor array.
+type KeyNotFound struct {
+ Key []string // The keys that were searched for.
+ Depth uint // Which key either was not found or was an incorrect type.
+ Type bsontype.Type // The type of the key that was found but was an incorrect type.
+}
+
+func (knf KeyNotFound) Error() string {
+ depth := knf.Depth
+ if depth >= uint(len(knf.Key)) {
+ depth = uint(len(knf.Key)) - 1
+ }
+
+ if len(knf.Key) == 0 {
+ return "no keys were provided for lookup"
+ }
+
+ if knf.Type != bsontype.Type(0) {
+ return fmt.Sprintf(`key "%s" was found but was not valid to traverse BSON type %s`, knf.Key[depth], knf.Type)
+ }
+
+ return fmt.Sprintf(`key "%s" was not found`, knf.Key[depth])
+}
+
+// Doc is a type safe, concise BSON document representation.
+type Doc []Elem
+
+// ReadDoc will create a Document using the provided slice of bytes. If the
+// slice of bytes is not a valid BSON document, this method will return an error.
+func ReadDoc(b []byte) (Doc, error) {
+ doc := make(Doc, 0)
+ err := doc.UnmarshalBSON(b)
+ if err != nil {
+ return nil, err
+ }
+ return doc, nil
+}
+
+// Copy makes a shallow copy of this document.
+func (d Doc) Copy() Doc {
+ d2 := make(Doc, len(d))
+ copy(d2, d)
+ return d2
+}
+
+// Append adds an element to the end of the document, creating it from the key and value provided.
+func (d Doc) Append(key string, val Val) Doc {
+ return append(d, Elem{Key: key, Value: val})
+}
+
+// Prepend adds an element to the beginning of the document, creating it from the key and value provided.
+func (d Doc) Prepend(key string, val Val) Doc {
+ // TODO: should we just modify d itself instead of doing an alloc here?
+ return append(Doc{{Key: key, Value: val}}, d...)
+}
+
+// Set replaces an element of a document. If an element with a matching key is
+// found, the element will be replaced with the one provided. If the document
+// does not have an element with that key, the element is appended to the
+// document instead.
+func (d Doc) Set(key string, val Val) Doc {
+ idx := d.IndexOf(key)
+ if idx == -1 {
+ return append(d, Elem{Key: key, Value: val})
+ }
+ d[idx] = Elem{Key: key, Value: val}
+ return d
+}
+
+// IndexOf returns the index of the first element with a key of key, or -1 if no element with a key
+// was found.
+func (d Doc) IndexOf(key string) int {
+ for i, e := range d {
+ if e.Key == key {
+ return i
+ }
+ }
+ return -1
+}
+
+// Delete removes the element with key if it exists and returns the updated Doc.
+func (d Doc) Delete(key string) Doc {
+ idx := d.IndexOf(key)
+ if idx == -1 {
+ return d
+ }
+ return append(d[:idx], d[idx+1:]...)
+}
+
+// Lookup searches the document and potentially subdocuments or arrays for the
+// provided key. Each key provided to this method represents a layer of depth.
+//
+// This method will return an empty Value if they key does not exist. To know if they key actually
+// exists, use LookupErr.
+func (d Doc) Lookup(key ...string) Val {
+ val, _ := d.LookupErr(key...)
+ return val
+}
+
+// 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 (d Doc) LookupErr(key ...string) (Val, error) {
+ elem, err := d.LookupElementErr(key...)
+ return elem.Value, err
+}
+
+// LookupElement searches the document and potentially subdocuments or arrays for the
+// provided key. Each key provided to this method represents a layer of depth.
+//
+// This method will return an empty Element if they key does not exist. To know if they key actually
+// exists, use LookupElementErr.
+func (d Doc) LookupElement(key ...string) Elem {
+ elem, _ := d.LookupElementErr(key...)
+ return elem
+}
+
+// LookupElementErr searches the document and potentially subdocuments for the
+// provided key. Each key provided to this method represents a layer of depth.
+func (d Doc) LookupElementErr(key ...string) (Elem, error) {
+ // KeyNotFound operates by being created where the error happens and then the depth is
+ // incremented by 1 as each function unwinds. Whenever this function returns, it also assigns
+ // the Key slice to the key slice it has. This ensures that the proper depth is identified and
+ // the proper keys.
+ if len(key) == 0 {
+ return Elem{}, KeyNotFound{Key: key}
+ }
+
+ var elem Elem
+ var err error
+ idx := d.IndexOf(key[0])
+ if idx == -1 {
+ return Elem{}, KeyNotFound{Key: key}
+ }
+
+ elem = d[idx]
+ if len(key) == 1 {
+ return elem, nil
+ }
+
+ switch elem.Value.Type() {
+ case bsontype.EmbeddedDocument:
+ switch tt := elem.Value.primitive.(type) {
+ case Doc:
+ elem, err = tt.LookupElementErr(key[1:]...)
+ case MDoc:
+ elem, err = tt.LookupElementErr(key[1:]...)
+ }
+ default:
+ return Elem{}, KeyNotFound{Type: elem.Value.Type()}
+ }
+ switch tt := err.(type) {
+ case KeyNotFound:
+ tt.Depth++
+ tt.Key = key
+ return Elem{}, tt
+ case nil:
+ return elem, nil
+ default:
+ return Elem{}, err // We can't actually hit this.
+ }
+}
+
+// MarshalBSONValue implements the bsoncodec.ValueMarshaler interface.
+//
+// This method will never return an error.
+func (d Doc) MarshalBSONValue() (bsontype.Type, []byte, error) {
+ if d == nil {
+ // TODO: Should we do this?
+ return bsontype.Null, nil, nil
+ }
+ data, _ := d.MarshalBSON()
+ return bsontype.EmbeddedDocument, data, nil
+}
+
+// MarshalBSON implements the Marshaler interface.
+//
+// This method will never return an error.
+func (d Doc) MarshalBSON() ([]byte, error) { return d.AppendMarshalBSON(nil) }
+
+// AppendMarshalBSON marshals Doc to BSON bytes, appending to dst.
+//
+// This method will never return an error.
+func (d Doc) AppendMarshalBSON(dst []byte) ([]byte, error) {
+ idx, dst := bsoncore.ReserveLength(dst)
+ for _, elem := range d {
+ t, data, _ := elem.Value.MarshalBSONValue() // Value.MarshalBSONValue never returns an error.
+ dst = append(dst, byte(t))
+ dst = append(dst, elem.Key...)
+ dst = append(dst, 0x00)
+ dst = append(dst, data...)
+ }
+ dst = append(dst, 0x00)
+ dst = bsoncore.UpdateLength(dst, idx, int32(len(dst[idx:])))
+ return dst, nil
+}
+
+// UnmarshalBSON implements the Unmarshaler interface.
+func (d *Doc) UnmarshalBSON(b []byte) error {
+ if d == nil {
+ return ErrNilDocument
+ }
+
+ if err := bsoncore.Document(b).Validate(); err != nil {
+ return err
+ }
+
+ elems, err := bsoncore.Document(b).Elements()
+ if err != nil {
+ return err
+ }
+ var val Val
+ for _, elem := range elems {
+ rawv := elem.Value()
+ err = val.UnmarshalBSONValue(rawv.Type, rawv.Data)
+ if err != nil {
+ return err
+ }
+ *d = d.Append(elem.Key(), val)
+ }
+ return nil
+}
+
+// UnmarshalBSONValue implements the bson.ValueUnmarshaler interface.
+func (d *Doc) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
+ if t != bsontype.EmbeddedDocument {
+ return fmt.Errorf("cannot unmarshal %s into a bsonx.Doc", t)
+ }
+ return d.UnmarshalBSON(data)
+}
+
+// Equal compares this document to another, returning true if they are equal.
+func (d Doc) Equal(id IDoc) bool {
+ switch tt := id.(type) {
+ case Doc:
+ d2 := tt
+ if len(d) != len(d2) {
+ return false
+ }
+ for idx := range d {
+ if !d[idx].Equal(d2[idx]) {
+ return false
+ }
+ }
+ case MDoc:
+ unique := make(map[string]struct{}, 0)
+ for _, elem := range d {
+ unique[elem.Key] = struct{}{}
+ val, ok := tt[elem.Key]
+ if !ok {
+ return false
+ }
+ if !val.Equal(elem.Value) {
+ return false
+ }
+ }
+ if len(unique) != len(tt) {
+ return false
+ }
+ case nil:
+ return d == nil
+ default:
+ return false
+ }
+
+ return true
+}
+
+// String implements the fmt.Stringer interface.
+func (d Doc) String() string {
+ var buf bytes.Buffer
+ buf.Write([]byte("bson.Document{"))
+ for idx, elem := range d {
+ if idx > 0 {
+ buf.Write([]byte(", "))
+ }
+ fmt.Fprintf(&buf, "%v", elem)
+ }
+ buf.WriteByte('}')
+
+ return buf.String()
+}
+
+func (Doc) idoc() {}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/element.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/element.go
new file mode 100644
index 0000000..b45dbea
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/element.go
@@ -0,0 +1,53 @@
+// 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 bsonx
+
+import (
+ "fmt"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+)
+
+const validateMaxDepthDefault = 2048
+
+// ElementTypeError specifies that a method to obtain a BSON value an incorrect type was called on a bson.Value.
+//
+// TODO: rename this ValueTypeError.
+type ElementTypeError struct {
+ Method string
+ Type bsontype.Type
+}
+
+// Error implements the error interface.
+func (ete ElementTypeError) Error() string {
+ return "Call of " + ete.Method + " on " + ete.Type.String() + " type"
+}
+
+// Elem represents a BSON element.
+//
+// NOTE: Element cannot be the value of a map nor a property of a struct without special handling.
+// The default encoders and decoders will not process Element correctly. To do so would require
+// information loss since an Element contains a key, but the keys used when encoding a struct are
+// the struct field names. Instead of using an Element, use a Value as a value in a map or a
+// property of a struct.
+type Elem struct {
+ Key string
+ Value Val
+}
+
+// Equal compares e and e2 and returns true if they are equal.
+func (e Elem) Equal(e2 Elem) bool {
+ if e.Key != e2.Key {
+ return false
+ }
+ return e.Value.Equal(e2.Value)
+}
+
+func (e Elem) String() string {
+ // TODO(GODRIVER-612): When bsoncore has appenders for extended JSON use that here.
+ return fmt.Sprintf(`bson.Element{"%s": %v}`, e.Key, e.Value)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/mdocument.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/mdocument.go
new file mode 100644
index 0000000..e483556
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/mdocument.go
@@ -0,0 +1,231 @@
+// 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 bsonx
+
+import (
+ "bytes"
+ "fmt"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+ "github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+)
+
+// MDoc is an unordered, type safe, concise BSON document representation. This type should not be
+// used if you require ordering of values or duplicate keys.
+type MDoc map[string]Val
+
+// ReadMDoc will create a Doc using the provided slice of bytes. If the
+// slice of bytes is not a valid BSON document, this method will return an error.
+func ReadMDoc(b []byte) (MDoc, error) {
+ doc := make(MDoc, 0)
+ err := doc.UnmarshalBSON(b)
+ if err != nil {
+ return nil, err
+ }
+ return doc, nil
+}
+
+// Copy makes a shallow copy of this document.
+func (d MDoc) Copy() MDoc {
+ d2 := make(MDoc, len(d))
+ for k, v := range d {
+ d2[k] = v
+ }
+ return d2
+}
+
+// Lookup searches the document and potentially subdocuments or arrays for the
+// provided key. Each key provided to this method represents a layer of depth.
+//
+// This method will return an empty Value if they key does not exist. To know if they key actually
+// exists, use LookupErr.
+func (d MDoc) Lookup(key ...string) Val {
+ val, _ := d.LookupErr(key...)
+ return val
+}
+
+// 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 (d MDoc) LookupErr(key ...string) (Val, error) {
+ elem, err := d.LookupElementErr(key...)
+ return elem.Value, err
+}
+
+// LookupElement searches the document and potentially subdocuments or arrays for the
+// provided key. Each key provided to this method represents a layer of depth.
+//
+// This method will return an empty Element if they key does not exist. To know if they key actually
+// exists, use LookupElementErr.
+func (d MDoc) LookupElement(key ...string) Elem {
+ elem, _ := d.LookupElementErr(key...)
+ return elem
+}
+
+// LookupElementErr searches the document and potentially subdocuments for the
+// provided key. Each key provided to this method represents a layer of depth.
+func (d MDoc) LookupElementErr(key ...string) (Elem, error) {
+ // KeyNotFound operates by being created where the error happens and then the depth is
+ // incremented by 1 as each function unwinds. Whenever this function returns, it also assigns
+ // the Key slice to the key slice it has. This ensures that the proper depth is identified and
+ // the proper keys.
+ if len(key) == 0 {
+ return Elem{}, KeyNotFound{Key: key}
+ }
+
+ var elem Elem
+ var err error
+ val, ok := d[key[0]]
+ if !ok {
+ return Elem{}, KeyNotFound{Key: key}
+ }
+
+ if len(key) == 1 {
+ return Elem{Key: key[0], Value: val}, nil
+ }
+
+ switch val.Type() {
+ case bsontype.EmbeddedDocument:
+ switch tt := val.primitive.(type) {
+ case Doc:
+ elem, err = tt.LookupElementErr(key[1:]...)
+ case MDoc:
+ elem, err = tt.LookupElementErr(key[1:]...)
+ }
+ default:
+ return Elem{}, KeyNotFound{Type: val.Type()}
+ }
+ switch tt := err.(type) {
+ case KeyNotFound:
+ tt.Depth++
+ tt.Key = key
+ return Elem{}, tt
+ case nil:
+ return elem, nil
+ default:
+ return Elem{}, err // We can't actually hit this.
+ }
+}
+
+// MarshalBSONValue implements the bsoncodec.ValueMarshaler interface.
+//
+// This method will never return an error.
+func (d MDoc) MarshalBSONValue() (bsontype.Type, []byte, error) {
+ if d == nil {
+ // TODO: Should we do this?
+ return bsontype.Null, nil, nil
+ }
+ data, _ := d.MarshalBSON()
+ return bsontype.EmbeddedDocument, data, nil
+}
+
+// MarshalBSON implements the Marshaler interface.
+//
+// This method will never return an error.
+func (d MDoc) MarshalBSON() ([]byte, error) { return d.AppendMarshalBSON(nil) }
+
+// AppendMarshalBSON marshals Doc to BSON bytes, appending to dst.
+//
+// This method will never return an error.
+func (d MDoc) AppendMarshalBSON(dst []byte) ([]byte, error) {
+ idx, dst := bsoncore.ReserveLength(dst)
+ for k, v := range d {
+ t, data, _ := v.MarshalBSONValue() // Value.MarshalBSONValue never returns an error.
+ dst = append(dst, byte(t))
+ dst = append(dst, k...)
+ dst = append(dst, 0x00)
+ dst = append(dst, data...)
+ }
+ dst = append(dst, 0x00)
+ dst = bsoncore.UpdateLength(dst, idx, int32(len(dst[idx:])))
+ return dst, nil
+}
+
+// UnmarshalBSON implements the Unmarshaler interface.
+func (d *MDoc) UnmarshalBSON(b []byte) error {
+ if d == nil {
+ return ErrNilDocument
+ }
+
+ if err := bsoncore.Document(b).Validate(); err != nil {
+ return err
+ }
+
+ elems, err := bsoncore.Document(b).Elements()
+ if err != nil {
+ return err
+ }
+ var val Val
+ for _, elem := range elems {
+ rawv := elem.Value()
+ err = val.UnmarshalBSONValue(rawv.Type, rawv.Data)
+ if err != nil {
+ return err
+ }
+ (*d)[elem.Key()] = val
+ }
+ return nil
+}
+
+// Equal compares this document to another, returning true if they are equal.
+func (d MDoc) Equal(id IDoc) bool {
+ switch tt := id.(type) {
+ case MDoc:
+ d2 := tt
+ if len(d) != len(d2) {
+ return false
+ }
+ for key, value := range d {
+ value2, ok := d2[key]
+ if !ok {
+ return false
+ }
+ if !value.Equal(value2) {
+ return false
+ }
+ }
+ case Doc:
+ unique := make(map[string]struct{}, 0)
+ for _, elem := range tt {
+ unique[elem.Key] = struct{}{}
+ val, ok := d[elem.Key]
+ if !ok {
+ return false
+ }
+ if !val.Equal(elem.Value) {
+ return false
+ }
+ }
+ if len(unique) != len(d) {
+ return false
+ }
+ case nil:
+ return d == nil
+ default:
+ return false
+ }
+
+ return true
+}
+
+// String implements the fmt.Stringer interface.
+func (d MDoc) String() string {
+ var buf bytes.Buffer
+ buf.Write([]byte("bson.Document{"))
+ first := true
+ for key, value := range d {
+ if !first {
+ buf.Write([]byte(", "))
+ }
+ fmt.Fprintf(&buf, "%v", Elem{Key: key, Value: value})
+ first = false
+ }
+ buf.WriteByte('}')
+
+ return buf.String()
+}
+
+func (MDoc) idoc() {}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/primitive_codecs.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/primitive_codecs.go
new file mode 100644
index 0000000..b34f07d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/primitive_codecs.go
@@ -0,0 +1,638 @@
+// 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 bsonx
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+ "github.com/mongodb/mongo-go-driver/bson/bsonrw"
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+)
+
+var primitiveCodecs PrimitiveCodecs
+
+var tDocument = reflect.TypeOf((Doc)(nil))
+var tMDoc = reflect.TypeOf((MDoc)(nil))
+var tArray = reflect.TypeOf((Arr)(nil))
+var tValue = reflect.TypeOf(Val{})
+var tElementSlice = reflect.TypeOf(([]Elem)(nil))
+
+// 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.
+ RegisterEncoder(tDocument, bsoncodec.ValueEncoderFunc(pc.DocumentEncodeValue)).
+ RegisterEncoder(tArray, bsoncodec.ValueEncoderFunc(pc.ArrayEncodeValue)).
+ RegisterEncoder(tValue, bsoncodec.ValueEncoderFunc(pc.ValueEncodeValue)).
+ RegisterEncoder(tElementSlice, bsoncodec.ValueEncoderFunc(pc.ElementSliceEncodeValue)).
+ RegisterDecoder(tDocument, bsoncodec.ValueDecoderFunc(pc.DocumentDecodeValue)).
+ RegisterDecoder(tArray, bsoncodec.ValueDecoderFunc(pc.ArrayDecodeValue)).
+ RegisterDecoder(tValue, bsoncodec.ValueDecoderFunc(pc.ValueDecodeValue)).
+ RegisterDecoder(tElementSlice, bsoncodec.ValueDecoderFunc(pc.ElementSliceDecodeValue))
+}
+
+// DocumentEncodeValue is the ValueEncoderFunc for *Document.
+func (pc PrimitiveCodecs) DocumentEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tDocument {
+ return bsoncodec.ValueEncoderError{Name: "DocumentEncodeValue", Types: []reflect.Type{tDocument}, Received: val}
+ }
+
+ if val.IsNil() {
+ return vw.WriteNull()
+ }
+
+ doc := val.Interface().(Doc)
+
+ dw, err := vw.WriteDocument()
+ if err != nil {
+ return err
+ }
+
+ return pc.encodeDocument(ec, dw, doc)
+}
+
+// DocumentDecodeValue is the ValueDecoderFunc for *Document.
+func (pc PrimitiveCodecs) DocumentDecodeValue(dctx bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tDocument {
+ return bsoncodec.ValueDecoderError{Name: "DocumentDecodeValue", Types: []reflect.Type{tDocument}, Received: val}
+ }
+
+ return pc.documentDecodeValue(dctx, vr, val.Addr().Interface().(*Doc))
+}
+
+func (pc PrimitiveCodecs) documentDecodeValue(dctx bsoncodec.DecodeContext, vr bsonrw.ValueReader, doc *Doc) error {
+
+ dr, err := vr.ReadDocument()
+ if err != nil {
+ return err
+ }
+
+ return pc.decodeDocument(dctx, dr, doc)
+}
+
+// ArrayEncodeValue is the ValueEncoderFunc for *Array.
+func (pc PrimitiveCodecs) ArrayEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tArray {
+ return bsoncodec.ValueEncoderError{Name: "ArrayEncodeValue", Types: []reflect.Type{tArray}, Received: val}
+ }
+
+ if val.IsNil() {
+ return vw.WriteNull()
+ }
+
+ arr := val.Interface().(Arr)
+
+ aw, err := vw.WriteArray()
+ if err != nil {
+ return err
+ }
+
+ for _, val := range arr {
+ dvw, err := aw.WriteArrayElement()
+ if err != nil {
+ return err
+ }
+
+ err = pc.encodeValue(ec, dvw, val)
+
+ if err != nil {
+ return err
+ }
+ }
+
+ return aw.WriteArrayEnd()
+}
+
+// ArrayDecodeValue is the ValueDecoderFunc for *Array.
+func (pc PrimitiveCodecs) ArrayDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tArray {
+ return bsoncodec.ValueDecoderError{Name: "ArrayDecodeValue", Types: []reflect.Type{tArray}, Received: val}
+ }
+
+ ar, err := vr.ReadArray()
+ if err != nil {
+ return err
+ }
+
+ if val.IsNil() {
+ val.Set(reflect.MakeSlice(tArray, 0, 0))
+ }
+ val.SetLen(0)
+
+ for {
+ vr, err := ar.ReadValue()
+ if err == bsonrw.ErrEOA {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ var elem Val
+ err = pc.valueDecodeValue(dc, vr, &elem)
+ if err != nil {
+ return err
+ }
+
+ val.Set(reflect.Append(val, reflect.ValueOf(elem)))
+ }
+
+ return nil
+}
+
+// ElementSliceEncodeValue is the ValueEncoderFunc for []*Element.
+func (pc PrimitiveCodecs) ElementSliceEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tElementSlice {
+ return bsoncodec.ValueEncoderError{Name: "ElementSliceEncodeValue", Types: []reflect.Type{tElementSlice}, Received: val}
+ }
+
+ if val.IsNil() {
+ return vw.WriteNull()
+ }
+
+ return pc.DocumentEncodeValue(ec, vw, val.Convert(tDocument))
+}
+
+// ElementSliceDecodeValue is the ValueDecoderFunc for []*Element.
+func (pc PrimitiveCodecs) ElementSliceDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tElementSlice {
+ return bsoncodec.ValueDecoderError{Name: "ElementSliceDecodeValue", Types: []reflect.Type{tElementSlice}, Received: val}
+ }
+
+ if val.IsNil() {
+ val.Set(reflect.MakeSlice(val.Type(), 0, 0))
+ }
+
+ val.SetLen(0)
+
+ dr, err := vr.ReadDocument()
+ if err != nil {
+ return err
+ }
+ elems := make([]reflect.Value, 0)
+ for {
+ key, vr, err := dr.ReadElement()
+ if err == bsonrw.ErrEOD {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ var elem Elem
+ err = pc.elementDecodeValue(dc, vr, key, &elem)
+ if err != nil {
+ return err
+ }
+
+ elems = append(elems, reflect.ValueOf(elem))
+ }
+
+ val.Set(reflect.Append(val, elems...))
+ return nil
+}
+
+// ValueEncodeValue is the ValueEncoderFunc for *Value.
+func (pc PrimitiveCodecs) ValueEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
+ if !val.IsValid() || val.Type() != tValue {
+ return bsoncodec.ValueEncoderError{Name: "ValueEncodeValue", Types: []reflect.Type{tValue}, Received: val}
+ }
+
+ v := val.Interface().(Val)
+
+ return pc.encodeValue(ec, vw, v)
+}
+
+// ValueDecodeValue is the ValueDecoderFunc for *Value.
+func (pc PrimitiveCodecs) ValueDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
+ if !val.CanSet() || val.Type() != tValue {
+ return bsoncodec.ValueDecoderError{Name: "ValueDecodeValue", Types: []reflect.Type{tValue}, Received: val}
+ }
+
+ return pc.valueDecodeValue(dc, vr, val.Addr().Interface().(*Val))
+}
+
+// encodeDocument is a separate function that we use because CodeWithScope
+// returns us a DocumentWriter and we need to do the same logic that we would do
+// for a document but cannot use a Codec.
+func (pc PrimitiveCodecs) encodeDocument(ec bsoncodec.EncodeContext, dw bsonrw.DocumentWriter, doc Doc) error {
+ for _, elem := range doc {
+ dvw, err := dw.WriteDocumentElement(elem.Key)
+ if err != nil {
+ return err
+ }
+
+ err = pc.encodeValue(ec, dvw, elem.Value)
+
+ if err != nil {
+ return err
+ }
+ }
+
+ return dw.WriteDocumentEnd()
+}
+
+// DecodeDocument haves decoding into a Doc from a bsonrw.DocumentReader.
+func (pc PrimitiveCodecs) DecodeDocument(dctx bsoncodec.DecodeContext, dr bsonrw.DocumentReader, pdoc *Doc) error {
+ return pc.decodeDocument(dctx, dr, pdoc)
+}
+
+func (pc PrimitiveCodecs) decodeDocument(dctx bsoncodec.DecodeContext, dr bsonrw.DocumentReader, pdoc *Doc) error {
+ if *pdoc == nil {
+ *pdoc = make(Doc, 0)
+ }
+ *pdoc = (*pdoc)[:0]
+ for {
+ key, vr, err := dr.ReadElement()
+ if err == bsonrw.ErrEOD {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ var elem Elem
+ err = pc.elementDecodeValue(dctx, vr, key, &elem)
+ if err != nil {
+ return err
+ }
+
+ *pdoc = append(*pdoc, elem)
+ }
+ return nil
+}
+
+func (pc PrimitiveCodecs) elementDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, key string, elem *Elem) error {
+ var val Val
+ switch vr.Type() {
+ case bsontype.Double:
+ f64, err := vr.ReadDouble()
+ if err != nil {
+ return err
+ }
+ val = Double(f64)
+ case bsontype.String:
+ str, err := vr.ReadString()
+ if err != nil {
+ return err
+ }
+ val = String(str)
+ case bsontype.EmbeddedDocument:
+ var embeddedDoc Doc
+ err := pc.documentDecodeValue(dc, vr, &embeddedDoc)
+ if err != nil {
+ return err
+ }
+ val = Document(embeddedDoc)
+ case bsontype.Array:
+ arr := reflect.New(tArray).Elem()
+ err := pc.ArrayDecodeValue(dc, vr, arr)
+ if err != nil {
+ return err
+ }
+ val = Array(arr.Interface().(Arr))
+ case bsontype.Binary:
+ data, subtype, err := vr.ReadBinary()
+ if err != nil {
+ return err
+ }
+ val = Binary(subtype, data)
+ case bsontype.Undefined:
+ err := vr.ReadUndefined()
+ if err != nil {
+ return err
+ }
+ val = Undefined()
+ case bsontype.ObjectID:
+ oid, err := vr.ReadObjectID()
+ if err != nil {
+ return err
+ }
+ val = ObjectID(oid)
+ case bsontype.Boolean:
+ b, err := vr.ReadBoolean()
+ if err != nil {
+ return err
+ }
+ val = Boolean(b)
+ case bsontype.DateTime:
+ dt, err := vr.ReadDateTime()
+ if err != nil {
+ return err
+ }
+ val = DateTime(dt)
+ case bsontype.Null:
+ err := vr.ReadNull()
+ if err != nil {
+ return err
+ }
+ val = Null()
+ case bsontype.Regex:
+ pattern, options, err := vr.ReadRegex()
+ if err != nil {
+ return err
+ }
+ val = Regex(pattern, options)
+ case bsontype.DBPointer:
+ ns, pointer, err := vr.ReadDBPointer()
+ if err != nil {
+ return err
+ }
+ val = DBPointer(ns, pointer)
+ case bsontype.JavaScript:
+ js, err := vr.ReadJavascript()
+ if err != nil {
+ return err
+ }
+ val = JavaScript(js)
+ case bsontype.Symbol:
+ symbol, err := vr.ReadSymbol()
+ if err != nil {
+ return err
+ }
+ val = Symbol(symbol)
+ case bsontype.CodeWithScope:
+ code, scope, err := vr.ReadCodeWithScope()
+ if err != nil {
+ return err
+ }
+ var doc Doc
+ err = pc.decodeDocument(dc, scope, &doc)
+ if err != nil {
+ return err
+ }
+ val = CodeWithScope(code, doc)
+ case bsontype.Int32:
+ i32, err := vr.ReadInt32()
+ if err != nil {
+ return err
+ }
+ val = Int32(i32)
+ case bsontype.Timestamp:
+ t, i, err := vr.ReadTimestamp()
+ if err != nil {
+ return err
+ }
+ val = Timestamp(t, i)
+ case bsontype.Int64:
+ i64, err := vr.ReadInt64()
+ if err != nil {
+ return err
+ }
+ val = Int64(i64)
+ case bsontype.Decimal128:
+ d128, err := vr.ReadDecimal128()
+ if err != nil {
+ return err
+ }
+ val = Decimal128(d128)
+ case bsontype.MinKey:
+ err := vr.ReadMinKey()
+ if err != nil {
+ return err
+ }
+ val = MinKey()
+ case bsontype.MaxKey:
+ err := vr.ReadMaxKey()
+ if err != nil {
+ return err
+ }
+ val = MaxKey()
+ default:
+ return fmt.Errorf("Cannot read unknown BSON type %s", vr.Type())
+ }
+
+ *elem = Elem{Key: key, Value: val}
+ return nil
+}
+
+// encodeValue does not validation, and the callers must perform validation on val before calling
+// this method.
+func (pc PrimitiveCodecs) encodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val Val) error {
+ var err error
+ switch val.Type() {
+ case bsontype.Double:
+ err = vw.WriteDouble(val.Double())
+ case bsontype.String:
+ err = vw.WriteString(val.StringValue())
+ case bsontype.EmbeddedDocument:
+ var encoder bsoncodec.ValueEncoder
+ encoder, err = ec.LookupEncoder(tDocument)
+ if err != nil {
+ break
+ }
+ err = encoder.EncodeValue(ec, vw, reflect.ValueOf(val.Document()))
+ case bsontype.Array:
+ var encoder bsoncodec.ValueEncoder
+ encoder, err = ec.LookupEncoder(tArray)
+ if err != nil {
+ break
+ }
+ err = encoder.EncodeValue(ec, vw, reflect.ValueOf(val.Array()))
+ case bsontype.Binary:
+ // TODO: FIX THIS (╯°□°)╯︵ ┻━┻
+ subtype, data := val.Binary()
+ err = vw.WriteBinaryWithSubtype(data, subtype)
+ case bsontype.Undefined:
+ err = vw.WriteUndefined()
+ case bsontype.ObjectID:
+ err = vw.WriteObjectID(val.ObjectID())
+ case bsontype.Boolean:
+ err = vw.WriteBoolean(val.Boolean())
+ case bsontype.DateTime:
+ err = vw.WriteDateTime(val.DateTime())
+ case bsontype.Null:
+ err = vw.WriteNull()
+ case bsontype.Regex:
+ err = vw.WriteRegex(val.Regex())
+ case bsontype.DBPointer:
+ err = vw.WriteDBPointer(val.DBPointer())
+ case bsontype.JavaScript:
+ err = vw.WriteJavascript(val.JavaScript())
+ case bsontype.Symbol:
+ err = vw.WriteSymbol(val.Symbol())
+ case bsontype.CodeWithScope:
+ code, scope := val.CodeWithScope()
+
+ var cwsw bsonrw.DocumentWriter
+ cwsw, err = vw.WriteCodeWithScope(code)
+ if err != nil {
+ break
+ }
+
+ err = pc.encodeDocument(ec, cwsw, scope)
+ case bsontype.Int32:
+ err = vw.WriteInt32(val.Int32())
+ case bsontype.Timestamp:
+ err = vw.WriteTimestamp(val.Timestamp())
+ case bsontype.Int64:
+ err = vw.WriteInt64(val.Int64())
+ case bsontype.Decimal128:
+ err = vw.WriteDecimal128(val.Decimal128())
+ case bsontype.MinKey:
+ err = vw.WriteMinKey()
+ case bsontype.MaxKey:
+ err = vw.WriteMaxKey()
+ default:
+ err = fmt.Errorf("%T is not a valid BSON type to encode", val.Type())
+ }
+
+ return err
+}
+
+func (pc PrimitiveCodecs) valueDecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val *Val) error {
+ switch vr.Type() {
+ case bsontype.Double:
+ f64, err := vr.ReadDouble()
+ if err != nil {
+ return err
+ }
+ *val = Double(f64)
+ case bsontype.String:
+ str, err := vr.ReadString()
+ if err != nil {
+ return err
+ }
+ *val = String(str)
+ case bsontype.EmbeddedDocument:
+ var embeddedDoc Doc
+ err := pc.documentDecodeValue(dc, vr, &embeddedDoc)
+ if err != nil {
+ return err
+ }
+ *val = Document(embeddedDoc)
+ case bsontype.Array:
+ arr := reflect.New(tArray).Elem()
+ err := pc.ArrayDecodeValue(dc, vr, arr)
+ if err != nil {
+ return err
+ }
+ *val = Array(arr.Interface().(Arr))
+ case bsontype.Binary:
+ data, subtype, err := vr.ReadBinary()
+ if err != nil {
+ return err
+ }
+ *val = Binary(subtype, data)
+ case bsontype.Undefined:
+ err := vr.ReadUndefined()
+ if err != nil {
+ return err
+ }
+ *val = Undefined()
+ case bsontype.ObjectID:
+ oid, err := vr.ReadObjectID()
+ if err != nil {
+ return err
+ }
+ *val = ObjectID(oid)
+ case bsontype.Boolean:
+ b, err := vr.ReadBoolean()
+ if err != nil {
+ return err
+ }
+ *val = Boolean(b)
+ case bsontype.DateTime:
+ dt, err := vr.ReadDateTime()
+ if err != nil {
+ return err
+ }
+ *val = DateTime(dt)
+ case bsontype.Null:
+ err := vr.ReadNull()
+ if err != nil {
+ return err
+ }
+ *val = Null()
+ case bsontype.Regex:
+ pattern, options, err := vr.ReadRegex()
+ if err != nil {
+ return err
+ }
+ *val = Regex(pattern, options)
+ case bsontype.DBPointer:
+ ns, pointer, err := vr.ReadDBPointer()
+ if err != nil {
+ return err
+ }
+ *val = DBPointer(ns, pointer)
+ case bsontype.JavaScript:
+ js, err := vr.ReadJavascript()
+ if err != nil {
+ return err
+ }
+ *val = JavaScript(js)
+ case bsontype.Symbol:
+ symbol, err := vr.ReadSymbol()
+ if err != nil {
+ return err
+ }
+ *val = Symbol(symbol)
+ case bsontype.CodeWithScope:
+ code, scope, err := vr.ReadCodeWithScope()
+ if err != nil {
+ return err
+ }
+ var scopeDoc Doc
+ err = pc.decodeDocument(dc, scope, &scopeDoc)
+ if err != nil {
+ return err
+ }
+ *val = CodeWithScope(code, scopeDoc)
+ case bsontype.Int32:
+ i32, err := vr.ReadInt32()
+ if err != nil {
+ return err
+ }
+ *val = Int32(i32)
+ case bsontype.Timestamp:
+ t, i, err := vr.ReadTimestamp()
+ if err != nil {
+ return err
+ }
+ *val = Timestamp(t, i)
+ case bsontype.Int64:
+ i64, err := vr.ReadInt64()
+ if err != nil {
+ return err
+ }
+ *val = Int64(i64)
+ case bsontype.Decimal128:
+ d128, err := vr.ReadDecimal128()
+ if err != nil {
+ return err
+ }
+ *val = Decimal128(d128)
+ case bsontype.MinKey:
+ err := vr.ReadMinKey()
+ if err != nil {
+ return err
+ }
+ *val = MinKey()
+ case bsontype.MaxKey:
+ err := vr.ReadMaxKey()
+ if err != nil {
+ return err
+ }
+ *val = MaxKey()
+ default:
+ return fmt.Errorf("Cannot read unknown BSON type %s", vr.Type())
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/registry.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/registry.go
new file mode 100644
index 0000000..83dfaa5
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/registry.go
@@ -0,0 +1,22 @@
+package bsonx
+
+import (
+ "github.com/mongodb/mongo-go-driver/bson"
+ "github.com/mongodb/mongo-go-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
+// deocders 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)
+ bson.PrimitiveCodecs{}.RegisterPrimitiveCodecs(rb)
+ primitiveCodecs.RegisterPrimitiveCodecs(rb)
+ return rb
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/value.go b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/value.go
new file mode 100644
index 0000000..033d9d8
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/bsonx/value.go
@@ -0,0 +1,899 @@
+// 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 bsonx
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "math"
+ "time"
+
+ "github.com/mongodb/mongo-go-driver/bson/bsontype"
+ "github.com/mongodb/mongo-go-driver/bson/primitive"
+ "github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+)
+
+// Val represents a BSON value.
+type Val struct {
+ // NOTE: The bootstrap is a small amount of space that'll be on the stack. At 15 bytes this
+ // doesn't make this type any larger, since there are 7 bytes of padding and we want an int64 to
+ // store small values (e.g. boolean, double, int64, etc...). The primitive property is where all
+ // of the larger values go. They will use either Go primitives or the primitive.* types.
+ t bsontype.Type
+ bootstrap [15]byte
+ primitive interface{}
+}
+
+func (v Val) reset() Val {
+ v.primitive = nil // clear out any pointers so we don't accidentally stop them from being garbage collected.
+ v.t = bsontype.Type(0)
+ v.bootstrap[0] = 0x00
+ v.bootstrap[1] = 0x00
+ v.bootstrap[2] = 0x00
+ v.bootstrap[3] = 0x00
+ v.bootstrap[4] = 0x00
+ v.bootstrap[5] = 0x00
+ v.bootstrap[6] = 0x00
+ v.bootstrap[7] = 0x00
+ v.bootstrap[8] = 0x00
+ v.bootstrap[9] = 0x00
+ v.bootstrap[10] = 0x00
+ v.bootstrap[11] = 0x00
+ v.bootstrap[12] = 0x00
+ v.bootstrap[13] = 0x00
+ v.bootstrap[14] = 0x00
+ return v
+}
+
+func (v Val) string() string {
+ if v.primitive != nil {
+ return v.primitive.(string)
+ }
+ // The string will either end with a null byte or it fills the entire bootstrap space.
+ length := uint8(v.bootstrap[0])
+ return string(v.bootstrap[1 : length+1])
+}
+
+func (v Val) writestring(str string) Val {
+ switch {
+ case len(str) < 15:
+ v.bootstrap[0] = uint8(len(str))
+ copy(v.bootstrap[1:], str)
+ default:
+ v.primitive = str
+ }
+ return v
+}
+
+func (v Val) i64() int64 {
+ return int64(v.bootstrap[0]) | int64(v.bootstrap[1])<<8 | int64(v.bootstrap[2])<<16 |
+ int64(v.bootstrap[3])<<24 | int64(v.bootstrap[4])<<32 | int64(v.bootstrap[5])<<40 |
+ int64(v.bootstrap[6])<<48 | int64(v.bootstrap[7])<<56
+}
+
+func (v Val) writei64(i64 int64) Val {
+ v.bootstrap[0] = byte(i64)
+ v.bootstrap[1] = byte(i64 >> 8)
+ v.bootstrap[2] = byte(i64 >> 16)
+ v.bootstrap[3] = byte(i64 >> 24)
+ v.bootstrap[4] = byte(i64 >> 32)
+ v.bootstrap[5] = byte(i64 >> 40)
+ v.bootstrap[6] = byte(i64 >> 48)
+ v.bootstrap[7] = byte(i64 >> 56)
+ return v
+}
+
+// IsZero returns true if this value is zero or a BSON null.
+func (v Val) IsZero() bool { return v.t == bsontype.Type(0) || v.t == bsontype.Null }
+
+func (v Val) String() string {
+ // TODO(GODRIVER-612): When bsoncore has appenders for extended JSON use that here.
+ return fmt.Sprintf("%v", v.Interface())
+}
+
+// Interface returns the Go value of this Value as an empty interface.
+//
+// This method will return nil if it is empty, otherwise it will return a Go primitive or a
+// primitive.* instance.
+func (v Val) Interface() interface{} {
+ switch v.Type() {
+ case bsontype.Double:
+ return v.Double()
+ case bsontype.String:
+ return v.StringValue()
+ case bsontype.EmbeddedDocument:
+ switch v.primitive.(type) {
+ case Doc:
+ return v.primitive.(Doc)
+ case MDoc:
+ return v.primitive.(MDoc)
+ default:
+ return primitive.Null{}
+ }
+ case bsontype.Array:
+ return v.Array()
+ case bsontype.Binary:
+ return v.primitive.(primitive.Binary)
+ case bsontype.Undefined:
+ return primitive.Undefined{}
+ case bsontype.ObjectID:
+ return v.ObjectID()
+ case bsontype.Boolean:
+ return v.Boolean()
+ case bsontype.DateTime:
+ return v.DateTime()
+ case bsontype.Null:
+ return primitive.Null{}
+ case bsontype.Regex:
+ return v.primitive.(primitive.Regex)
+ case bsontype.DBPointer:
+ return v.primitive.(primitive.DBPointer)
+ case bsontype.JavaScript:
+ return v.JavaScript()
+ case bsontype.Symbol:
+ return v.Symbol()
+ case bsontype.CodeWithScope:
+ return v.primitive.(primitive.CodeWithScope)
+ case bsontype.Int32:
+ return v.Int32()
+ case bsontype.Timestamp:
+ t, i := v.Timestamp()
+ return primitive.Timestamp{T: t, I: i}
+ case bsontype.Int64:
+ return v.Int64()
+ case bsontype.Decimal128:
+ return v.Decimal128()
+ case bsontype.MinKey:
+ return primitive.MinKey{}
+ case bsontype.MaxKey:
+ return primitive.MaxKey{}
+ default:
+ return primitive.Null{}
+ }
+}
+
+// MarshalBSONValue implements the bsoncodec.ValueMarshaler interface.
+func (v Val) MarshalBSONValue() (bsontype.Type, []byte, error) {
+ return v.MarshalAppendBSONValue(nil)
+}
+
+// MarshalAppendBSONValue is similar to MarshalBSONValue, but allows the caller to specify a slice
+// to add the bytes to.
+func (v Val) MarshalAppendBSONValue(dst []byte) (bsontype.Type, []byte, error) {
+ t := v.Type()
+ switch v.Type() {
+ case bsontype.Double:
+ dst = bsoncore.AppendDouble(dst, v.Double())
+ case bsontype.String:
+ dst = bsoncore.AppendString(dst, v.String())
+ case bsontype.EmbeddedDocument:
+ switch v.primitive.(type) {
+ case Doc:
+ t, dst, _ = v.primitive.(Doc).MarshalBSONValue() // Doc.MarshalBSONValue never returns an error.
+ case MDoc:
+ t, dst, _ = v.primitive.(MDoc).MarshalBSONValue() // MDoc.MarshalBSONValue never returns an error.
+ }
+ case bsontype.Array:
+ t, dst, _ = v.Array().MarshalBSONValue() // Arr.MarshalBSON never returns an error.
+ case bsontype.Binary:
+ subtype, bindata := v.Binary()
+ dst = bsoncore.AppendBinary(dst, subtype, bindata)
+ case bsontype.Undefined:
+ case bsontype.ObjectID:
+ dst = bsoncore.AppendObjectID(dst, v.ObjectID())
+ case bsontype.Boolean:
+ dst = bsoncore.AppendBoolean(dst, v.Boolean())
+ case bsontype.DateTime:
+ dst = bsoncore.AppendDateTime(dst, int64(v.DateTime()))
+ case bsontype.Null:
+ case bsontype.Regex:
+ pattern, options := v.Regex()
+ dst = bsoncore.AppendRegex(dst, pattern, options)
+ case bsontype.DBPointer:
+ ns, ptr := v.DBPointer()
+ dst = bsoncore.AppendDBPointer(dst, ns, ptr)
+ case bsontype.JavaScript:
+ dst = bsoncore.AppendJavaScript(dst, string(v.JavaScript()))
+ case bsontype.Symbol:
+ dst = bsoncore.AppendSymbol(dst, string(v.Symbol()))
+ case bsontype.CodeWithScope:
+ code, doc := v.CodeWithScope()
+ var scope []byte
+ scope, _ = doc.MarshalBSON() // Doc.MarshalBSON never returns an error.
+ dst = bsoncore.AppendCodeWithScope(dst, code, scope)
+ case bsontype.Int32:
+ dst = bsoncore.AppendInt32(dst, v.Int32())
+ case bsontype.Timestamp:
+ t, i := v.Timestamp()
+ dst = bsoncore.AppendTimestamp(dst, t, i)
+ case bsontype.Int64:
+ dst = bsoncore.AppendInt64(dst, v.Int64())
+ case bsontype.Decimal128:
+ dst = bsoncore.AppendDecimal128(dst, v.Decimal128())
+ case bsontype.MinKey:
+ case bsontype.MaxKey:
+ default:
+ panic(fmt.Errorf("invalid BSON type %v", t))
+ }
+
+ return t, dst, nil
+}
+
+// UnmarshalBSONValue implements the bsoncodec.ValueUnmarshaler interface.
+func (v *Val) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
+ if v == nil {
+ return errors.New("cannot unmarshal into nil Value")
+ }
+ var err error
+ var ok = true
+ var rem []byte
+ switch t {
+ case bsontype.Double:
+ var f64 float64
+ f64, rem, ok = bsoncore.ReadDouble(data)
+ *v = Double(f64)
+ case bsontype.String:
+ var str string
+ str, rem, ok = bsoncore.ReadString(data)
+ *v = String(str)
+ case bsontype.EmbeddedDocument:
+ var raw []byte
+ var doc Doc
+ raw, rem, ok = bsoncore.ReadDocument(data)
+ doc, err = ReadDoc(raw)
+ *v = Document(doc)
+ case bsontype.Array:
+ var raw []byte
+ arr := make(Arr, 0)
+ raw, rem, ok = bsoncore.ReadArray(data)
+ err = arr.UnmarshalBSONValue(t, raw)
+ *v = Array(arr)
+ case bsontype.Binary:
+ var subtype byte
+ var bindata []byte
+ subtype, bindata, rem, ok = bsoncore.ReadBinary(data)
+ *v = Binary(subtype, bindata)
+ case bsontype.Undefined:
+ *v = Undefined()
+ case bsontype.ObjectID:
+ var oid primitive.ObjectID
+ oid, rem, ok = bsoncore.ReadObjectID(data)
+ *v = ObjectID(oid)
+ case bsontype.Boolean:
+ var b bool
+ b, rem, ok = bsoncore.ReadBoolean(data)
+ *v = Boolean(b)
+ case bsontype.DateTime:
+ var dt int64
+ dt, rem, ok = bsoncore.ReadDateTime(data)
+ *v = DateTime(dt)
+ case bsontype.Null:
+ *v = Null()
+ case bsontype.Regex:
+ var pattern, options string
+ pattern, options, rem, ok = bsoncore.ReadRegex(data)
+ *v = Regex(pattern, options)
+ case bsontype.DBPointer:
+ var ns string
+ var ptr primitive.ObjectID
+ ns, ptr, rem, ok = bsoncore.ReadDBPointer(data)
+ *v = DBPointer(ns, ptr)
+ case bsontype.JavaScript:
+ var js string
+ js, rem, ok = bsoncore.ReadJavaScript(data)
+ *v = JavaScript(js)
+ case bsontype.Symbol:
+ var symbol string
+ symbol, rem, ok = bsoncore.ReadSymbol(data)
+ *v = Symbol(symbol)
+ case bsontype.CodeWithScope:
+ var raw []byte
+ var code string
+ var scope Doc
+ code, raw, rem, ok = bsoncore.ReadCodeWithScope(data)
+ scope, err = ReadDoc(raw)
+ *v = CodeWithScope(code, scope)
+ case bsontype.Int32:
+ var i32 int32
+ i32, rem, ok = bsoncore.ReadInt32(data)
+ *v = Int32(i32)
+ case bsontype.Timestamp:
+ var i, t uint32
+ t, i, rem, ok = bsoncore.ReadTimestamp(data)
+ *v = Timestamp(t, i)
+ case bsontype.Int64:
+ var i64 int64
+ i64, rem, ok = bsoncore.ReadInt64(data)
+ *v = Int64(i64)
+ case bsontype.Decimal128:
+ var d128 primitive.Decimal128
+ d128, rem, ok = bsoncore.ReadDecimal128(data)
+ *v = Decimal128(d128)
+ case bsontype.MinKey:
+ *v = MinKey()
+ case bsontype.MaxKey:
+ *v = MaxKey()
+ default:
+ err = fmt.Errorf("invalid BSON type %v", t)
+ }
+
+ if !ok && err == nil {
+ err = bsoncore.NewInsufficientBytesError(data, rem)
+ }
+
+ return err
+}
+
+// Type returns the BSON type of this value.
+func (v Val) Type() bsontype.Type {
+ if v.t == bsontype.Type(0) {
+ return bsontype.Null
+ }
+ return v.t
+}
+
+// IsNumber returns true if the type of v is a numberic BSON type.
+func (v Val) IsNumber() bool {
+ switch v.Type() {
+ case bsontype.Double, bsontype.Int32, bsontype.Int64, bsontype.Decimal128:
+ return true
+ default:
+ return false
+ }
+}
+
+// Double returns the BSON double value the Value represents. It panics if the value is a BSON type
+// other than double.
+func (v Val) Double() float64 {
+ if v.t != bsontype.Double {
+ panic(ElementTypeError{"bson.Value.Double", v.t})
+ }
+ return math.Float64frombits(binary.LittleEndian.Uint64(v.bootstrap[0:8]))
+}
+
+// DoubleOK is the same as Double, but returns a boolean instead of panicking.
+func (v Val) DoubleOK() (float64, bool) {
+ if v.t != bsontype.Double {
+ return 0, false
+ }
+ return math.Float64frombits(binary.LittleEndian.Uint64(v.bootstrap[0:8])), true
+}
+
+// StringValue returns the BSON string the Value represents. It panics if the value is a BSON type
+// other than string.
+//
+// NOTE: This method is called StringValue to avoid it implementing the
+// fmt.Stringer interface.
+func (v Val) StringValue() string {
+ if v.t != bsontype.String {
+ panic(ElementTypeError{"bson.Value.StringValue", v.t})
+ }
+ return v.string()
+}
+
+// StringValueOK is the same as StringValue, but returns a boolean instead of
+// panicking.
+func (v Val) StringValueOK() (string, bool) {
+ if v.t != bsontype.String {
+ return "", false
+ }
+ return v.string(), true
+}
+
+func (v Val) asDoc() Doc {
+ doc, ok := v.primitive.(Doc)
+ if ok {
+ return doc
+ }
+ mdoc := v.primitive.(MDoc)
+ for k, v := range mdoc {
+ doc = append(doc, Elem{k, v})
+ }
+ return doc
+}
+
+func (v Val) asMDoc() MDoc {
+ mdoc, ok := v.primitive.(MDoc)
+ if ok {
+ return mdoc
+ }
+ doc := v.primitive.(Doc)
+ for _, elem := range doc {
+ mdoc[elem.Key] = elem.Value
+ }
+ return mdoc
+}
+
+// Document returns the BSON embedded document value the Value represents. It panics if the value
+// is a BSON type other than embedded document.
+func (v Val) Document() Doc {
+ if v.t != bsontype.EmbeddedDocument {
+ panic(ElementTypeError{"bson.Value.Document", v.t})
+ }
+ return v.asDoc()
+}
+
+// DocumentOK is the same as Document, except it returns a boolean
+// instead of panicking.
+func (v Val) DocumentOK() (Doc, bool) {
+ if v.t != bsontype.EmbeddedDocument {
+ return nil, false
+ }
+ return v.asDoc(), true
+}
+
+// MDocument returns the BSON embedded document value the Value represents. It panics if the value
+// is a BSON type other than embedded document.
+func (v Val) MDocument() MDoc {
+ if v.t != bsontype.EmbeddedDocument {
+ panic(ElementTypeError{"bson.Value.MDocument", v.t})
+ }
+ return v.asMDoc()
+}
+
+// MDocumentOK is the same as Document, except it returns a boolean
+// instead of panicking.
+func (v Val) MDocumentOK() (MDoc, bool) {
+ if v.t != bsontype.EmbeddedDocument {
+ return nil, false
+ }
+ return v.asMDoc(), true
+}
+
+// Array returns the BSON array value the Value represents. It panics if the value is a BSON type
+// other than array.
+func (v Val) Array() Arr {
+ if v.t != bsontype.Array {
+ panic(ElementTypeError{"bson.Value.Array", v.t})
+ }
+ return v.primitive.(Arr)
+}
+
+// ArrayOK is the same as Array, except it returns a boolean
+// instead of panicking.
+func (v Val) ArrayOK() (Arr, bool) {
+ if v.t != bsontype.Array {
+ return nil, false
+ }
+ return v.primitive.(Arr), true
+}
+
+// Binary returns the BSON binary value the Value represents. It panics if the value is a BSON type
+// other than binary.
+func (v Val) Binary() (byte, []byte) {
+ if v.t != bsontype.Binary {
+ panic(ElementTypeError{"bson.Value.Binary", v.t})
+ }
+ bin := v.primitive.(primitive.Binary)
+ return bin.Subtype, bin.Data
+}
+
+// BinaryOK is the same as Binary, except it returns a boolean instead of
+// panicking.
+func (v Val) BinaryOK() (byte, []byte, bool) {
+ if v.t != bsontype.Binary {
+ return 0x00, nil, false
+ }
+ bin := v.primitive.(primitive.Binary)
+ return bin.Subtype, bin.Data, true
+}
+
+// Undefined returns the BSON undefined the Value represents. It panics if the value is a BSON type
+// other than binary.
+func (v Val) Undefined() {
+ if v.t != bsontype.Undefined {
+ panic(ElementTypeError{"bson.Value.Undefined", v.t})
+ }
+ return
+}
+
+// UndefinedOK is the same as Undefined, except it returns a boolean instead of
+// panicking.
+func (v Val) UndefinedOK() bool {
+ if v.t != bsontype.Undefined {
+ return false
+ }
+ return true
+}
+
+// ObjectID returns the BSON ObjectID the Value represents. It panics if the value is a BSON type
+// other than ObjectID.
+func (v Val) ObjectID() primitive.ObjectID {
+ if v.t != bsontype.ObjectID {
+ panic(ElementTypeError{"bson.Value.ObjectID", v.t})
+ }
+ var oid primitive.ObjectID
+ copy(oid[:], v.bootstrap[:12])
+ return oid
+}
+
+// ObjectIDOK is the same as ObjectID, except it returns a boolean instead of
+// panicking.
+func (v Val) ObjectIDOK() (primitive.ObjectID, bool) {
+ if v.t != bsontype.ObjectID {
+ return primitive.ObjectID{}, false
+ }
+ var oid primitive.ObjectID
+ copy(oid[:], v.bootstrap[:12])
+ return oid, true
+}
+
+// Boolean returns the BSON boolean the Value represents. It panics if the value is a BSON type
+// other than boolean.
+func (v Val) Boolean() bool {
+ if v.t != bsontype.Boolean {
+ panic(ElementTypeError{"bson.Value.Boolean", v.t})
+ }
+ return v.bootstrap[0] == 0x01
+}
+
+// BooleanOK is the same as Boolean, except it returns a boolean instead of
+// panicking.
+func (v Val) BooleanOK() (bool, bool) {
+ if v.t != bsontype.Boolean {
+ return false, false
+ }
+ return v.bootstrap[0] == 0x01, true
+}
+
+// DateTime returns the BSON datetime the Value represents. It panics if the value is a BSON type
+// other than datetime.
+func (v Val) DateTime() int64 {
+ if v.t != bsontype.DateTime {
+ panic(ElementTypeError{"bson.Value.DateTime", v.t})
+ }
+ return v.i64()
+}
+
+// DateTimeOK is the same as DateTime, except it returns a boolean instead of
+// panicking.
+func (v Val) DateTimeOK() (int64, bool) {
+ if v.t != bsontype.DateTime {
+ return 0, false
+ }
+ return v.i64(), true
+}
+
+// Time returns the BSON datetime the Value represents as time.Time. It panics if the value is a BSON
+// type other than datetime.
+func (v Val) Time() time.Time {
+ if v.t != bsontype.DateTime {
+ panic(ElementTypeError{"bson.Value.Time", v.t})
+ }
+ i := v.i64()
+ return time.Unix(int64(i)/1000, int64(i)%1000*1000000)
+}
+
+// TimeOK is the same as Time, except it returns a boolean instead of
+// panicking.
+func (v Val) TimeOK() (time.Time, bool) {
+ if v.t != bsontype.DateTime {
+ return time.Time{}, false
+ }
+ i := v.i64()
+ return time.Unix(int64(i)/1000, int64(i)%1000*1000000), true
+}
+
+// Null returns the BSON undefined the Value represents. It panics if the value is a BSON type
+// other than binary.
+func (v Val) Null() {
+ if v.t != bsontype.Null && v.t != bsontype.Type(0) {
+ panic(ElementTypeError{"bson.Value.Null", v.t})
+ }
+ return
+}
+
+// NullOK is the same as Null, except it returns a boolean instead of
+// panicking.
+func (v Val) NullOK() bool {
+ if v.t != bsontype.Null && v.t != bsontype.Type(0) {
+ return false
+ }
+ return true
+}
+
+// Regex returns the BSON regex the Value represents. It panics if the value is a BSON type
+// other than regex.
+func (v Val) Regex() (pattern, options string) {
+ if v.t != bsontype.Regex {
+ panic(ElementTypeError{"bson.Value.Regex", v.t})
+ }
+ regex := v.primitive.(primitive.Regex)
+ return regex.Pattern, regex.Options
+}
+
+// RegexOK is the same as Regex, except that it returns a boolean
+// instead of panicking.
+func (v Val) RegexOK() (pattern, options string, ok bool) {
+ if v.t != bsontype.Regex {
+ return "", "", false
+ }
+ regex := v.primitive.(primitive.Regex)
+ return regex.Pattern, regex.Options, true
+}
+
+// DBPointer returns the BSON dbpointer the Value represents. It panics if the value is a BSON type
+// other than dbpointer.
+func (v Val) DBPointer() (string, primitive.ObjectID) {
+ if v.t != bsontype.DBPointer {
+ panic(ElementTypeError{"bson.Value.DBPointer", v.t})
+ }
+ dbptr := v.primitive.(primitive.DBPointer)
+ return dbptr.DB, dbptr.Pointer
+}
+
+// DBPointerOK is the same as DBPoitner, except that it returns a boolean
+// instead of panicking.
+func (v Val) DBPointerOK() (string, primitive.ObjectID, bool) {
+ if v.t != bsontype.DBPointer {
+ return "", primitive.ObjectID{}, false
+ }
+ dbptr := v.primitive.(primitive.DBPointer)
+ return dbptr.DB, dbptr.Pointer, true
+}
+
+// JavaScript returns the BSON JavaScript the Value represents. It panics if the value is a BSON type
+// other than JavaScript.
+func (v Val) JavaScript() string {
+ if v.t != bsontype.JavaScript {
+ panic(ElementTypeError{"bson.Value.JavaScript", v.t})
+ }
+ return v.string()
+}
+
+// JavaScriptOK is the same as Javascript, except that it returns a boolean
+// instead of panicking.
+func (v Val) JavaScriptOK() (string, bool) {
+ if v.t != bsontype.JavaScript {
+ return "", false
+ }
+ return v.string(), true
+}
+
+// Symbol returns the BSON symbol the Value represents. It panics if the value is a BSON type
+// other than symbol.
+func (v Val) Symbol() string {
+ if v.t != bsontype.Symbol {
+ panic(ElementTypeError{"bson.Value.Symbol", v.t})
+ }
+ return v.string()
+}
+
+// SymbolOK is the same as Javascript, except that it returns a boolean
+// instead of panicking.
+func (v Val) SymbolOK() (string, bool) {
+ if v.t != bsontype.Symbol {
+ return "", false
+ }
+ return v.string(), true
+}
+
+// CodeWithScope returns the BSON code with scope value the Value represents. It panics if the
+// value is a BSON type other than code with scope.
+func (v Val) CodeWithScope() (string, Doc) {
+ if v.t != bsontype.CodeWithScope {
+ panic(ElementTypeError{"bson.Value.CodeWithScope", v.t})
+ }
+ cws := v.primitive.(primitive.CodeWithScope)
+ return string(cws.Code), cws.Scope.(Doc)
+}
+
+// CodeWithScopeOK is the same as JavascriptWithScope,
+// except that it returns a boolean instead of panicking.
+func (v Val) CodeWithScopeOK() (string, Doc, bool) {
+ if v.t != bsontype.CodeWithScope {
+ return "", nil, false
+ }
+ cws := v.primitive.(primitive.CodeWithScope)
+ return string(cws.Code), cws.Scope.(Doc), true
+}
+
+// Int32 returns the BSON int32 the Value represents. It panics if the value is a BSON type
+// other than int32.
+func (v Val) Int32() int32 {
+ if v.t != bsontype.Int32 {
+ panic(ElementTypeError{"bson.Value.Int32", v.t})
+ }
+ return int32(v.bootstrap[0]) | int32(v.bootstrap[1])<<8 |
+ int32(v.bootstrap[2])<<16 | int32(v.bootstrap[3])<<24
+}
+
+// Int32OK is the same as Int32, except that it returns a boolean instead of
+// panicking.
+func (v Val) Int32OK() (int32, bool) {
+ if v.t != bsontype.Int32 {
+ return 0, false
+ }
+ return int32(v.bootstrap[0]) | int32(v.bootstrap[1])<<8 |
+ int32(v.bootstrap[2])<<16 | int32(v.bootstrap[3])<<24,
+ true
+}
+
+// Timestamp returns the BSON timestamp the Value represents. It panics if the value is a
+// BSON type other than timestamp.
+func (v Val) Timestamp() (t, i uint32) {
+ if v.t != bsontype.Timestamp {
+ panic(ElementTypeError{"bson.Value.Timestamp", v.t})
+ }
+ return uint32(v.bootstrap[4]) | uint32(v.bootstrap[5])<<8 |
+ uint32(v.bootstrap[6])<<16 | uint32(v.bootstrap[7])<<24,
+ uint32(v.bootstrap[0]) | uint32(v.bootstrap[1])<<8 |
+ uint32(v.bootstrap[2])<<16 | uint32(v.bootstrap[3])<<24
+}
+
+// TimestampOK is the same as Timestamp, except that it returns a boolean
+// instead of panicking.
+func (v Val) TimestampOK() (t uint32, i uint32, ok bool) {
+ if v.t != bsontype.Timestamp {
+ return 0, 0, false
+ }
+ return uint32(v.bootstrap[4]) | uint32(v.bootstrap[5])<<8 |
+ uint32(v.bootstrap[6])<<16 | uint32(v.bootstrap[7])<<24,
+ uint32(v.bootstrap[0]) | uint32(v.bootstrap[1])<<8 |
+ uint32(v.bootstrap[2])<<16 | uint32(v.bootstrap[3])<<24,
+ true
+}
+
+// Int64 returns the BSON int64 the Value represents. It panics if the value is a BSON type
+// other than int64.
+func (v Val) Int64() int64 {
+ if v.t != bsontype.Int64 {
+ panic(ElementTypeError{"bson.Value.Int64", v.t})
+ }
+ return v.i64()
+}
+
+// Int64OK is the same as Int64, except that it returns a boolean instead of
+// panicking.
+func (v Val) Int64OK() (int64, bool) {
+ if v.t != bsontype.Int64 {
+ return 0, false
+ }
+ return v.i64(), true
+}
+
+// Decimal128 returns the BSON decimal128 value the Value represents. It panics if the value is a
+// BSON type other than decimal128.
+func (v Val) Decimal128() primitive.Decimal128 {
+ if v.t != bsontype.Decimal128 {
+ panic(ElementTypeError{"bson.Value.Decimal128", v.t})
+ }
+ return v.primitive.(primitive.Decimal128)
+}
+
+// Decimal128OK is the same as Decimal128, except that it returns a boolean
+// instead of panicking.
+func (v Val) Decimal128OK() (primitive.Decimal128, bool) {
+ if v.t != bsontype.Decimal128 {
+ return primitive.Decimal128{}, false
+ }
+ return v.primitive.(primitive.Decimal128), true
+}
+
+// MinKey returns the BSON minkey the Value represents. It panics if the value is a BSON type
+// other than binary.
+func (v Val) MinKey() {
+ if v.t != bsontype.MinKey {
+ panic(ElementTypeError{"bson.Value.MinKey", v.t})
+ }
+ return
+}
+
+// MinKeyOK is the same as MinKey, except it returns a boolean instead of
+// panicking.
+func (v Val) MinKeyOK() bool {
+ if v.t != bsontype.MinKey {
+ return false
+ }
+ return true
+}
+
+// MaxKey returns the BSON maxkey the Value represents. It panics if the value is a BSON type
+// other than binary.
+func (v Val) MaxKey() {
+ if v.t != bsontype.MaxKey {
+ panic(ElementTypeError{"bson.Value.MaxKey", v.t})
+ }
+ return
+}
+
+// MaxKeyOK is the same as MaxKey, except it returns a boolean instead of
+// panicking.
+func (v Val) MaxKeyOK() bool {
+ if v.t != bsontype.MaxKey {
+ return false
+ }
+ return true
+}
+
+// Equal compares v to v2 and returns true if they are equal. Unknown BSON types are
+// never equal. Two empty values are equal.
+func (v Val) Equal(v2 Val) bool {
+ if v.Type() != v2.Type() {
+ return false
+ }
+ if v.IsZero() && v2.IsZero() {
+ return true
+ }
+
+ switch v.Type() {
+ case bsontype.Double, bsontype.DateTime, bsontype.Timestamp, bsontype.Int64:
+ return bytes.Equal(v.bootstrap[0:8], v2.bootstrap[0:8])
+ case bsontype.String:
+ return v.string() == v2.string()
+ case bsontype.EmbeddedDocument:
+ return v.equalDocs(v2)
+ case bsontype.Array:
+ return v.Array().Equal(v2.Array())
+ case bsontype.Binary:
+ return v.primitive.(primitive.Binary).Equal(v2.primitive.(primitive.Binary))
+ case bsontype.Undefined:
+ return true
+ case bsontype.ObjectID:
+ return bytes.Equal(v.bootstrap[0:12], v2.bootstrap[0:12])
+ case bsontype.Boolean:
+ return v.bootstrap[0] == v2.bootstrap[0]
+ case bsontype.Null:
+ return true
+ case bsontype.Regex:
+ return v.primitive.(primitive.Regex).Equal(v2.primitive.(primitive.Regex))
+ case bsontype.DBPointer:
+ return v.primitive.(primitive.DBPointer).Equal(v2.primitive.(primitive.DBPointer))
+ case bsontype.JavaScript:
+ return v.JavaScript() == v2.JavaScript()
+ case bsontype.Symbol:
+ return v.Symbol() == v2.Symbol()
+ case bsontype.CodeWithScope:
+ code1, scope1 := v.primitive.(primitive.CodeWithScope).Code, v.primitive.(primitive.CodeWithScope).Scope
+ code2, scope2 := v2.primitive.(primitive.CodeWithScope).Code, v2.primitive.(primitive.CodeWithScope).Scope
+ return code1 == code2 && v.equalInterfaceDocs(scope1, scope2)
+ case bsontype.Int32:
+ return v.Int32() == v2.Int32()
+ case bsontype.Decimal128:
+ h, l := v.Decimal128().GetBytes()
+ h2, l2 := v2.Decimal128().GetBytes()
+ return h == h2 && l == l2
+ case bsontype.MinKey:
+ return true
+ case bsontype.MaxKey:
+ return true
+ default:
+ return false
+ }
+}
+
+func (v Val) equalDocs(v2 Val) bool {
+ _, ok1 := v.primitive.(MDoc)
+ _, ok2 := v2.primitive.(MDoc)
+ if ok1 || ok2 {
+ return v.asMDoc().Equal(v2.asMDoc())
+ }
+ return v.asDoc().Equal(v2.asDoc())
+}
+
+func (Val) equalInterfaceDocs(i, i2 interface{}) bool {
+ switch d := i.(type) {
+ case MDoc:
+ d2, ok := i2.(IDoc)
+ if !ok {
+ return false
+ }
+ return d.Equal(d2)
+ case Doc:
+ d2, ok := i2.(IDoc)
+ if !ok {
+ return false
+ }
+ return d.Equal(d2)
+ case nil:
+ return i2 == nil
+ default:
+ return false
+ }
+}