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
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/README.md b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/README.md
new file mode 100644
index 0000000..7588f4a
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/README.md
@@ -0,0 +1,11 @@
+MongoDB Go Driver Low-Level Driver Library
+==========================================
+The packages within this library allow users to build applications using a low-level driver
+interface. Knowledge of the internals of a MongoDB driver are assumed, so this library contains
+advanced features. The aim of this library is to provide an easy to use, high performance
+implementation of a low-level driver.
+
+This Library's API is experimental and subject to change. Packages may be changed or removed without
+notice. These APIs are not stable and do not guarantee backward compatibility.
+
+**THIS LIBRARY IS EXPERIMENTAL AND SUBJECT TO CHANGE.**
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/abort_transaction.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/abort_transaction.go
new file mode 100644
index 0000000..4798b05
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/abort_transaction.go
@@ -0,0 +1,71 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// AbortTransaction handles the full cycle dispatch and execution of abortting a transaction
+// against the provided topology.
+func AbortTransaction(
+	ctx context.Context,
+	cmd command.AbortTransaction,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+) (result.TransactionResult, error) {
+	res, err := abortTransaction(ctx, cmd, topo, selector, nil)
+	if cerr, ok := err.(command.Error); ok && err != nil {
+		// Retry if appropriate
+		if cerr.Retryable() {
+			res, err = abortTransaction(ctx, cmd, topo, selector, cerr)
+		}
+	}
+	return res, err
+}
+
+func abortTransaction(
+	ctx context.Context,
+	cmd command.AbortTransaction,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	oldErr error,
+) (result.TransactionResult, error) {
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		// If retrying server selection, return the original error if it fails
+		if oldErr != nil {
+			return result.TransactionResult{}, oldErr
+		}
+		return result.TransactionResult{}, err
+	}
+
+	desc := ss.Description()
+
+	if oldErr != nil && (!topo.SupportsSessions() || !description.SessionsSupported(desc.WireVersion)) {
+		// Assuming we are retrying (oldErr != nil),
+		// if server doesn't support retryable writes, return the original error
+		// Conditions for retry write support are the same as that of sessions
+		return result.TransactionResult{}, oldErr
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		if oldErr != nil {
+			return result.TransactionResult{}, oldErr
+		}
+		return result.TransactionResult{}, err
+	}
+	defer conn.Close()
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/aggregate.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/aggregate.go
new file mode 100644
index 0000000..fd6c949
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/aggregate.go
@@ -0,0 +1,207 @@
+// 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 driver
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// Aggregate handles the full cycle dispatch and execution of an aggregate command against the provided
+// topology.
+func Aggregate(
+	ctx context.Context,
+	cmd command.Aggregate,
+	topo *topology.Topology,
+	readSelector, writeSelector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	registry *bsoncodec.Registry,
+	opts ...*options.AggregateOptions,
+) (*BatchCursor, error) {
+
+	dollarOut := cmd.HasDollarOut()
+
+	var ss *topology.SelectedServer
+	var err error
+	switch dollarOut {
+	case true:
+		ss, err = topo.SelectServer(ctx, writeSelector)
+		if err != nil {
+			return nil, err
+		}
+	case false:
+		ss, err = topo.SelectServer(ctx, readSelector)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	defer conn.Close()
+
+	rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
+	if err != nil {
+		return nil, err
+	}
+	cmd.ReadPref = rp
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	aggOpts := options.MergeAggregateOptions(opts...)
+
+	if aggOpts.AllowDiskUse != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"allowDiskUse", bsonx.Boolean(*aggOpts.AllowDiskUse)})
+	}
+	var batchSize int32
+	if aggOpts.BatchSize != nil {
+		elem := bsonx.Elem{"batchSize", bsonx.Int32(*aggOpts.BatchSize)}
+		cmd.Opts = append(cmd.Opts, elem)
+		cmd.CursorOpts = append(cmd.CursorOpts, elem)
+		batchSize = *aggOpts.BatchSize
+	}
+	if aggOpts.BypassDocumentValidation != nil && desc.WireVersion.Includes(4) {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"bypassDocumentValidation", bsonx.Boolean(*aggOpts.BypassDocumentValidation)})
+	}
+	if aggOpts.Collation != nil {
+		if desc.WireVersion.Max < 5 {
+			return nil, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(aggOpts.Collation.ToDocument())})
+	}
+	if aggOpts.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"maxTimeMS", bsonx.Int64(int64(*aggOpts.MaxTime / time.Millisecond))})
+	}
+	if aggOpts.MaxAwaitTime != nil {
+		// specified as maxTimeMS on getMore commands
+		cmd.CursorOpts = append(cmd.CursorOpts, bsonx.Elem{
+			"maxTimeMS", bsonx.Int64(int64(*aggOpts.MaxAwaitTime / time.Millisecond)),
+		})
+	}
+	if aggOpts.Comment != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"comment", bsonx.String(*aggOpts.Comment)})
+	}
+	if aggOpts.Hint != nil {
+		hintElem, err := interfaceToElement("hint", aggOpts.Hint, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		cmd.Opts = append(cmd.Opts, hintElem)
+	}
+
+	res, err := cmd.RoundTrip(ctx, desc, conn)
+	if err != nil {
+		closeImplicitSession(cmd.Session)
+		return nil, err
+	}
+
+	if desc.WireVersion.Max < 4 {
+		return buildLegacyCommandBatchCursor(res, batchSize, ss.Server)
+	}
+
+	return NewBatchCursor(bsoncore.Document(res), cmd.Session, cmd.Clock, ss.Server, cmd.CursorOpts...)
+}
+
+func buildLegacyCommandBatchCursor(rdr bson.Raw, batchSize int32, server *topology.Server) (*BatchCursor, error) {
+	firstBatchDocs, ns, cursorID, err := getCursorValues(rdr)
+	if err != nil {
+		return nil, err
+	}
+
+	return NewLegacyBatchCursor(ns, cursorID, firstBatchDocs, 0, batchSize, server)
+}
+
+// get the firstBatch, cursor ID, and namespace from a bson.Raw
+//
+// TODO(GODRIVER-617): Change the documents return value into []bsoncore.Document.
+func getCursorValues(result bson.Raw) ([]bson.Raw, command.Namespace, int64, error) {
+	cur, err := result.LookupErr("cursor")
+	if err != nil {
+		return nil, command.Namespace{}, 0, err
+	}
+	if cur.Type != bson.TypeEmbeddedDocument {
+		return nil, command.Namespace{}, 0, fmt.Errorf("cursor should be an embedded document but it is a BSON %s", cur.Type)
+	}
+
+	elems, err := cur.Document().Elements()
+	if err != nil {
+		return nil, command.Namespace{}, 0, err
+	}
+
+	var ok bool
+	var batch []bson.Raw
+	var namespace command.Namespace
+	var cursorID int64
+
+	for _, elem := range elems {
+		switch elem.Key() {
+		case "firstBatch":
+			arr, ok := elem.Value().ArrayOK()
+			if !ok {
+				return nil, command.Namespace{}, 0, fmt.Errorf("firstBatch should be an array but it is a BSON %s", elem.Value().Type)
+			}
+			if err != nil {
+				return nil, command.Namespace{}, 0, err
+			}
+
+			vals, err := arr.Values()
+			if err != nil {
+				return nil, command.Namespace{}, 0, err
+			}
+
+			for _, val := range vals {
+				if val.Type != bsontype.EmbeddedDocument {
+					return nil, command.Namespace{}, 0, fmt.Errorf("element of cursor batch is not a document, but at %s", val.Type)
+				}
+				batch = append(batch, val.Value)
+			}
+		case "ns":
+			if elem.Value().Type != bson.TypeString {
+				return nil, command.Namespace{}, 0, fmt.Errorf("namespace should be a string but it is a BSON %s", elem.Value().Type)
+			}
+			namespace = command.ParseNamespace(elem.Value().StringValue())
+			err = namespace.Validate()
+			if err != nil {
+				return nil, command.Namespace{}, 0, err
+			}
+		case "id":
+			cursorID, ok = elem.Value().Int64OK()
+			if !ok {
+				return nil, command.Namespace{}, 0, fmt.Errorf("id should be an int64 but it is a BSON %s", elem.Value().Type)
+			}
+		}
+	}
+
+	return batch, namespace, cursorID, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/auth.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/auth.go
new file mode 100644
index 0000000..2ea1bfc
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/auth.go
@@ -0,0 +1,169 @@
+// 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 auth
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// AuthenticatorFactory constructs an authenticator.
+type AuthenticatorFactory func(cred *Cred) (Authenticator, error)
+
+var authFactories = make(map[string]AuthenticatorFactory)
+
+func init() {
+	RegisterAuthenticatorFactory("", newDefaultAuthenticator)
+	RegisterAuthenticatorFactory(SCRAMSHA1, newScramSHA1Authenticator)
+	RegisterAuthenticatorFactory(SCRAMSHA256, newScramSHA256Authenticator)
+	RegisterAuthenticatorFactory(MONGODBCR, newMongoDBCRAuthenticator)
+	RegisterAuthenticatorFactory(PLAIN, newPlainAuthenticator)
+	RegisterAuthenticatorFactory(GSSAPI, newGSSAPIAuthenticator)
+	RegisterAuthenticatorFactory(MongoDBX509, newMongoDBX509Authenticator)
+}
+
+// CreateAuthenticator creates an authenticator.
+func CreateAuthenticator(name string, cred *Cred) (Authenticator, error) {
+	if f, ok := authFactories[name]; ok {
+		return f(cred)
+	}
+
+	return nil, newAuthError(fmt.Sprintf("unknown authenticator: %s", name), nil)
+}
+
+// RegisterAuthenticatorFactory registers the authenticator factory.
+func RegisterAuthenticatorFactory(name string, factory AuthenticatorFactory) {
+	authFactories[name] = factory
+}
+
+// // Opener returns a connection opener that will open and authenticate the connection.
+// func Opener(opener conn.Opener, authenticator Authenticator) conn.Opener {
+// 	return func(ctx context.Context, addr model.Addr, opts ...conn.Option) (conn.Connection, error) {
+// 		return NewConnection(ctx, authenticator, opener, addr, opts...)
+// 	}
+// }
+//
+// // NewConnection opens a connection and authenticates it.
+// func NewConnection(ctx context.Context, authenticator Authenticator, opener conn.Opener, addr model.Addr, opts ...conn.Option) (conn.Connection, error) {
+// 	conn, err := opener(ctx, addr, opts...)
+// 	if err != nil {
+// 		if conn != nil {
+// 			// Ignore any error that occurs since we're already returning a different one.
+// 			_ = conn.Close()
+// 		}
+// 		return nil, err
+// 	}
+//
+// 	err = authenticator.Auth(ctx, conn)
+// 	if err != nil {
+// 		// Ignore any error that occurs since we're already returning a different one.
+// 		_ = conn.Close()
+// 		return nil, err
+// 	}
+//
+// 	return conn, nil
+// }
+
+// Configurer creates a connection configurer for the given authenticator.
+//
+// TODO(skriptble): Fully implement this once this package is moved over to the new connection type.
+// func Configurer(configurer connection.Configurer, authenticator Authenticator) connection.Configurer {
+// 	return connection.ConfigurerFunc(func(ctx context.Context, conn connection.Connection) (connection.Connection, error) {
+// 		err := authenticator.Auth(ctx, conn)
+// 		if err != nil {
+// 			conn.Close()
+// 			return nil, err
+// 		}
+// 		if configurer == nil {
+// 			return conn, nil
+// 		}
+// 		return configurer.Configure(ctx, conn)
+// 	})
+// }
+
+// HandshakeOptions packages options that can be passed to the Handshaker()
+// function.  DBUser is optional but must be of the form <dbname.username>;
+// if non-empty, then the connection will do SASL mechanism negotiation.
+type HandshakeOptions struct {
+	AppName       string
+	Authenticator Authenticator
+	Compressors   []string
+	DBUser        string
+}
+
+// Handshaker creates a connection handshaker for the given authenticator.
+func Handshaker(h connection.Handshaker, options *HandshakeOptions) connection.Handshaker {
+	return connection.HandshakerFunc(func(ctx context.Context, addr address.Address, rw wiremessage.ReadWriter) (description.Server, error) {
+		desc, err := (&command.Handshake{
+			Client:             command.ClientDoc(options.AppName),
+			Compressors:        options.Compressors,
+			SaslSupportedMechs: options.DBUser,
+		}).Handshake(ctx, addr, rw)
+
+		if err != nil {
+			return description.Server{}, newAuthError("handshake failure", err)
+		}
+
+		err = options.Authenticator.Auth(ctx, desc, rw)
+		if err != nil {
+			return description.Server{}, newAuthError("auth error", err)
+		}
+		if h == nil {
+			return desc, nil
+		}
+		return h.Handshake(ctx, addr, rw)
+	})
+}
+
+// Authenticator handles authenticating a connection.
+type Authenticator interface {
+	// Auth authenticates the connection.
+	Auth(context.Context, description.Server, wiremessage.ReadWriter) error
+}
+
+func newAuthError(msg string, inner error) error {
+	return &Error{
+		message: msg,
+		inner:   inner,
+	}
+}
+
+func newError(err error, mech string) error {
+	return &Error{
+		message: fmt.Sprintf("unable to authenticate using mechanism \"%s\"", mech),
+		inner:   err,
+	}
+}
+
+// Error is an error that occurred during authentication.
+type Error struct {
+	message string
+	inner   error
+}
+
+func (e *Error) Error() string {
+	if e.inner == nil {
+		return e.message
+	}
+	return fmt.Sprintf("%s: %s", e.message, e.inner)
+}
+
+// Inner returns the wrapped error.
+func (e *Error) Inner() error {
+	return e.inner
+}
+
+// Message returns the message.
+func (e *Error) Message() string {
+	return e.message
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/cred.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/cred.go
new file mode 100644
index 0000000..7b2b8f1
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/cred.go
@@ -0,0 +1,16 @@
+// 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 auth
+
+// Cred is a user's credential.
+type Cred struct {
+	Source      string
+	Username    string
+	Password    string
+	PasswordSet bool
+	Props       map[string]string
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/default.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/default.go
new file mode 100644
index 0000000..52d07e9
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/default.go
@@ -0,0 +1,67 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package auth
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+func newDefaultAuthenticator(cred *Cred) (Authenticator, error) {
+	return &DefaultAuthenticator{
+		Cred: cred,
+	}, nil
+}
+
+// DefaultAuthenticator uses SCRAM-SHA-1 or MONGODB-CR depending
+// on the server version.
+type DefaultAuthenticator struct {
+	Cred *Cred
+}
+
+// Auth authenticates the connection.
+func (a *DefaultAuthenticator) Auth(ctx context.Context, desc description.Server, rw wiremessage.ReadWriter) error {
+	var actual Authenticator
+	var err error
+
+	switch chooseAuthMechanism(desc) {
+	case SCRAMSHA256:
+		actual, err = newScramSHA256Authenticator(a.Cred)
+	case SCRAMSHA1:
+		actual, err = newScramSHA1Authenticator(a.Cred)
+	default:
+		actual, err = newMongoDBCRAuthenticator(a.Cred)
+	}
+
+	if err != nil {
+		return newAuthError("error creating authenticator", err)
+	}
+
+	return actual.Auth(ctx, desc, rw)
+}
+
+// If a server provides a list of supported mechanisms, we choose
+// SCRAM-SHA-256 if it exists or else MUST use SCRAM-SHA-1.
+// Otherwise, we decide based on what is supported.
+func chooseAuthMechanism(desc description.Server) string {
+	if desc.SaslSupportedMechs != nil {
+		for _, v := range desc.SaslSupportedMechs {
+			if v == SCRAMSHA256 {
+				return v
+			}
+		}
+		return SCRAMSHA1
+	}
+
+	if err := description.ScramSHA1Supported(desc.WireVersion); err == nil {
+		return SCRAMSHA1
+	}
+
+	return MONGODBCR
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/doc.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/doc.go
new file mode 100644
index 0000000..9db65cf
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/doc.go
@@ -0,0 +1,23 @@
+// 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 auth is not for public use.
+//
+// The API for packages in the 'private' directory have no stability
+// guarantee.
+//
+// The packages within the 'private' directory would normally be put into an
+// 'internal' directory to prohibit their use outside the 'mongo' directory.
+// However, some MongoDB tools require very low-level access to the building
+// blocks of a driver, so we have placed them under 'private' to allow these
+// packages to be imported by projects that need them.
+//
+// These package APIs may be modified in backwards-incompatible ways at any
+// time.
+//
+// You are strongly discouraged from directly using any packages
+// under 'private'.
+package auth
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi.go
new file mode 100644
index 0000000..f324957
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi.go
@@ -0,0 +1,52 @@
+// 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
+
+//+build gssapi
+//+build windows linux darwin
+
+package auth
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// GSSAPI is the mechanism name for GSSAPI.
+const GSSAPI = "GSSAPI"
+
+func newGSSAPIAuthenticator(cred *Cred) (Authenticator, error) {
+	if cred.Source != "" && cred.Source != "$external" {
+		return nil, newAuthError("GSSAPI source must be empty or $external", nil)
+	}
+
+	return &GSSAPIAuthenticator{
+		Username:    cred.Username,
+		Password:    cred.Password,
+		PasswordSet: cred.PasswordSet,
+		Props:       cred.Props,
+	}, nil
+}
+
+// GSSAPIAuthenticator uses the GSSAPI algorithm over SASL to authenticate a connection.
+type GSSAPIAuthenticator struct {
+	Username    string
+	Password    string
+	PasswordSet bool
+	Props       map[string]string
+}
+
+// Auth authenticates the connection.
+func (a *GSSAPIAuthenticator) Auth(ctx context.Context, desc description.Server, rw wiremessage.ReadWriter) error {
+	client, err := gssapi.New(desc.Addr.String(), a.Username, a.Password, a.PasswordSet, a.Props)
+
+	if err != nil {
+		return newAuthError("error creating gssapi", err)
+	}
+	return ConductSaslConversation(ctx, desc, rw, "$external", client)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi_not_enabled.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi_not_enabled.go
new file mode 100644
index 0000000..d88b764
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi_not_enabled.go
@@ -0,0 +1,16 @@
+// 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
+
+//+build !gssapi
+
+package auth
+
+// GSSAPI is the mechanism name for GSSAPI.
+const GSSAPI = "GSSAPI"
+
+func newGSSAPIAuthenticator(cred *Cred) (Authenticator, error) {
+	return nil, newAuthError("GSSAPI support not enabled during build (-tags gssapi)", nil)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi_not_supported.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi_not_supported.go
new file mode 100644
index 0000000..55caa28
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/gssapi_not_supported.go
@@ -0,0 +1,21 @@
+// 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
+
+//+build gssapi,!windows,!linux,!darwin
+
+package auth
+
+import (
+	"fmt"
+	"runtime"
+)
+
+// GSSAPI is the mechanism name for GSSAPI.
+const GSSAPI = "GSSAPI"
+
+func newGSSAPIAuthenticator(cred *Cred) (Authenticator, error) {
+	return nil, newAuthError(fmt.Sprintf("GSSAPI is not supported on %s", runtime.GOOS), nil)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss.go
new file mode 100644
index 0000000..366ab7b
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss.go
@@ -0,0 +1,168 @@
+// 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
+
+//+build gssapi
+//+build linux darwin
+
+package gssapi
+
+/*
+#cgo linux CFLAGS: -DGOOS_linux
+#cgo linux LDFLAGS: -lgssapi_krb5 -lkrb5
+#cgo darwin CFLAGS: -DGOOS_darwin
+#cgo darwin LDFLAGS: -framework GSS
+#include "gss_wrapper.h"
+*/
+import "C"
+import (
+	"fmt"
+	"net"
+	"runtime"
+	"strings"
+	"unsafe"
+)
+
+// New creates a new SaslClient.
+func New(target, username, password string, passwordSet bool, props map[string]string) (*SaslClient, error) {
+	serviceName := "mongodb"
+
+	for key, value := range props {
+		switch strings.ToUpper(key) {
+		case "CANONICALIZE_HOST_NAME":
+			return nil, fmt.Errorf("CANONICALIZE_HOST_NAME is not supported when using gssapi on %s", runtime.GOOS)
+		case "SERVICE_REALM":
+			return nil, fmt.Errorf("SERVICE_REALM is not supported when using gssapi on %s", runtime.GOOS)
+		case "SERVICE_NAME":
+			serviceName = value
+		default:
+			return nil, fmt.Errorf("unknown mechanism property %s", key)
+		}
+	}
+
+	hostname, _, err := net.SplitHostPort(target)
+	if err != nil {
+		return nil, fmt.Errorf("invalid endpoint (%s) specified: %s", target, err)
+	}
+
+	servicePrincipalName := fmt.Sprintf("%s@%s", serviceName, hostname)
+
+	return &SaslClient{
+		servicePrincipalName: servicePrincipalName,
+		username:             username,
+		password:             password,
+		passwordSet:          passwordSet,
+	}, nil
+}
+
+type SaslClient struct {
+	servicePrincipalName string
+	username             string
+	password             string
+	passwordSet          bool
+
+	// state
+	state           C.gssapi_client_state
+	contextComplete bool
+	done            bool
+}
+
+func (sc *SaslClient) Close() {
+	C.gssapi_client_destroy(&sc.state)
+}
+
+func (sc *SaslClient) Start() (string, []byte, error) {
+	const mechName = "GSSAPI"
+
+	cservicePrincipalName := C.CString(sc.servicePrincipalName)
+	defer C.free(unsafe.Pointer(cservicePrincipalName))
+	var cusername *C.char
+	var cpassword *C.char
+	if sc.username != "" {
+		cusername = C.CString(sc.username)
+		defer C.free(unsafe.Pointer(cusername))
+		if sc.passwordSet {
+			cpassword = C.CString(sc.password)
+			defer C.free(unsafe.Pointer(cpassword))
+		}
+	}
+	status := C.gssapi_client_init(&sc.state, cservicePrincipalName, cusername, cpassword)
+
+	if status != C.GSSAPI_OK {
+		return mechName, nil, sc.getError("unable to initialize client")
+	}
+
+	return mechName, nil, nil
+}
+
+func (sc *SaslClient) Next(challenge []byte) ([]byte, error) {
+
+	var buf unsafe.Pointer
+	var bufLen C.size_t
+	var outBuf unsafe.Pointer
+	var outBufLen C.size_t
+
+	if sc.contextComplete {
+		if sc.username == "" {
+			var cusername *C.char
+			status := C.gssapi_client_username(&sc.state, &cusername)
+			if status != C.GSSAPI_OK {
+				return nil, sc.getError("unable to acquire username")
+			}
+			defer C.free(unsafe.Pointer(cusername))
+			sc.username = C.GoString((*C.char)(unsafe.Pointer(cusername)))
+		}
+
+		bytes := append([]byte{1, 0, 0, 0}, []byte(sc.username)...)
+		buf = unsafe.Pointer(&bytes[0])
+		bufLen = C.size_t(len(bytes))
+		status := C.gssapi_client_wrap_msg(&sc.state, buf, bufLen, &outBuf, &outBufLen)
+		if status != C.GSSAPI_OK {
+			return nil, sc.getError("unable to wrap authz")
+		}
+
+		sc.done = true
+	} else {
+		if len(challenge) > 0 {
+			buf = unsafe.Pointer(&challenge[0])
+			bufLen = C.size_t(len(challenge))
+		}
+
+		status := C.gssapi_client_negotiate(&sc.state, buf, bufLen, &outBuf, &outBufLen)
+		switch status {
+		case C.GSSAPI_OK:
+			sc.contextComplete = true
+		case C.GSSAPI_CONTINUE:
+		default:
+			return nil, sc.getError("unable to negotiate with server")
+		}
+	}
+
+	if outBuf != nil {
+		defer C.free(outBuf)
+	}
+
+	return C.GoBytes(outBuf, C.int(outBufLen)), nil
+}
+
+func (sc *SaslClient) Completed() bool {
+	return sc.done
+}
+
+func (sc *SaslClient) getError(prefix string) error {
+	var desc *C.char
+
+	status := C.gssapi_error_desc(sc.state.maj_stat, sc.state.min_stat, &desc)
+	if status != C.GSSAPI_OK {
+		if desc != nil {
+			C.free(unsafe.Pointer(desc))
+		}
+
+		return fmt.Errorf("%s: (%v, %v)", prefix, sc.state.maj_stat, sc.state.min_stat)
+	}
+	defer C.free(unsafe.Pointer(desc))
+
+	return fmt.Errorf("%s: %v(%v,%v)", prefix, C.GoString(desc), int32(sc.state.maj_stat), int32(sc.state.min_stat))
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.c b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.c
new file mode 100644
index 0000000..0ca591f
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.c
@@ -0,0 +1,248 @@
+//+build gssapi
+//+build linux darwin
+
+#include <string.h>
+#include <stdio.h>
+#include "gss_wrapper.h"
+
+OM_uint32 gssapi_canonicalize_name(
+    OM_uint32* minor_status, 
+    char *input_name, 
+    gss_OID input_name_type, 
+    gss_name_t *output_name
+)
+{
+    OM_uint32 major_status;
+    gss_name_t imported_name = GSS_C_NO_NAME;
+    gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER;
+
+    buffer.value = input_name;
+    buffer.length = strlen(input_name);
+    major_status = gss_import_name(minor_status, &buffer, input_name_type, &imported_name);
+    if (GSS_ERROR(major_status)) {
+        return major_status;
+    }
+
+    major_status = gss_canonicalize_name(minor_status, imported_name, (gss_OID)gss_mech_krb5, output_name);
+    if (imported_name != GSS_C_NO_NAME) {
+        OM_uint32 ignored;
+        gss_release_name(&ignored, &imported_name);
+    }
+
+    return major_status;
+}
+
+int gssapi_error_desc(
+    OM_uint32 maj_stat, 
+    OM_uint32 min_stat, 
+    char **desc
+)
+{
+    OM_uint32 stat = maj_stat;
+    int stat_type = GSS_C_GSS_CODE;
+    if (min_stat != 0) {
+        stat = min_stat;
+        stat_type = GSS_C_MECH_CODE;
+    }
+
+    OM_uint32 local_maj_stat, local_min_stat;
+    OM_uint32 msg_ctx = 0;
+    gss_buffer_desc desc_buffer;
+    do
+    {
+        local_maj_stat = gss_display_status(
+            &local_min_stat,
+            stat,
+            stat_type,
+            GSS_C_NO_OID,
+            &msg_ctx,
+            &desc_buffer
+        );
+        if (GSS_ERROR(local_maj_stat)) {
+            return GSSAPI_ERROR;
+        }
+
+        if (*desc) {
+            free(*desc);
+        }
+
+        *desc = malloc(desc_buffer.length+1);
+        memcpy(*desc, desc_buffer.value, desc_buffer.length+1);
+
+        gss_release_buffer(&local_min_stat, &desc_buffer);
+    }
+    while(msg_ctx != 0);
+
+    return GSSAPI_OK;
+}
+
+int gssapi_client_init(
+    gssapi_client_state *client,
+    char* spn,
+    char* username,
+    char* password
+)
+{
+    client->cred = GSS_C_NO_CREDENTIAL;
+    client->ctx = GSS_C_NO_CONTEXT;
+
+    client->maj_stat = gssapi_canonicalize_name(&client->min_stat, spn, GSS_C_NT_HOSTBASED_SERVICE, &client->spn);
+    if (GSS_ERROR(client->maj_stat)) {
+        return GSSAPI_ERROR;
+    }
+
+    if (username) {
+        gss_name_t name;
+        client->maj_stat = gssapi_canonicalize_name(&client->min_stat, username, GSS_C_NT_USER_NAME, &name);
+        if (GSS_ERROR(client->maj_stat)) {
+            return GSSAPI_ERROR;
+        }
+
+        if (password) {
+            gss_buffer_desc password_buffer;
+            password_buffer.value = password;
+            password_buffer.length = strlen(password);
+            client->maj_stat = gss_acquire_cred_with_password(&client->min_stat, name, &password_buffer, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client->cred, NULL, NULL);
+        } else {
+            client->maj_stat = gss_acquire_cred(&client->min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client->cred, NULL, NULL);
+        }
+
+        if (GSS_ERROR(client->maj_stat)) {
+            return GSSAPI_ERROR;
+        }
+
+        OM_uint32 ignored;
+        gss_release_name(&ignored, &name);
+    }
+
+    return GSSAPI_OK;
+}
+
+int gssapi_client_username(
+    gssapi_client_state *client,
+    char** username
+)
+{
+    OM_uint32 ignored;
+    gss_name_t name = GSS_C_NO_NAME;
+
+    client->maj_stat = gss_inquire_context(&client->min_stat, client->ctx, &name, NULL, NULL, NULL, NULL, NULL, NULL);
+    if (GSS_ERROR(client->maj_stat)) {
+        return GSSAPI_ERROR;
+    }
+
+    gss_buffer_desc name_buffer;
+    client->maj_stat = gss_display_name(&client->min_stat, name, &name_buffer, NULL);
+    if (GSS_ERROR(client->maj_stat)) {
+        gss_release_name(&ignored, &name);
+        return GSSAPI_ERROR;
+    }
+
+	*username = malloc(name_buffer.length+1);
+	memcpy(*username, name_buffer.value, name_buffer.length+1);
+
+    gss_release_buffer(&ignored, &name_buffer);
+    gss_release_name(&ignored, &name);
+    return GSSAPI_OK;
+}
+
+int gssapi_client_negotiate(
+    gssapi_client_state *client,
+    void* input,
+    size_t input_length,
+    void** output,
+    size_t* output_length
+)
+{
+    gss_buffer_desc input_buffer = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc output_buffer = GSS_C_EMPTY_BUFFER;
+
+    if (input) {
+        input_buffer.value = input;
+        input_buffer.length = input_length;
+    }
+
+    client->maj_stat = gss_init_sec_context(
+        &client->min_stat,
+        client->cred,
+        &client->ctx,
+        client->spn,
+        GSS_C_NO_OID,
+        GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
+        0,
+        GSS_C_NO_CHANNEL_BINDINGS,
+        &input_buffer,
+        NULL,
+        &output_buffer,
+        NULL,
+        NULL
+    );
+
+    if (output_buffer.length) {
+        *output = malloc(output_buffer.length);
+        *output_length = output_buffer.length;
+        memcpy(*output, output_buffer.value, output_buffer.length);
+
+        OM_uint32 ignored;
+        gss_release_buffer(&ignored, &output_buffer);
+    }
+
+    if (GSS_ERROR(client->maj_stat)) {
+        return GSSAPI_ERROR;
+    } else if (client->maj_stat == GSS_S_CONTINUE_NEEDED) {
+        return GSSAPI_CONTINUE;
+    }
+
+    return GSSAPI_OK;
+}
+
+int gssapi_client_wrap_msg(
+    gssapi_client_state *client,
+    void* input,
+    size_t input_length,
+    void** output,
+    size_t* output_length 
+)
+{
+    gss_buffer_desc input_buffer = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc output_buffer = GSS_C_EMPTY_BUFFER;
+
+    input_buffer.value = input;
+    input_buffer.length = input_length;
+
+    client->maj_stat = gss_wrap(&client->min_stat, client->ctx, 0, GSS_C_QOP_DEFAULT, &input_buffer, NULL, &output_buffer);
+
+    if (output_buffer.length) {
+        *output = malloc(output_buffer.length);
+        *output_length = output_buffer.length;
+        memcpy(*output, output_buffer.value, output_buffer.length);
+
+        gss_release_buffer(&client->min_stat, &output_buffer);
+    }
+
+    if (GSS_ERROR(client->maj_stat)) {
+        return GSSAPI_ERROR;
+    }
+
+    return GSSAPI_OK;
+}
+
+int gssapi_client_destroy(
+    gssapi_client_state *client
+)
+{
+    OM_uint32 ignored;
+    if (client->ctx != GSS_C_NO_CONTEXT) {
+        gss_delete_sec_context(&ignored, &client->ctx, GSS_C_NO_BUFFER);
+    }
+
+    if (client->spn != GSS_C_NO_NAME) {
+        gss_release_name(&ignored, &client->spn);
+    }
+
+    if (client->cred != GSS_C_NO_CREDENTIAL) {
+        gss_release_cred(&ignored, &client->cred);
+    }
+
+    return GSSAPI_OK;
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.h b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.h
new file mode 100644
index 0000000..ca7b907
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/gss_wrapper.h
@@ -0,0 +1,66 @@
+//+build gssapi
+//+build linux darwin
+#ifndef GSS_WRAPPER_H
+#define GSS_WRAPPER_H
+
+#include <stdlib.h>
+#ifdef GOOS_linux
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#endif
+#ifdef GOOS_darwin
+#include <GSS/GSS.h>
+#endif
+
+#define GSSAPI_OK 0
+#define GSSAPI_CONTINUE 1
+#define GSSAPI_ERROR 2
+
+typedef struct {
+    gss_name_t spn;
+    gss_cred_id_t cred;
+    gss_ctx_id_t ctx;
+
+    OM_uint32 maj_stat;
+    OM_uint32 min_stat;
+} gssapi_client_state;
+
+int gssapi_error_desc(
+    OM_uint32 maj_stat, 
+    OM_uint32 min_stat, 
+    char **desc
+);
+
+int gssapi_client_init(
+    gssapi_client_state *client,
+    char* spn,
+    char* username,
+    char* password
+);
+
+int gssapi_client_username(
+    gssapi_client_state *client,
+    char** username
+);
+
+int gssapi_client_negotiate(
+    gssapi_client_state *client,
+    void* input,
+    size_t input_length,
+    void** output,
+    size_t* output_length
+);
+
+int gssapi_client_wrap_msg(
+    gssapi_client_state *client,
+    void* input,
+    size_t input_length,
+    void** output,
+    size_t* output_length 
+);
+
+int gssapi_client_destroy(
+    gssapi_client_state *client
+);
+
+#endif
\ No newline at end of file
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi.go
new file mode 100644
index 0000000..dd547f3
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi.go
@@ -0,0 +1,345 @@
+// 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
+
+//+build gssapi,windows
+
+package gssapi
+
+// #include "sspi_wrapper.h"
+import "C"
+import (
+	"fmt"
+	"net"
+	"strconv"
+	"strings"
+	"sync"
+	"unsafe"
+)
+
+// New creates a new SaslClient.
+func New(target, username, password string, passwordSet bool, props map[string]string) (*SaslClient, error) {
+	initOnce.Do(initSSPI)
+	if initError != nil {
+		return nil, initError
+	}
+
+	var err error
+	serviceName := "mongodb"
+	serviceRealm := ""
+	canonicalizeHostName := false
+
+	for key, value := range props {
+		switch strings.ToUpper(key) {
+		case "CANONICALIZE_HOST_NAME":
+			canonicalizeHostName, err = strconv.ParseBool(value)
+			if err != nil {
+				return nil, fmt.Errorf("%s must be a boolean (true, false, 0, 1) but got '%s'", key, value)
+			}
+
+		case "SERVICE_REALM":
+			serviceRealm = value
+		case "SERVICE_NAME":
+			serviceName = value
+		}
+	}
+
+	hostname, _, err := net.SplitHostPort(target)
+	if err != nil {
+		return nil, fmt.Errorf("invalid endpoint (%s) specified: %s", target, err)
+	}
+	if canonicalizeHostName {
+		names, err := net.LookupAddr(hostname)
+		if err != nil || len(names) == 0 {
+			return nil, fmt.Errorf("unable to canonicalize hostname: %s", err)
+		}
+		hostname = names[0]
+		if hostname[len(hostname)-1] == '.' {
+			hostname = hostname[:len(hostname)-1]
+		}
+	}
+
+	servicePrincipalName := fmt.Sprintf("%s/%s", serviceName, hostname)
+	if serviceRealm != "" {
+		servicePrincipalName += "@" + serviceRealm
+	}
+
+	return &SaslClient{
+		servicePrincipalName: servicePrincipalName,
+		username:             username,
+		password:             password,
+		passwordSet:          passwordSet,
+	}, nil
+}
+
+type SaslClient struct {
+	servicePrincipalName string
+	username             string
+	password             string
+	passwordSet          bool
+
+	// state
+	state           C.sspi_client_state
+	contextComplete bool
+	done            bool
+}
+
+func (sc *SaslClient) Close() {
+	C.sspi_client_destroy(&sc.state)
+}
+
+func (sc *SaslClient) Start() (string, []byte, error) {
+	const mechName = "GSSAPI"
+
+	var cusername *C.char
+	var cpassword *C.char
+	if sc.username != "" {
+		cusername = C.CString(sc.username)
+		defer C.free(unsafe.Pointer(cusername))
+		if sc.passwordSet {
+			cpassword = C.CString(sc.password)
+			defer C.free(unsafe.Pointer(cpassword))
+		}
+	}
+	status := C.sspi_client_init(&sc.state, cusername, cpassword)
+
+	if status != C.SSPI_OK {
+		return mechName, nil, sc.getError("unable to intitialize client")
+	}
+
+	return mechName, nil, nil
+}
+
+func (sc *SaslClient) Next(challenge []byte) ([]byte, error) {
+
+	var outBuf C.PVOID
+	var outBufLen C.ULONG
+
+	if sc.contextComplete {
+		if sc.username == "" {
+			var cusername *C.char
+			status := C.sspi_client_username(&sc.state, &cusername)
+			if status != C.SSPI_OK {
+				return nil, sc.getError("unable to acquire username")
+			}
+			defer C.free(unsafe.Pointer(cusername))
+			sc.username = C.GoString((*C.char)(unsafe.Pointer(cusername)))
+		}
+
+		bytes := append([]byte{1, 0, 0, 0}, []byte(sc.username)...)
+		buf := (C.PVOID)(unsafe.Pointer(&bytes[0]))
+		bufLen := C.ULONG(len(bytes))
+		status := C.sspi_client_wrap_msg(&sc.state, buf, bufLen, &outBuf, &outBufLen)
+		if status != C.SSPI_OK {
+			return nil, sc.getError("unable to wrap authz")
+		}
+
+		sc.done = true
+	} else {
+		var buf C.PVOID
+		var bufLen C.ULONG
+		if len(challenge) > 0 {
+			buf = (C.PVOID)(unsafe.Pointer(&challenge[0]))
+			bufLen = C.ULONG(len(challenge))
+		}
+		cservicePrincipalName := C.CString(sc.servicePrincipalName)
+		defer C.free(unsafe.Pointer(cservicePrincipalName))
+
+		status := C.sspi_client_negotiate(&sc.state, cservicePrincipalName, buf, bufLen, &outBuf, &outBufLen)
+		switch status {
+		case C.SSPI_OK:
+			sc.contextComplete = true
+		case C.SSPI_CONTINUE:
+		default:
+			return nil, sc.getError("unable to negotiate with server")
+		}
+	}
+
+	if outBuf != C.PVOID(nil) {
+		defer C.free(unsafe.Pointer(outBuf))
+	}
+
+	return C.GoBytes(unsafe.Pointer(outBuf), C.int(outBufLen)), nil
+}
+
+func (sc *SaslClient) Completed() bool {
+	return sc.done
+}
+
+func (sc *SaslClient) getError(prefix string) error {
+	return getError(prefix, sc.state.status)
+}
+
+var initOnce sync.Once
+var initError error
+
+func initSSPI() {
+	rc := C.sspi_init()
+	if rc != 0 {
+		initError = fmt.Errorf("error initializing sspi: %v", rc)
+	}
+}
+
+func getError(prefix string, status C.SECURITY_STATUS) error {
+	var s string
+	switch status {
+	case C.SEC_E_ALGORITHM_MISMATCH:
+		s = "The client and server cannot communicate because they do not possess a common algorithm."
+	case C.SEC_E_BAD_BINDINGS:
+		s = "The SSPI channel bindings supplied by the client are incorrect."
+	case C.SEC_E_BAD_PKGID:
+		s = "The requested package identifier does not exist."
+	case C.SEC_E_BUFFER_TOO_SMALL:
+		s = "The buffers supplied to the function are not large enough to contain the information."
+	case C.SEC_E_CANNOT_INSTALL:
+		s = "The security package cannot initialize successfully and should not be installed."
+	case C.SEC_E_CANNOT_PACK:
+		s = "The package is unable to pack the context."
+	case C.SEC_E_CERT_EXPIRED:
+		s = "The received certificate has expired."
+	case C.SEC_E_CERT_UNKNOWN:
+		s = "An unknown error occurred while processing the certificate."
+	case C.SEC_E_CERT_WRONG_USAGE:
+		s = "The certificate is not valid for the requested usage."
+	case C.SEC_E_CONTEXT_EXPIRED:
+		s = "The application is referencing a context that has already been closed. A properly written application should not receive this error."
+	case C.SEC_E_CROSSREALM_DELEGATION_FAILURE:
+		s = "The server attempted to make a Kerberos-constrained delegation request for a target outside the server's realm."
+	case C.SEC_E_CRYPTO_SYSTEM_INVALID:
+		s = "The cryptographic system or checksum function is not valid because a required function is unavailable."
+	case C.SEC_E_DECRYPT_FAILURE:
+		s = "The specified data could not be decrypted."
+	case C.SEC_E_DELEGATION_REQUIRED:
+		s = "The requested operation cannot be completed. The computer must be trusted for delegation"
+	case C.SEC_E_DOWNGRADE_DETECTED:
+		s = "The system detected a possible attempt to compromise security. Verify that the server that authenticated you can be contacted."
+	case C.SEC_E_ENCRYPT_FAILURE:
+		s = "The specified data could not be encrypted."
+	case C.SEC_E_ILLEGAL_MESSAGE:
+		s = "The message received was unexpected or badly formatted."
+	case C.SEC_E_INCOMPLETE_CREDENTIALS:
+		s = "The credentials supplied were not complete and could not be verified. The context could not be initialized."
+	case C.SEC_E_INCOMPLETE_MESSAGE:
+		s = "The message supplied was incomplete. The signature was not verified."
+	case C.SEC_E_INSUFFICIENT_MEMORY:
+		s = "Not enough memory is available to complete the request."
+	case C.SEC_E_INTERNAL_ERROR:
+		s = "An error occurred that did not map to an SSPI error code."
+	case C.SEC_E_INVALID_HANDLE:
+		s = "The handle passed to the function is not valid."
+	case C.SEC_E_INVALID_TOKEN:
+		s = "The token passed to the function is not valid."
+	case C.SEC_E_ISSUING_CA_UNTRUSTED:
+		s = "An untrusted certification authority (CA) was detected while processing the smart card certificate used for authentication."
+	case C.SEC_E_ISSUING_CA_UNTRUSTED_KDC:
+		s = "An untrusted CA was detected while processing the domain controller certificate used for authentication. The system event log contains additional information."
+	case C.SEC_E_KDC_CERT_EXPIRED:
+		s = "The domain controller certificate used for smart card logon has expired."
+	case C.SEC_E_KDC_CERT_REVOKED:
+		s = "The domain controller certificate used for smart card logon has been revoked."
+	case C.SEC_E_KDC_INVALID_REQUEST:
+		s = "A request that is not valid was sent to the KDC."
+	case C.SEC_E_KDC_UNABLE_TO_REFER:
+		s = "The KDC was unable to generate a referral for the service requested."
+	case C.SEC_E_KDC_UNKNOWN_ETYPE:
+		s = "The requested encryption type is not supported by the KDC."
+	case C.SEC_E_LOGON_DENIED:
+		s = "The logon has been denied"
+	case C.SEC_E_MAX_REFERRALS_EXCEEDED:
+		s = "The number of maximum ticket referrals has been exceeded."
+	case C.SEC_E_MESSAGE_ALTERED:
+		s = "The message supplied for verification has been altered."
+	case C.SEC_E_MULTIPLE_ACCOUNTS:
+		s = "The received certificate was mapped to multiple accounts."
+	case C.SEC_E_MUST_BE_KDC:
+		s = "The local computer must be a Kerberos domain controller (KDC)"
+	case C.SEC_E_NO_AUTHENTICATING_AUTHORITY:
+		s = "No authority could be contacted for authentication."
+	case C.SEC_E_NO_CREDENTIALS:
+		s = "No credentials are available."
+	case C.SEC_E_NO_IMPERSONATION:
+		s = "No impersonation is allowed for this context."
+	case C.SEC_E_NO_IP_ADDRESSES:
+		s = "Unable to accomplish the requested task because the local computer does not have any IP addresses."
+	case C.SEC_E_NO_KERB_KEY:
+		s = "No Kerberos key was found."
+	case C.SEC_E_NO_PA_DATA:
+		s = "Policy administrator (PA) data is needed to determine the encryption type"
+	case C.SEC_E_NO_S4U_PROT_SUPPORT:
+		s = "The Kerberos subsystem encountered an error. A service for user protocol request was made against a domain controller which does not support service for a user."
+	case C.SEC_E_NO_TGT_REPLY:
+		s = "The client is trying to negotiate a context and the server requires a user-to-user connection"
+	case C.SEC_E_NOT_OWNER:
+		s = "The caller of the function does not own the credentials."
+	case C.SEC_E_OK:
+		s = "The operation completed successfully."
+	case C.SEC_E_OUT_OF_SEQUENCE:
+		s = "The message supplied for verification is out of sequence."
+	case C.SEC_E_PKINIT_CLIENT_FAILURE:
+		s = "The smart card certificate used for authentication is not trusted."
+	case C.SEC_E_PKINIT_NAME_MISMATCH:
+		s = "The client certificate does not contain a valid UPN or does not match the client name in the logon request."
+	case C.SEC_E_QOP_NOT_SUPPORTED:
+		s = "The quality of protection attribute is not supported by this package."
+	case C.SEC_E_REVOCATION_OFFLINE_C:
+		s = "The revocation status of the smart card certificate used for authentication could not be determined."
+	case C.SEC_E_REVOCATION_OFFLINE_KDC:
+		s = "The revocation status of the domain controller certificate used for smart card authentication could not be determined. The system event log contains additional information."
+	case C.SEC_E_SECPKG_NOT_FOUND:
+		s = "The security package was not recognized."
+	case C.SEC_E_SECURITY_QOS_FAILED:
+		s = "The security context could not be established due to a failure in the requested quality of service (for example"
+	case C.SEC_E_SHUTDOWN_IN_PROGRESS:
+		s = "A system shutdown is in progress."
+	case C.SEC_E_SMARTCARD_CERT_EXPIRED:
+		s = "The smart card certificate used for authentication has expired."
+	case C.SEC_E_SMARTCARD_CERT_REVOKED:
+		s = "The smart card certificate used for authentication has been revoked. Additional information may exist in the event log."
+	case C.SEC_E_SMARTCARD_LOGON_REQUIRED:
+		s = "Smart card logon is required and was not used."
+	case C.SEC_E_STRONG_CRYPTO_NOT_SUPPORTED:
+		s = "The other end of the security negotiation requires strong cryptography"
+	case C.SEC_E_TARGET_UNKNOWN:
+		s = "The target was not recognized."
+	case C.SEC_E_TIME_SKEW:
+		s = "The clocks on the client and server computers do not match."
+	case C.SEC_E_TOO_MANY_PRINCIPALS:
+		s = "The KDC reply contained more than one principal name."
+	case C.SEC_E_UNFINISHED_CONTEXT_DELETED:
+		s = "A security context was deleted before the context was completed. This is considered a logon failure."
+	case C.SEC_E_UNKNOWN_CREDENTIALS:
+		s = "The credentials provided were not recognized."
+	case C.SEC_E_UNSUPPORTED_FUNCTION:
+		s = "The requested function is not supported."
+	case C.SEC_E_UNSUPPORTED_PREAUTH:
+		s = "An unsupported preauthentication mechanism was presented to the Kerberos package."
+	case C.SEC_E_UNTRUSTED_ROOT:
+		s = "The certificate chain was issued by an authority that is not trusted."
+	case C.SEC_E_WRONG_CREDENTIAL_HANDLE:
+		s = "The supplied credential handle does not match the credential associated with the security context."
+	case C.SEC_E_WRONG_PRINCIPAL:
+		s = "The target principal name is incorrect."
+	case C.SEC_I_COMPLETE_AND_CONTINUE:
+		s = "The function completed successfully"
+	case C.SEC_I_COMPLETE_NEEDED:
+		s = "The function completed successfully"
+	case C.SEC_I_CONTEXT_EXPIRED:
+		s = "The message sender has finished using the connection and has initiated a shutdown. For information about initiating or recognizing a shutdown"
+	case C.SEC_I_CONTINUE_NEEDED:
+		s = "The function completed successfully"
+	case C.SEC_I_INCOMPLETE_CREDENTIALS:
+		s = "The credentials supplied were not complete and could not be verified. Additional information can be returned from the context."
+	case C.SEC_I_LOCAL_LOGON:
+		s = "The logon was completed"
+	case C.SEC_I_NO_LSA_CONTEXT:
+		s = "There is no LSA mode context associated with this context."
+	case C.SEC_I_RENEGOTIATE:
+		s = "The context data must be renegotiated with the peer."
+	default:
+		return fmt.Errorf("%s: 0x%x", prefix, uint32(status))
+	}
+
+	return fmt.Errorf("%s: %s(0x%x)", prefix, s, uint32(status))
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.c b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.c
new file mode 100644
index 0000000..9d218bd
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.c
@@ -0,0 +1,218 @@
+//+build gssapi,windows
+
+#include "sspi_wrapper.h"
+
+static HINSTANCE sspi_secur32_dll = NULL;
+static PSecurityFunctionTable sspi_functions = NULL;
+static const LPSTR SSPI_PACKAGE_NAME = "kerberos";
+
+int sspi_init(
+)
+{
+	sspi_secur32_dll = LoadLibrary("secur32.dll");
+	if (!sspi_secur32_dll) {
+		return GetLastError();
+	}
+
+    INIT_SECURITY_INTERFACE init_security_interface = (INIT_SECURITY_INTERFACE)GetProcAddress(sspi_secur32_dll, SECURITY_ENTRYPOINT);
+    if (!init_security_interface) {
+        return -1;
+    }
+
+    sspi_functions = (*init_security_interface)();
+    if (!sspi_functions) {
+        return -2;
+    }
+
+	return SSPI_OK;
+}
+
+int sspi_client_init(
+    sspi_client_state *client,
+    char* username,
+    char* password
+)
+{
+	TimeStamp timestamp;
+
+    if (username) {
+        if (password) {
+            SEC_WINNT_AUTH_IDENTITY auth_identity;
+            
+        #ifdef _UNICODE
+            auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+        #else
+            auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
+        #endif
+            auth_identity.User = (LPSTR) username;
+            auth_identity.UserLength = strlen(username);
+            auth_identity.Password = (LPSTR) password;
+            auth_identity.PasswordLength = strlen(password);
+            auth_identity.Domain = NULL;
+            auth_identity.DomainLength = 0;
+            client->status = sspi_functions->AcquireCredentialsHandle(NULL, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &auth_identity, NULL, NULL, &client->cred, &timestamp);
+        } else {
+            client->status = sspi_functions->AcquireCredentialsHandle(username, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &client->cred, &timestamp);
+        }
+    } else {
+        client->status = sspi_functions->AcquireCredentialsHandle(NULL, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &client->cred, &timestamp);
+    }
+
+    if (client->status != SEC_E_OK) {
+        return SSPI_ERROR;
+    }
+
+    return SSPI_OK;
+}
+
+int sspi_client_username(
+    sspi_client_state *client,
+    char** username
+)
+{
+    SecPkgCredentials_Names names;
+	client->status = sspi_functions->QueryCredentialsAttributes(&client->cred, SECPKG_CRED_ATTR_NAMES, &names);
+
+	if (client->status != SEC_E_OK) {
+		return SSPI_ERROR;
+	}
+
+	int len = strlen(names.sUserName) + 1;
+	*username = malloc(len);
+	memcpy(*username, names.sUserName, len);
+
+	sspi_functions->FreeContextBuffer(names.sUserName);
+
+    return SSPI_OK;
+}
+
+int sspi_client_negotiate(
+    sspi_client_state *client,
+    char* spn,
+    PVOID input,
+    ULONG input_length,
+    PVOID* output,
+    ULONG* output_length
+)
+{
+    SecBufferDesc inbuf;
+	SecBuffer in_bufs[1];
+	SecBufferDesc outbuf;
+	SecBuffer out_bufs[1];
+
+	if (client->has_ctx > 0) {
+		inbuf.ulVersion = SECBUFFER_VERSION;
+		inbuf.cBuffers = 1;
+		inbuf.pBuffers = in_bufs;
+		in_bufs[0].pvBuffer = input;
+		in_bufs[0].cbBuffer = input_length;
+		in_bufs[0].BufferType = SECBUFFER_TOKEN;
+	}
+
+	outbuf.ulVersion = SECBUFFER_VERSION;
+	outbuf.cBuffers = 1;
+	outbuf.pBuffers = out_bufs;
+	out_bufs[0].pvBuffer = NULL;
+	out_bufs[0].cbBuffer = 0;
+	out_bufs[0].BufferType = SECBUFFER_TOKEN;
+
+	ULONG context_attr = 0;
+
+	client->status = sspi_functions->InitializeSecurityContext(
+        &client->cred,
+        client->has_ctx > 0 ? &client->ctx : NULL,
+        (LPSTR) spn,
+        ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MUTUAL_AUTH,
+        0,
+        SECURITY_NETWORK_DREP,
+        client->has_ctx > 0 ? &inbuf : NULL,
+        0,
+        &client->ctx,
+        &outbuf,
+        &context_attr,
+        NULL);
+
+    if (client->status != SEC_E_OK && client->status != SEC_I_CONTINUE_NEEDED) {
+        return SSPI_ERROR;
+    }
+
+    client->has_ctx = 1;
+
+	*output = malloc(out_bufs[0].cbBuffer);
+	*output_length = out_bufs[0].cbBuffer;
+	memcpy(*output, out_bufs[0].pvBuffer, *output_length);
+    sspi_functions->FreeContextBuffer(out_bufs[0].pvBuffer);
+
+    if (client->status == SEC_I_CONTINUE_NEEDED) {
+        return SSPI_CONTINUE;
+    }
+
+    return SSPI_OK;
+}
+
+int sspi_client_wrap_msg(
+    sspi_client_state *client,
+    PVOID input,
+    ULONG input_length,
+    PVOID* output,
+    ULONG* output_length 
+)
+{
+    SecPkgContext_Sizes sizes;
+
+	client->status = sspi_functions->QueryContextAttributes(&client->ctx, SECPKG_ATTR_SIZES, &sizes);
+	if (client->status != SEC_E_OK) {
+		return SSPI_ERROR;
+	}
+
+	char *msg = malloc((sizes.cbSecurityTrailer + input_length + sizes.cbBlockSize) * sizeof(char));
+	memcpy(&msg[sizes.cbSecurityTrailer], input, input_length);
+
+	SecBuffer wrap_bufs[3];
+	SecBufferDesc wrap_buf_desc;
+	wrap_buf_desc.cBuffers = 3;
+	wrap_buf_desc.pBuffers = wrap_bufs;
+	wrap_buf_desc.ulVersion = SECBUFFER_VERSION;
+
+	wrap_bufs[0].cbBuffer = sizes.cbSecurityTrailer;
+	wrap_bufs[0].BufferType = SECBUFFER_TOKEN;
+	wrap_bufs[0].pvBuffer = msg;
+
+	wrap_bufs[1].cbBuffer = input_length;
+	wrap_bufs[1].BufferType = SECBUFFER_DATA;
+	wrap_bufs[1].pvBuffer = msg + sizes.cbSecurityTrailer;
+
+	wrap_bufs[2].cbBuffer = sizes.cbBlockSize;
+	wrap_bufs[2].BufferType = SECBUFFER_PADDING;
+	wrap_bufs[2].pvBuffer = msg + sizes.cbSecurityTrailer + input_length;
+
+	client->status = sspi_functions->EncryptMessage(&client->ctx, SECQOP_WRAP_NO_ENCRYPT, &wrap_buf_desc, 0);
+	if (client->status != SEC_E_OK) {
+		free(msg);
+		return SSPI_ERROR;
+	}
+
+	*output_length = wrap_bufs[0].cbBuffer + wrap_bufs[1].cbBuffer + wrap_bufs[2].cbBuffer;
+	*output = malloc(*output_length);
+
+	memcpy(*output, wrap_bufs[0].pvBuffer, wrap_bufs[0].cbBuffer);
+	memcpy(*output + wrap_bufs[0].cbBuffer, wrap_bufs[1].pvBuffer, wrap_bufs[1].cbBuffer);
+	memcpy(*output + wrap_bufs[0].cbBuffer + wrap_bufs[1].cbBuffer, wrap_bufs[2].pvBuffer, wrap_bufs[2].cbBuffer);
+
+	free(msg);
+
+	return SSPI_OK;
+}
+
+int sspi_client_destroy(
+    sspi_client_state *client
+)
+{
+    if (client->has_ctx > 0) {
+        sspi_functions->DeleteSecurityContext(&client->ctx);
+    }
+
+    sspi_functions->FreeCredentialsHandle(&client->cred);
+
+    return SSPI_OK;
+}
\ No newline at end of file
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.h b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.h
new file mode 100644
index 0000000..ee6e9a7
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/internal/gssapi/sspi_wrapper.h
@@ -0,0 +1,58 @@
+//+build gssapi,windows
+
+#ifndef SSPI_WRAPPER_H
+#define SSPI_WRAPPER_H
+
+#define SECURITY_WIN32 1  /* Required for SSPI */
+
+#include <windows.h>
+#include <sspi.h>
+
+#define SSPI_OK 0
+#define SSPI_CONTINUE 1
+#define SSPI_ERROR 2
+
+typedef struct {
+    CredHandle cred;
+    CtxtHandle ctx;
+
+    int has_ctx;
+
+    SECURITY_STATUS status;
+} sspi_client_state;
+
+int sspi_init();
+
+int sspi_client_init(
+    sspi_client_state *client,
+    char* username,
+    char* password
+);
+
+int sspi_client_username(
+    sspi_client_state *client,
+    char** username
+);
+
+int sspi_client_negotiate(
+    sspi_client_state *client,
+    char* spn,
+    PVOID input,
+    ULONG input_length,
+    PVOID* output,
+    ULONG* output_length
+);
+
+int sspi_client_wrap_msg(
+    sspi_client_state *client,
+    PVOID input,
+    ULONG input_length,
+    PVOID* output,
+    ULONG* output_length 
+);
+
+int sspi_client_destroy(
+    sspi_client_state *client
+);
+
+#endif
\ No newline at end of file
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/mongodbcr.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/mongodbcr.go
new file mode 100644
index 0000000..89dcf08
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/mongodbcr.go
@@ -0,0 +1,100 @@
+// 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 auth
+
+import (
+	"context"
+	"crypto/md5"
+	"fmt"
+
+	"io"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// MONGODBCR is the mechanism name for MONGODB-CR.
+//
+// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
+const MONGODBCR = "MONGODB-CR"
+
+func newMongoDBCRAuthenticator(cred *Cred) (Authenticator, error) {
+	return &MongoDBCRAuthenticator{
+		DB:       cred.Source,
+		Username: cred.Username,
+		Password: cred.Password,
+	}, nil
+}
+
+// MongoDBCRAuthenticator uses the MONGODB-CR algorithm to authenticate a connection.
+//
+// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
+type MongoDBCRAuthenticator struct {
+	DB       string
+	Username string
+	Password string
+}
+
+// Auth authenticates the connection.
+//
+// The MONGODB-CR authentication mechanism is deprecated in MongoDB 4.0.
+func (a *MongoDBCRAuthenticator) Auth(ctx context.Context, desc description.Server, rw wiremessage.ReadWriter) error {
+
+	// Arbiters cannot be authenticated
+	if desc.Kind == description.RSArbiter {
+		return nil
+	}
+
+	db := a.DB
+	if db == "" {
+		db = defaultAuthDB
+	}
+
+	cmd := command.Read{DB: db, Command: bsonx.Doc{{"getnonce", bsonx.Int32(1)}}}
+	ssdesc := description.SelectedServer{Server: desc}
+	rdr, err := cmd.RoundTrip(ctx, ssdesc, rw)
+	if err != nil {
+		return newError(err, MONGODBCR)
+	}
+
+	var getNonceResult struct {
+		Nonce string `bson:"nonce"`
+	}
+
+	err = bson.Unmarshal(rdr, &getNonceResult)
+	if err != nil {
+		return newAuthError("unmarshal error", err)
+	}
+
+	cmd = command.Read{
+		DB: db,
+		Command: bsonx.Doc{
+			{"authenticate", bsonx.Int32(1)},
+			{"user", bsonx.String(a.Username)},
+			{"nonce", bsonx.String(getNonceResult.Nonce)},
+			{"key", bsonx.String(a.createKey(getNonceResult.Nonce))},
+		},
+	}
+	_, err = cmd.RoundTrip(ctx, ssdesc, rw)
+	if err != nil {
+		return newError(err, MONGODBCR)
+	}
+
+	return nil
+}
+
+func (a *MongoDBCRAuthenticator) createKey(nonce string) string {
+	h := md5.New()
+
+	_, _ = io.WriteString(h, nonce)
+	_, _ = io.WriteString(h, a.Username)
+	_, _ = io.WriteString(h, mongoPasswordDigest(a.Username, a.Password))
+	return fmt.Sprintf("%x", h.Sum(nil))
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/plain.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/plain.go
new file mode 100644
index 0000000..3f66aee
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/plain.go
@@ -0,0 +1,56 @@
+// 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 auth
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// PLAIN is the mechanism name for PLAIN.
+const PLAIN = "PLAIN"
+
+func newPlainAuthenticator(cred *Cred) (Authenticator, error) {
+	return &PlainAuthenticator{
+		Username: cred.Username,
+		Password: cred.Password,
+	}, nil
+}
+
+// PlainAuthenticator uses the PLAIN algorithm over SASL to authenticate a connection.
+type PlainAuthenticator struct {
+	Username string
+	Password string
+}
+
+// Auth authenticates the connection.
+func (a *PlainAuthenticator) Auth(ctx context.Context, desc description.Server, rw wiremessage.ReadWriter) error {
+	return ConductSaslConversation(ctx, desc, rw, "$external", &plainSaslClient{
+		username: a.Username,
+		password: a.Password,
+	})
+}
+
+type plainSaslClient struct {
+	username string
+	password string
+}
+
+func (c *plainSaslClient) Start() (string, []byte, error) {
+	b := []byte("\x00" + c.username + "\x00" + c.password)
+	return PLAIN, b, nil
+}
+
+func (c *plainSaslClient) Next(challenge []byte) ([]byte, error) {
+	return nil, newAuthError("unexpected server challenge", nil)
+}
+
+func (c *plainSaslClient) Completed() bool {
+	return true
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/sasl.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/sasl.go
new file mode 100644
index 0000000..5357f48
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/sasl.go
@@ -0,0 +1,120 @@
+// 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 auth
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// SaslClient is the client piece of a sasl conversation.
+type SaslClient interface {
+	Start() (string, []byte, error)
+	Next(challenge []byte) ([]byte, error)
+	Completed() bool
+}
+
+// SaslClientCloser is a SaslClient that has resources to clean up.
+type SaslClientCloser interface {
+	SaslClient
+	Close()
+}
+
+// ConductSaslConversation handles running a sasl conversation with MongoDB.
+func ConductSaslConversation(ctx context.Context, desc description.Server, rw wiremessage.ReadWriter, db string, client SaslClient) error {
+	// Arbiters cannot be authenticated
+	if desc.Kind == description.RSArbiter {
+		return nil
+	}
+
+	if db == "" {
+		db = defaultAuthDB
+	}
+
+	if closer, ok := client.(SaslClientCloser); ok {
+		defer closer.Close()
+	}
+
+	mech, payload, err := client.Start()
+	if err != nil {
+		return newError(err, mech)
+	}
+
+	saslStartCmd := command.Read{
+		DB: db,
+		Command: bsonx.Doc{
+			{"saslStart", bsonx.Int32(1)},
+			{"mechanism", bsonx.String(mech)},
+			{"payload", bsonx.Binary(0x00, payload)},
+		},
+	}
+
+	type saslResponse struct {
+		ConversationID int    `bson:"conversationId"`
+		Code           int    `bson:"code"`
+		Done           bool   `bson:"done"`
+		Payload        []byte `bson:"payload"`
+	}
+
+	var saslResp saslResponse
+
+	ssdesc := description.SelectedServer{Server: desc}
+	rdr, err := saslStartCmd.RoundTrip(ctx, ssdesc, rw)
+	if err != nil {
+		return newError(err, mech)
+	}
+
+	err = bson.Unmarshal(rdr, &saslResp)
+	if err != nil {
+		return newAuthError("unmarshall error", err)
+	}
+
+	cid := saslResp.ConversationID
+
+	for {
+		if saslResp.Code != 0 {
+			return newError(err, mech)
+		}
+
+		if saslResp.Done && client.Completed() {
+			return nil
+		}
+
+		payload, err = client.Next(saslResp.Payload)
+		if err != nil {
+			return newError(err, mech)
+		}
+
+		if saslResp.Done && client.Completed() {
+			return nil
+		}
+
+		saslContinueCmd := command.Read{
+			DB: db,
+			Command: bsonx.Doc{
+				{"saslContinue", bsonx.Int32(1)},
+				{"conversationId", bsonx.Int32(int32(cid))},
+				{"payload", bsonx.Binary(0x00, payload)},
+			},
+		}
+
+		rdr, err = saslContinueCmd.RoundTrip(ctx, ssdesc, rw)
+		if err != nil {
+			return newError(err, mech)
+		}
+
+		err = bson.Unmarshal(rdr, &saslResp)
+		if err != nil {
+			return newAuthError("unmarshal error", err)
+		}
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/scram.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/scram.go
new file mode 100644
index 0000000..170488d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/scram.go
@@ -0,0 +1,102 @@
+// 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
+
+// Copyright (C) MongoDB, Inc. 2018-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 auth
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+	"github.com/xdg/scram"
+	"github.com/xdg/stringprep"
+)
+
+// SCRAMSHA1 holds the mechanism name "SCRAM-SHA-1"
+const SCRAMSHA1 = "SCRAM-SHA-1"
+
+// SCRAMSHA256 holds the mechanism name "SCRAM-SHA-256"
+const SCRAMSHA256 = "SCRAM-SHA-256"
+
+func newScramSHA1Authenticator(cred *Cred) (Authenticator, error) {
+	passdigest := mongoPasswordDigest(cred.Username, cred.Password)
+	client, err := scram.SHA1.NewClientUnprepped(cred.Username, passdigest, "")
+	if err != nil {
+		return nil, newAuthError("error initializing SCRAM-SHA-1 client", err)
+	}
+	client.WithMinIterations(4096)
+	return &ScramAuthenticator{
+		mechanism: SCRAMSHA1,
+		source:    cred.Source,
+		client:    client,
+	}, nil
+}
+
+func newScramSHA256Authenticator(cred *Cred) (Authenticator, error) {
+	passprep, err := stringprep.SASLprep.Prepare(cred.Password)
+	if err != nil {
+		return nil, newAuthError(fmt.Sprintf("error SASLprepping password '%s'", cred.Password), err)
+	}
+	client, err := scram.SHA256.NewClientUnprepped(cred.Username, passprep, "")
+	if err != nil {
+		return nil, newAuthError("error initializing SCRAM-SHA-256 client", err)
+	}
+	client.WithMinIterations(4096)
+	return &ScramAuthenticator{
+		mechanism: SCRAMSHA256,
+		source:    cred.Source,
+		client:    client,
+	}, nil
+}
+
+// ScramAuthenticator uses the SCRAM algorithm over SASL to authenticate a connection.
+type ScramAuthenticator struct {
+	mechanism string
+	source    string
+	client    *scram.Client
+}
+
+// Auth authenticates the connection.
+func (a *ScramAuthenticator) Auth(ctx context.Context, desc description.Server, rw wiremessage.ReadWriter) error {
+	adapter := &scramSaslAdapter{conversation: a.client.NewConversation(), mechanism: a.mechanism}
+	err := ConductSaslConversation(ctx, desc, rw, a.source, adapter)
+	if err != nil {
+		return newAuthError("sasl conversation error", err)
+	}
+	return nil
+}
+
+type scramSaslAdapter struct {
+	mechanism    string
+	conversation *scram.ClientConversation
+}
+
+func (a *scramSaslAdapter) Start() (string, []byte, error) {
+	step, err := a.conversation.Step("")
+	if err != nil {
+		return a.mechanism, nil, err
+	}
+	return a.mechanism, []byte(step), nil
+}
+
+func (a *scramSaslAdapter) Next(challenge []byte) ([]byte, error) {
+	step, err := a.conversation.Step(string(challenge))
+	if err != nil {
+		return nil, err
+	}
+	return []byte(step), nil
+}
+
+func (a *scramSaslAdapter) Completed() bool {
+	return a.conversation.Done()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/util.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/util.go
new file mode 100644
index 0000000..36b8c07
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/util.go
@@ -0,0 +1,23 @@
+// 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 auth
+
+import (
+	"crypto/md5"
+	"fmt"
+	"io"
+)
+
+const defaultAuthDB = "admin"
+
+func mongoPasswordDigest(username, password string) string {
+	h := md5.New()
+	_, _ = io.WriteString(h, username)
+	_, _ = io.WriteString(h, ":mongo:")
+	_, _ = io.WriteString(h, password)
+	return fmt.Sprintf("%x", h.Sum(nil))
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/x509.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/x509.go
new file mode 100644
index 0000000..219513b
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/auth/x509.go
@@ -0,0 +1,49 @@
+// 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 auth
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// MongoDBX509 is the mechanism name for MongoDBX509.
+const MongoDBX509 = "MONGODB-X509"
+
+func newMongoDBX509Authenticator(cred *Cred) (Authenticator, error) {
+	return &MongoDBX509Authenticator{User: cred.Username}, nil
+}
+
+// MongoDBX509Authenticator uses X.509 certificates over TLS to authenticate a connection.
+type MongoDBX509Authenticator struct {
+	User string
+}
+
+// Auth implements the Authenticator interface.
+func (a *MongoDBX509Authenticator) Auth(ctx context.Context, desc description.Server, rw wiremessage.ReadWriter) error {
+	authRequestDoc := bsonx.Doc{
+		{"authenticate", bsonx.Int32(1)},
+		{"mechanism", bsonx.String(MongoDBX509)},
+	}
+
+	if desc.WireVersion.Max < 5 {
+		authRequestDoc = append(authRequestDoc, bsonx.Elem{"user", bsonx.String(a.User)})
+	}
+
+	authCmd := command.Read{DB: "$external", Command: authRequestDoc}
+	ssdesc := description.SelectedServer{Server: desc}
+	_, err := authCmd.RoundTrip(ctx, ssdesc, rw)
+	if err != nil {
+		return newAuthError("round trip error", err)
+	}
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/batch_cursor.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/batch_cursor.go
new file mode 100644
index 0000000..da946c3
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/batch_cursor.go
@@ -0,0 +1,424 @@
+package driver
+
+import (
+	"context"
+	"errors"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// BatchCursor is a batch implementation of a cursor. It returns documents in entire batches instead
+// of one at a time. An individual document cursor can be built on top of this batch cursor.
+type BatchCursor struct {
+	clientSession *session.Client
+	clock         *session.ClusterClock
+	namespace     command.Namespace
+	id            int64
+	err           error
+	server        *topology.Server
+	opts          []bsonx.Elem
+	currentBatch  []byte
+	firstBatch    bool
+	batchNumber   int
+
+	// legacy server (< 3.2) fields
+	batchSize   int32
+	limit       int32
+	numReturned int32 // number of docs returned by server
+}
+
+// NewBatchCursor creates a new BatchCursor from the provided parameters.
+func NewBatchCursor(result bsoncore.Document, clientSession *session.Client, clock *session.ClusterClock, server *topology.Server, opts ...bsonx.Elem) (*BatchCursor, error) {
+	cur, err := result.LookupErr("cursor")
+	if err != nil {
+		return nil, err
+	}
+	if cur.Type != bson.TypeEmbeddedDocument {
+		return nil, fmt.Errorf("cursor should be an embedded document but it is a BSON %s", cur.Type)
+	}
+
+	elems, err := cur.Document().Elements()
+	if err != nil {
+		return nil, err
+	}
+	bc := &BatchCursor{
+		clientSession: clientSession,
+		clock:         clock,
+		server:        server,
+		opts:          opts,
+		firstBatch:    true,
+	}
+
+	var ok bool
+	for _, elem := range elems {
+		switch elem.Key() {
+		case "firstBatch":
+			arr, ok := elem.Value().ArrayOK()
+			if !ok {
+				return nil, fmt.Errorf("firstBatch should be an array but it is a BSON %s", elem.Value().Type)
+			}
+			vals, err := arr.Values()
+			if err != nil {
+				return nil, err
+			}
+
+			for _, val := range vals {
+				if val.Type != bsontype.EmbeddedDocument {
+					return nil, fmt.Errorf("element of cursor batch is not a document, but at %s", val.Type)
+				}
+				bc.currentBatch = append(bc.currentBatch, val.Data...)
+			}
+		case "ns":
+			if elem.Value().Type != bson.TypeString {
+				return nil, fmt.Errorf("namespace should be a string but it is a BSON %s", elem.Value().Type)
+			}
+			namespace := command.ParseNamespace(elem.Value().StringValue())
+			err = namespace.Validate()
+			if err != nil {
+				return nil, err
+			}
+			bc.namespace = namespace
+		case "id":
+			bc.id, ok = elem.Value().Int64OK()
+			if !ok {
+				return nil, fmt.Errorf("id should be an int64 but it is a BSON %s", elem.Value().Type)
+			}
+		}
+	}
+
+	// close session if everything fits in first batch
+	if bc.id == 0 {
+		bc.closeImplicitSession()
+	}
+	return bc, nil
+}
+
+// NewEmptyBatchCursor returns a batch cursor that is empty.
+func NewEmptyBatchCursor() *BatchCursor {
+	return &BatchCursor{}
+}
+
+// NewLegacyBatchCursor creates a new BatchCursor for server versions 3.0 and below from the
+// provided parameters.
+//
+// TODO(GODRIVER-617): The batch parameter here should be []bsoncore.Document. Change it to this
+// once we have the new wiremessage package that uses bsoncore instead of bson.
+func NewLegacyBatchCursor(ns command.Namespace, cursorID int64, batch []bson.Raw, limit int32, batchSize int32, server *topology.Server) (*BatchCursor, error) {
+	bc := &BatchCursor{
+		id:          cursorID,
+		server:      server,
+		namespace:   ns,
+		limit:       limit,
+		batchSize:   batchSize,
+		numReturned: int32(len(batch)),
+		firstBatch:  true,
+	}
+
+	// take as many documents from the batch as needed
+	firstBatchSize := int32(len(batch))
+	if limit != 0 && limit < firstBatchSize {
+		firstBatchSize = limit
+	}
+	batch = batch[:firstBatchSize]
+	for _, doc := range batch {
+		bc.currentBatch = append(bc.currentBatch, doc...)
+	}
+
+	return bc, nil
+}
+
+// ID returns the cursor ID for this batch cursor.
+func (bc *BatchCursor) ID() int64 {
+	return bc.id
+}
+
+// Next indicates if there is another batch available. Returning false does not necessarily indicate
+// that the cursor is closed. This method will return false when an empty batch is returned.
+//
+// If Next returns true, there is a valid batch of documents available. If Next returns false, there
+// is not a valid batch of documents available.
+func (bc *BatchCursor) Next(ctx context.Context) bool {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	if bc.firstBatch {
+		bc.firstBatch = false
+		return true
+	}
+
+	if bc.id == 0 || bc.server == nil {
+		return false
+	}
+
+	if bc.legacy() {
+		bc.legacyGetMore(ctx)
+	} else {
+		bc.getMore(ctx)
+	}
+
+	return len(bc.currentBatch) > 0
+}
+
+// Batch will append the current batch of documents to dst. RequiredBytes can be called to determine
+// the length of the current batch of documents.
+//
+// If there is no batch available, this method does nothing.
+func (bc *BatchCursor) Batch(dst []byte) []byte { return append(dst, bc.currentBatch...) }
+
+// RequiredBytes returns the number of bytes required for the current batch.
+func (bc *BatchCursor) RequiredBytes() int { return len(bc.currentBatch) }
+
+// Err returns the latest error encountered.
+func (bc *BatchCursor) Err() error { return bc.err }
+
+// Close closes this batch cursor.
+func (bc *BatchCursor) Close(ctx context.Context) error {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	if bc.server == nil {
+		return nil
+	}
+
+	if bc.legacy() {
+		return bc.legacyKillCursor(ctx)
+	}
+
+	defer bc.closeImplicitSession()
+	conn, err := bc.server.Connection(ctx)
+	if err != nil {
+		return err
+	}
+
+	_, err = (&command.KillCursors{
+		Clock: bc.clock,
+		NS:    bc.namespace,
+		IDs:   []int64{bc.id},
+	}).RoundTrip(ctx, bc.server.SelectedDescription(), conn)
+	if err != nil {
+		_ = conn.Close() // The command response error is more important here
+		return err
+	}
+
+	bc.id = 0
+	return conn.Close()
+}
+
+func (bc *BatchCursor) closeImplicitSession() {
+	if bc.clientSession != nil && bc.clientSession.SessionType == session.Implicit {
+		bc.clientSession.EndSession()
+	}
+}
+
+func (bc *BatchCursor) clearBatch() {
+	bc.currentBatch = bc.currentBatch[:0]
+}
+
+func (bc *BatchCursor) getMore(ctx context.Context) {
+	bc.clearBatch()
+	if bc.id == 0 {
+		return
+	}
+
+	conn, err := bc.server.Connection(ctx)
+	if err != nil {
+		bc.err = err
+		return
+	}
+
+	response, err := (&command.GetMore{
+		Clock:   bc.clock,
+		ID:      bc.id,
+		NS:      bc.namespace,
+		Opts:    bc.opts,
+		Session: bc.clientSession,
+	}).RoundTrip(ctx, bc.server.SelectedDescription(), conn)
+	if err != nil {
+		_ = conn.Close() // The command response error is more important here
+		bc.err = err
+		return
+	}
+
+	err = conn.Close()
+	if err != nil {
+		bc.err = err
+		return
+	}
+
+	id, err := response.LookupErr("cursor", "id")
+	if err != nil {
+		bc.err = err
+		return
+	}
+	var ok bool
+	bc.id, ok = id.Int64OK()
+	if !ok {
+		bc.err = fmt.Errorf("BSON Type %s is not %s", id.Type, bson.TypeInt64)
+		return
+	}
+
+	// if this is the last getMore, close the session
+	if bc.id == 0 {
+		bc.closeImplicitSession()
+	}
+
+	batch, err := response.LookupErr("cursor", "nextBatch")
+	if err != nil {
+		bc.err = err
+		return
+	}
+	var arr bson.Raw
+	arr, ok = batch.ArrayOK()
+	if !ok {
+		bc.err = fmt.Errorf("BSON Type %s is not %s", batch.Type, bson.TypeArray)
+		return
+	}
+	vals, err := arr.Values()
+	if err != nil {
+		bc.err = err
+		return
+	}
+
+	for _, val := range vals {
+		if val.Type != bsontype.EmbeddedDocument {
+			bc.err = fmt.Errorf("element of cursor batch is not a document, but at %s", val.Type)
+			bc.currentBatch = bc.currentBatch[:0] // don't return a batch on error
+			return
+		}
+		bc.currentBatch = append(bc.currentBatch, val.Value...)
+	}
+
+	return
+}
+
+func (bc *BatchCursor) legacy() bool {
+	return bc.server.Description().WireVersion == nil || bc.server.Description().WireVersion.Max < 4
+}
+
+func (bc *BatchCursor) legacyKillCursor(ctx context.Context) error {
+	conn, err := bc.server.Connection(ctx)
+	if err != nil {
+		return err
+	}
+
+	kc := wiremessage.KillCursors{
+		NumberOfCursorIDs: 1,
+		CursorIDs:         []int64{bc.id},
+		CollectionName:    bc.namespace.Collection,
+		DatabaseName:      bc.namespace.DB,
+	}
+
+	err = conn.WriteWireMessage(ctx, kc)
+	if err != nil {
+		_ = conn.Close()
+		return err
+	}
+
+	err = conn.Close() // no reply from OP_KILL_CURSORS
+	if err != nil {
+		return err
+	}
+
+	bc.id = 0
+	bc.clearBatch()
+	return nil
+}
+
+func (bc *BatchCursor) legacyGetMore(ctx context.Context) {
+	bc.clearBatch()
+	if bc.id == 0 {
+		return
+	}
+
+	conn, err := bc.server.Connection(ctx)
+	if err != nil {
+		bc.err = err
+		return
+	}
+
+	numToReturn := bc.batchSize
+	if bc.limit != 0 && bc.numReturned+bc.batchSize > bc.limit {
+		numToReturn = bc.limit - bc.numReturned
+	}
+	gm := wiremessage.GetMore{
+		FullCollectionName: bc.namespace.DB + "." + bc.namespace.Collection,
+		CursorID:           bc.id,
+		NumberToReturn:     numToReturn,
+	}
+
+	err = conn.WriteWireMessage(ctx, gm)
+	if err != nil {
+		_ = conn.Close()
+		bc.err = err
+		return
+	}
+
+	response, err := conn.ReadWireMessage(ctx)
+	if err != nil {
+		_ = conn.Close()
+		bc.err = err
+		return
+	}
+
+	err = conn.Close()
+	if err != nil {
+		bc.err = err
+		return
+	}
+
+	reply, ok := response.(wiremessage.Reply)
+	if !ok {
+		bc.err = errors.New("did not receive OP_REPLY response")
+		return
+	}
+
+	err = validateGetMoreReply(reply)
+	if err != nil {
+		bc.err = err
+		return
+	}
+
+	bc.id = reply.CursorID
+	bc.numReturned += reply.NumberReturned
+	if bc.limit != 0 && bc.numReturned >= bc.limit {
+		err = bc.Close(ctx)
+		if err != nil {
+			bc.err = err
+			return
+		}
+	}
+
+	for _, doc := range reply.Documents {
+		bc.currentBatch = append(bc.currentBatch, doc...)
+	}
+}
+
+func validateGetMoreReply(reply wiremessage.Reply) error {
+	if int(reply.NumberReturned) != len(reply.Documents) {
+		return command.NewCommandResponseError("malformed OP_REPLY: NumberReturned does not match number of returned documents", nil)
+	}
+
+	if reply.ResponseFlags&wiremessage.CursorNotFound == wiremessage.CursorNotFound {
+		return command.QueryFailureError{
+			Message: "query failure - cursor not found",
+		}
+	}
+	if reply.ResponseFlags&wiremessage.QueryFailure == wiremessage.QueryFailure {
+		return command.QueryFailureError{
+			Message:  "query failure",
+			Response: reply.Documents[0],
+		}
+	}
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/bulk_write.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/bulk_write.go
new file mode 100644
index 0000000..4d461d5
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/bulk_write.go
@@ -0,0 +1,627 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// BulkWriteError is an error from one operation in a bulk write.
+type BulkWriteError struct {
+	result.WriteError
+	Model WriteModel
+}
+
+// BulkWriteException is a collection of errors returned by a bulk write operation.
+type BulkWriteException struct {
+	WriteConcernError *result.WriteConcernError
+	WriteErrors       []BulkWriteError
+}
+
+func (BulkWriteException) Error() string {
+	return ""
+}
+
+type bulkWriteBatch struct {
+	models   []WriteModel
+	canRetry bool
+}
+
+// BulkWrite handles the full dispatch cycle for a bulk write operation.
+func BulkWrite(
+	ctx context.Context,
+	ns command.Namespace,
+	models []WriteModel,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	retryWrite bool,
+	sess *session.Client,
+	writeConcern *writeconcern.WriteConcern,
+	clock *session.ClusterClock,
+	registry *bsoncodec.Registry,
+	opts ...*options.BulkWriteOptions,
+) (result.BulkWrite, error) {
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.BulkWrite{}, err
+	}
+
+	err = verifyOptions(models, ss)
+	if err != nil {
+		return result.BulkWrite{}, err
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if sess == nil && topo.SupportsSessions() {
+		sess, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.BulkWrite{}, err
+		}
+
+		defer sess.EndSession()
+	}
+
+	bwOpts := options.MergeBulkWriteOptions(opts...)
+
+	ordered := *bwOpts.Ordered
+
+	batches := createBatches(models, ordered)
+	bwRes := result.BulkWrite{
+		UpsertedIDs: make(map[int64]interface{}),
+	}
+	bwErr := BulkWriteException{
+		WriteErrors: make([]BulkWriteError, 0),
+	}
+
+	var opIndex int64 // the operation index for the upsertedIDs map
+	continueOnError := !ordered
+	for _, batch := range batches {
+		if len(batch.models) == 0 {
+			continue
+		}
+
+		batchRes, batchErr, err := runBatch(ctx, ns, topo, selector, ss, sess, clock, writeConcern, retryWrite,
+			bwOpts.BypassDocumentValidation, continueOnError, batch, registry)
+
+		mergeResults(&bwRes, batchRes, opIndex)
+		bwErr.WriteConcernError = batchErr.WriteConcernError
+		for i := range batchErr.WriteErrors {
+			batchErr.WriteErrors[i].Index = batchErr.WriteErrors[i].Index + int(opIndex)
+		}
+		bwErr.WriteErrors = append(bwErr.WriteErrors, batchErr.WriteErrors...)
+
+		if !continueOnError && (err != nil || len(batchErr.WriteErrors) > 0 || batchErr.WriteConcernError != nil) {
+			if err != nil {
+				return result.BulkWrite{}, err
+			}
+
+			return result.BulkWrite{}, bwErr
+		}
+
+		opIndex += int64(len(batch.models))
+	}
+
+	bwRes.MatchedCount -= bwRes.UpsertedCount
+	return bwRes, nil
+}
+
+func runBatch(
+	ctx context.Context,
+	ns command.Namespace,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	ss *topology.SelectedServer,
+	sess *session.Client,
+	clock *session.ClusterClock,
+	wc *writeconcern.WriteConcern,
+	retryWrite bool,
+	bypassDocValidation *bool,
+	continueOnError bool,
+	batch bulkWriteBatch,
+	registry *bsoncodec.Registry,
+) (result.BulkWrite, BulkWriteException, error) {
+	batchRes := result.BulkWrite{
+		UpsertedIDs: make(map[int64]interface{}),
+	}
+	batchErr := BulkWriteException{}
+
+	var writeErrors []result.WriteError
+	switch batch.models[0].(type) {
+	case InsertOneModel:
+		res, err := runInsert(ctx, ns, topo, selector, ss, sess, clock, wc, retryWrite, batch, bypassDocValidation,
+			continueOnError, registry)
+		if err != nil {
+			return result.BulkWrite{}, BulkWriteException{}, err
+		}
+
+		batchRes.InsertedCount = int64(res.N)
+		writeErrors = res.WriteErrors
+	case DeleteOneModel, DeleteManyModel:
+		res, err := runDelete(ctx, ns, topo, selector, ss, sess, clock, wc, retryWrite, batch, continueOnError, registry)
+		if err != nil {
+			return result.BulkWrite{}, BulkWriteException{}, err
+		}
+
+		batchRes.DeletedCount = int64(res.N)
+		writeErrors = res.WriteErrors
+	case ReplaceOneModel, UpdateOneModel, UpdateManyModel:
+		res, err := runUpdate(ctx, ns, topo, selector, ss, sess, clock, wc, retryWrite, batch, bypassDocValidation,
+			continueOnError, registry)
+		if err != nil {
+			return result.BulkWrite{}, BulkWriteException{}, err
+		}
+
+		batchRes.MatchedCount = res.MatchedCount
+		batchRes.ModifiedCount = res.ModifiedCount
+		batchRes.UpsertedCount = int64(len(res.Upserted))
+		writeErrors = res.WriteErrors
+		for _, upsert := range res.Upserted {
+			batchRes.UpsertedIDs[upsert.Index] = upsert.ID
+		}
+	}
+
+	batchErr.WriteErrors = make([]BulkWriteError, 0, len(writeErrors))
+	for _, we := range writeErrors {
+		batchErr.WriteErrors = append(batchErr.WriteErrors, BulkWriteError{
+			WriteError: we,
+			Model:      batch.models[0],
+		})
+	}
+
+	return batchRes, batchErr, nil
+}
+
+func runInsert(
+	ctx context.Context,
+	ns command.Namespace,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	ss *topology.SelectedServer,
+	sess *session.Client,
+	clock *session.ClusterClock,
+	wc *writeconcern.WriteConcern,
+	retryWrite bool,
+	batch bulkWriteBatch,
+	bypassDocValidation *bool,
+	continueOnError bool,
+	registry *bsoncodec.Registry,
+) (result.Insert, error) {
+	docs := make([]bsonx.Doc, len(batch.models))
+	var i int
+	for _, model := range batch.models {
+		converted := model.(InsertOneModel)
+		doc, err := interfaceToDocument(converted.Document, registry)
+		if err != nil {
+			return result.Insert{}, err
+		}
+
+		docs[i] = doc
+		i++
+	}
+
+	cmd := command.Insert{
+		ContinueOnError: continueOnError,
+		NS:              ns,
+		Docs:            docs,
+		Session:         sess,
+		Clock:           clock,
+		WriteConcern:    wc,
+	}
+
+	if bypassDocValidation != nil {
+		cmd.Opts = []bsonx.Elem{{"bypassDocumentValidation", bsonx.Boolean(*bypassDocValidation)}}
+	}
+
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite || !batch.canRetry {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false
+		}
+		return insert(ctx, cmd, ss, nil)
+	}
+
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, origErr := insert(ctx, cmd, ss, nil)
+	if shouldRetry(origErr, res.WriteConcernError) {
+		newServer, err := topo.SelectServer(ctx, selector)
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return res, origErr
+		}
+
+		return insert(ctx, cmd, newServer, origErr)
+	}
+
+	return res, origErr
+}
+
+func runDelete(
+	ctx context.Context,
+	ns command.Namespace,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	ss *topology.SelectedServer,
+	sess *session.Client,
+	clock *session.ClusterClock,
+	wc *writeconcern.WriteConcern,
+	retryWrite bool,
+	batch bulkWriteBatch,
+	continueOnError bool,
+	registry *bsoncodec.Registry,
+) (result.Delete, error) {
+	docs := make([]bsonx.Doc, len(batch.models))
+	var i int
+
+	for _, model := range batch.models {
+		var doc bsonx.Doc
+		var err error
+
+		if dom, ok := model.(DeleteOneModel); ok {
+			doc, err = createDeleteDoc(dom.Filter, dom.Collation, false, registry)
+		} else if dmm, ok := model.(DeleteManyModel); ok {
+			doc, err = createDeleteDoc(dmm.Filter, dmm.Collation, true, registry)
+		}
+
+		if err != nil {
+			return result.Delete{}, err
+		}
+
+		docs[i] = doc
+		i++
+	}
+
+	cmd := command.Delete{
+		ContinueOnError: continueOnError,
+		NS:              ns,
+		Deletes:         docs,
+		Session:         sess,
+		Clock:           clock,
+		WriteConcern:    wc,
+	}
+
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite || !batch.canRetry {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false
+		}
+		return delete(ctx, cmd, ss, nil)
+	}
+
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, origErr := delete(ctx, cmd, ss, nil)
+	if shouldRetry(origErr, res.WriteConcernError) {
+		newServer, err := topo.SelectServer(ctx, selector)
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return res, origErr
+		}
+
+		return delete(ctx, cmd, newServer, origErr)
+	}
+
+	return res, origErr
+}
+
+func runUpdate(
+	ctx context.Context,
+	ns command.Namespace,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	ss *topology.SelectedServer,
+	sess *session.Client,
+	clock *session.ClusterClock,
+	wc *writeconcern.WriteConcern,
+	retryWrite bool,
+	batch bulkWriteBatch,
+	bypassDocValidation *bool,
+	continueOnError bool,
+	registry *bsoncodec.Registry,
+) (result.Update, error) {
+	docs := make([]bsonx.Doc, len(batch.models))
+
+	for i, model := range batch.models {
+		var doc bsonx.Doc
+		var err error
+
+		if rom, ok := model.(ReplaceOneModel); ok {
+			doc, err = createUpdateDoc(rom.Filter, rom.Replacement, options.ArrayFilters{}, false, rom.UpdateModel, false,
+				registry)
+		} else if uom, ok := model.(UpdateOneModel); ok {
+			doc, err = createUpdateDoc(uom.Filter, uom.Update, uom.ArrayFilters, uom.ArrayFiltersSet, uom.UpdateModel, false,
+				registry)
+		} else if umm, ok := model.(UpdateManyModel); ok {
+			doc, err = createUpdateDoc(umm.Filter, umm.Update, umm.ArrayFilters, umm.ArrayFiltersSet, umm.UpdateModel, true,
+				registry)
+		}
+
+		if err != nil {
+			return result.Update{}, err
+		}
+
+		docs[i] = doc
+	}
+
+	cmd := command.Update{
+		ContinueOnError: continueOnError,
+		NS:              ns,
+		Docs:            docs,
+		Session:         sess,
+		Clock:           clock,
+		WriteConcern:    wc,
+	}
+	if bypassDocValidation != nil {
+		// TODO this is temporary!
+		cmd.Opts = []bsonx.Elem{{"bypassDocumentValidation", bsonx.Boolean(*bypassDocValidation)}}
+		//cmd.Opts = []option.UpdateOptioner{option.OptBypassDocumentValidation(bypassDocValidation)}
+	}
+
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite || !batch.canRetry {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false
+		}
+		return update(ctx, cmd, ss, nil)
+	}
+
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, origErr := update(ctx, cmd, ss, nil)
+	if shouldRetry(origErr, res.WriteConcernError) {
+		newServer, err := topo.SelectServer(ctx, selector)
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return res, origErr
+		}
+
+		return update(ctx, cmd, newServer, origErr)
+	}
+
+	return res, origErr
+}
+
+func verifyOptions(models []WriteModel, ss *topology.SelectedServer) error {
+	maxVersion := ss.Description().WireVersion.Max
+	// 3.4 is wire version 5
+	// 3.6 is wire version 6
+
+	for _, model := range models {
+		var collationSet bool
+		var afSet bool // arrayFilters
+
+		switch converted := model.(type) {
+		case DeleteOneModel:
+			collationSet = converted.Collation != nil
+		case DeleteManyModel:
+			collationSet = converted.Collation != nil
+		case ReplaceOneModel:
+			collationSet = converted.Collation != nil
+		case UpdateOneModel:
+			afSet = converted.ArrayFiltersSet
+			collationSet = converted.Collation != nil
+		case UpdateManyModel:
+			afSet = converted.ArrayFiltersSet
+			collationSet = converted.Collation != nil
+		}
+
+		if afSet && maxVersion < 6 {
+			return ErrArrayFilters
+		}
+
+		if collationSet && maxVersion < 5 {
+			return ErrCollation
+		}
+	}
+
+	return nil
+}
+
+func createBatches(models []WriteModel, ordered bool) []bulkWriteBatch {
+	if ordered {
+		return createOrderedBatches(models)
+	}
+
+	batches := make([]bulkWriteBatch, 3)
+	var i int
+	for i = 0; i < 3; i++ {
+		batches[i].canRetry = true
+	}
+
+	var numBatches int // number of batches used. can't use len(batches) because it's set to 3
+	insertInd := -1
+	updateInd := -1
+	deleteInd := -1
+
+	for _, model := range models {
+		switch converted := model.(type) {
+		case InsertOneModel:
+			if insertInd == -1 {
+				// this is the first InsertOneModel
+				insertInd = numBatches
+				numBatches++
+			}
+
+			batches[insertInd].models = append(batches[insertInd].models, model)
+		case DeleteOneModel, DeleteManyModel:
+			if deleteInd == -1 {
+				deleteInd = numBatches
+				numBatches++
+			}
+
+			batches[deleteInd].models = append(batches[deleteInd].models, model)
+			if _, ok := converted.(DeleteManyModel); ok {
+				batches[deleteInd].canRetry = false
+			}
+		case ReplaceOneModel, UpdateOneModel, UpdateManyModel:
+			if updateInd == -1 {
+				updateInd = numBatches
+				numBatches++
+			}
+
+			batches[updateInd].models = append(batches[updateInd].models, model)
+			if _, ok := converted.(UpdateManyModel); ok {
+				batches[updateInd].canRetry = false
+			}
+		}
+	}
+
+	return batches
+}
+
+func createOrderedBatches(models []WriteModel) []bulkWriteBatch {
+	var batches []bulkWriteBatch
+	var prevKind command.WriteCommandKind = -1
+	i := -1 // batch index
+
+	for _, model := range models {
+		var createNewBatch bool
+		var canRetry bool
+		var newKind command.WriteCommandKind
+
+		switch model.(type) {
+		case InsertOneModel:
+			createNewBatch = prevKind != command.InsertCommand
+			canRetry = true
+			newKind = command.InsertCommand
+		case DeleteOneModel:
+			createNewBatch = prevKind != command.DeleteCommand
+			canRetry = true
+			newKind = command.DeleteCommand
+		case DeleteManyModel:
+			createNewBatch = prevKind != command.DeleteCommand
+			newKind = command.DeleteCommand
+		case ReplaceOneModel, UpdateOneModel:
+			createNewBatch = prevKind != command.UpdateCommand
+			canRetry = true
+			newKind = command.UpdateCommand
+		case UpdateManyModel:
+			createNewBatch = prevKind != command.UpdateCommand
+			newKind = command.UpdateCommand
+		}
+
+		if createNewBatch {
+			batches = append(batches, bulkWriteBatch{
+				models:   []WriteModel{model},
+				canRetry: canRetry,
+			})
+			i++
+		} else {
+			batches[i].models = append(batches[i].models, model)
+			if !canRetry {
+				batches[i].canRetry = false // don't make it true if it was already false
+			}
+		}
+
+		prevKind = newKind
+	}
+
+	return batches
+}
+
+func shouldRetry(cmdErr error, wcErr *result.WriteConcernError) bool {
+	if cerr, ok := cmdErr.(command.Error); ok && cerr.Retryable() ||
+		wcErr != nil && command.IsWriteConcernErrorRetryable(wcErr) {
+		return true
+	}
+
+	return false
+}
+
+func createUpdateDoc(
+	filter interface{},
+	update interface{},
+	arrayFilters options.ArrayFilters,
+	arrayFiltersSet bool,
+	updateModel UpdateModel,
+	multi bool,
+	registry *bsoncodec.Registry,
+) (bsonx.Doc, error) {
+	f, err := interfaceToDocument(filter, registry)
+	if err != nil {
+		return nil, err
+	}
+
+	u, err := interfaceToDocument(update, registry)
+	if err != nil {
+		return nil, err
+	}
+
+	doc := bsonx.Doc{
+		{"q", bsonx.Document(f)},
+		{"u", bsonx.Document(u)},
+		{"multi", bsonx.Boolean(multi)},
+	}
+
+	if arrayFiltersSet {
+		arr, err := arrayFilters.ToArray()
+		if err != nil {
+			return nil, err
+		}
+		doc = append(doc, bsonx.Elem{"arrayFilters", bsonx.Array(arr)})
+	}
+
+	if updateModel.Collation != nil {
+		doc = append(doc, bsonx.Elem{"collation", bsonx.Document(updateModel.Collation.ToDocument())})
+	}
+
+	if updateModel.UpsertSet {
+		doc = append(doc, bsonx.Elem{"upsert", bsonx.Boolean(updateModel.Upsert)})
+	}
+
+	return doc, nil
+}
+
+func createDeleteDoc(
+	filter interface{},
+	collation *options.Collation,
+	many bool,
+	registry *bsoncodec.Registry,
+) (bsonx.Doc, error) {
+	f, err := interfaceToDocument(filter, registry)
+	if err != nil {
+		return nil, err
+	}
+
+	var limit int32 = 1
+	if many {
+		limit = 0
+	}
+
+	doc := bsonx.Doc{
+		{"q", bsonx.Document(f)},
+		{"limit", bsonx.Int32(limit)},
+	}
+
+	if collation != nil {
+		doc = append(doc, bsonx.Elem{"collation", bsonx.Document(collation.ToDocument())})
+	}
+
+	return doc, nil
+}
+
+func mergeResults(aggResult *result.BulkWrite, newResult result.BulkWrite, opIndex int64) {
+	aggResult.InsertedCount += newResult.InsertedCount
+	aggResult.MatchedCount += newResult.MatchedCount
+	aggResult.ModifiedCount += newResult.ModifiedCount
+	aggResult.DeletedCount += newResult.DeletedCount
+	aggResult.UpsertedCount += newResult.UpsertedCount
+
+	for index, upsertID := range newResult.UpsertedIDs {
+		aggResult.UpsertedIDs[index+opIndex] = upsertID
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/commit_transaction.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/commit_transaction.go
new file mode 100644
index 0000000..a3b3439
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/commit_transaction.go
@@ -0,0 +1,106 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// CommitTransaction handles the full cycle dispatch and execution of committing a transaction
+// against the provided topology.
+func CommitTransaction(
+	ctx context.Context,
+	cmd command.CommitTransaction,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+) (result.TransactionResult, error) {
+	res, err := commitTransaction(ctx, cmd, topo, selector, nil)
+	if cerr, ok := err.(command.Error); ok && err != nil {
+		// Retry if appropriate
+		if cerr.Retryable() {
+			res, err = commitTransaction(ctx, cmd, topo, selector, cerr)
+			if cerr2, ok := err.(command.Error); ok && err != nil {
+				// Retry failures also get label
+				cerr2.Labels = append(cerr2.Labels, command.UnknownTransactionCommitResult)
+			} else if err != nil {
+				err = command.Error{Message: err.Error(), Labels: []string{command.UnknownTransactionCommitResult}}
+			}
+		}
+	}
+	return res, err
+}
+
+func commitTransaction(
+	ctx context.Context,
+	cmd command.CommitTransaction,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	oldErr error,
+) (result.TransactionResult, error) {
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		// If retrying server selection, return the original error if it fails
+		if oldErr != nil {
+			return result.TransactionResult{}, oldErr
+		}
+		return result.TransactionResult{}, err
+	}
+
+	desc := ss.Description()
+
+	if oldErr != nil && (!topo.SupportsSessions() || !description.SessionsSupported(desc.WireVersion)) {
+		// Assuming we are retrying (oldErr != nil),
+		// if server doesn't support retryable writes, return the original error
+		// Conditions for retry write support are the same as that of sessions
+		return result.TransactionResult{}, oldErr
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		if oldErr != nil {
+			return result.TransactionResult{}, oldErr
+		}
+		return result.TransactionResult{}, err
+	}
+	defer conn.Close()
+
+	res, err := cmd.RoundTrip(ctx, desc, conn)
+
+	// Add UnknownCommitTransaction Error label where appropriate
+	if err != nil {
+		var newLabels []string
+		if cerr, ok := err.(command.Error); ok {
+			// Replace the label TransientTransactionError with UnknownTransactionCommitResult
+			// if network error, write concern shutdown, or write concern failed errors
+			hasUnknownCommitErr := false
+			for _, label := range cerr.Labels {
+				if label == command.NetworkError {
+					hasUnknownCommitErr = true
+					break
+				}
+			}
+
+			// network error, retryable error, or write concern fail/timeout (64) get the unknown label
+			if hasUnknownCommitErr || cerr.Retryable() || cerr.Code == 64 {
+				for _, label := range cerr.Labels {
+					if label != command.TransientTransactionError {
+						newLabels = append(newLabels, label)
+					}
+				}
+				newLabels = append(newLabels, command.UnknownTransactionCommitResult)
+				cerr.Labels = newLabels
+			}
+			err = cerr
+		}
+	}
+	return res, err
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/count.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/count.go
new file mode 100644
index 0000000..7b7fba4
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/count.go
@@ -0,0 +1,93 @@
+// 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 driver
+
+import (
+	"context"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// Count handles the full cycle dispatch and execution of a count command against the provided
+// topology.
+func Count(
+	ctx context.Context,
+	cmd command.Count,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	registry *bsoncodec.Registry,
+	opts ...*options.CountOptions,
+) (int64, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return 0, err
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return 0, err
+	}
+	defer conn.Close()
+
+	rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
+	if err != nil {
+		return 0, err
+	}
+	cmd.ReadPref = rp
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return 0, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	countOpts := options.MergeCountOptions(opts...)
+
+	if countOpts.Limit != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"limit", bsonx.Int64(*countOpts.Limit)})
+	}
+	if countOpts.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{
+			"maxTimeMS", bsonx.Int64(int64(*countOpts.MaxTime / time.Millisecond)),
+		})
+	}
+	if countOpts.Skip != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"skip", bsonx.Int64(*countOpts.Skip)})
+	}
+	if countOpts.Collation != nil {
+		if desc.WireVersion.Max < 5 {
+			return 0, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(countOpts.Collation.ToDocument())})
+	}
+	if countOpts.Hint != nil {
+		hintElem, err := interfaceToElement("hint", countOpts.Hint, registry)
+		if err != nil {
+			return 0, err
+		}
+
+		cmd.Opts = append(cmd.Opts, hintElem)
+	}
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/count_documents.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/count_documents.go
new file mode 100644
index 0000000..b727d53
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/count_documents.go
@@ -0,0 +1,87 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package driver
+
+import (
+	"context"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"time"
+)
+
+// CountDocuments handles the full cycle dispatch and execution of a countDocuments command against the provided
+// topology.
+func CountDocuments(
+	ctx context.Context,
+	cmd command.CountDocuments,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	registry *bsoncodec.Registry,
+	opts ...*options.CountOptions,
+) (int64, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return 0, err
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return 0, err
+	}
+	defer conn.Close()
+
+	rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
+	if err != nil {
+		return 0, err
+	}
+	cmd.ReadPref = rp
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return 0, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	countOpts := options.MergeCountOptions(opts...)
+
+	// ignore Skip and Limit because we already have these options in the pipeline
+	if countOpts.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{
+			"maxTimeMS", bsonx.Int64(int64(*countOpts.MaxTime / time.Millisecond)),
+		})
+	}
+	if countOpts.Collation != nil {
+		if desc.WireVersion.Max < 5 {
+			return 0, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(countOpts.Collation.ToDocument())})
+	}
+	if countOpts.Hint != nil {
+		hintElem, err := interfaceToElement("hint", countOpts.Hint, registry)
+		if err != nil {
+			return 0, err
+		}
+
+		cmd.Opts = append(cmd.Opts, hintElem)
+	}
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/create_indexes.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/create_indexes.go
new file mode 100644
index 0000000..48b277e
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/create_indexes.go
@@ -0,0 +1,77 @@
+// 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 driver
+
+import (
+	"context"
+
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// CreateIndexes handles the full cycle dispatch and execution of a createIndexes
+// command against the provided topology.
+func CreateIndexes(
+	ctx context.Context,
+	cmd command.CreateIndexes,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	opts ...*options.CreateIndexesOptions,
+) (result.CreateIndexes, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.CreateIndexes{}, err
+	}
+
+	desc := ss.Description()
+	if desc.WireVersion.Max < 5 && hasCollation(cmd) {
+		return result.CreateIndexes{}, ErrCollation
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return result.CreateIndexes{}, err
+	}
+	defer conn.Close()
+
+	cio := options.MergeCreateIndexesOptions(opts...)
+	if cio.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"maxTimeMS", bsonx.Int64(int64(*cio.MaxTime / time.Millisecond))})
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.CreateIndexes{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	return cmd.RoundTrip(ctx, ss.Description(), conn)
+}
+
+func hasCollation(cmd command.CreateIndexes) bool {
+	for _, ind := range cmd.Indexes {
+		if _, err := ind.Document().LookupErr("collation"); err == nil {
+			return true
+		}
+	}
+
+	return false
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/delete.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/delete.go
new file mode 100644
index 0000000..c622f9b
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/delete.go
@@ -0,0 +1,116 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// Delete handles the full cycle dispatch and execution of a delete command against the provided
+// topology.
+func Delete(
+	ctx context.Context,
+	cmd command.Delete,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	retryWrite bool,
+	opts ...*options.DeleteOptions,
+) (result.Delete, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.Delete{}, err
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() && writeconcern.AckWrite(cmd.WriteConcern) {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.Delete{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	deleteOpts := options.MergeDeleteOptions(opts...)
+	if deleteOpts.Collation != nil {
+		if ss.Description().WireVersion.Max < 5 {
+			return result.Delete{}, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(deleteOpts.Collation.ToDocument())})
+	}
+
+	// Execute in a single trip if retry writes not supported, or retry not enabled
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false // explicitly set to false to prevent encoding transaction number
+		}
+		return delete(ctx, cmd, ss, nil)
+	}
+
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, originalErr := delete(ctx, cmd, ss, nil)
+
+	// Retry if appropriate
+	if cerr, ok := originalErr.(command.Error); ok && cerr.Retryable() ||
+		res.WriteConcernError != nil && command.IsWriteConcernErrorRetryable(res.WriteConcernError) {
+		ss, err := topo.SelectServer(ctx, selector)
+
+		// Return original error if server selection fails or new server does not support retryable writes
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return res, originalErr
+		}
+
+		return delete(ctx, cmd, ss, cerr)
+	}
+	return res, originalErr
+}
+
+func delete(
+	ctx context.Context,
+	cmd command.Delete,
+	ss *topology.SelectedServer,
+	oldErr error,
+) (result.Delete, error) {
+	desc := ss.Description()
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		if oldErr != nil {
+			return result.Delete{}, oldErr
+		}
+		return result.Delete{}, err
+	}
+
+	if !writeconcern.AckWrite(cmd.WriteConcern) {
+		go func() {
+			defer func() { _ = recover() }()
+			defer conn.Close()
+
+			_, _ = cmd.RoundTrip(ctx, desc, conn)
+		}()
+
+		return result.Delete{}, command.ErrUnacknowledgedWrite
+	}
+	defer conn.Close()
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/delete_indexes.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/delete_indexes.go
new file mode 100644
index 0000000..669c797
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/delete_indexes.go
@@ -0,0 +1,62 @@
+// 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 driver
+
+import (
+	"context"
+
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// DropIndexes handles the full cycle dispatch and execution of a dropIndexes
+// command against the provided topology.
+func DropIndexes(
+	ctx context.Context,
+	cmd command.DropIndexes,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	opts ...*options.DropIndexesOptions,
+) (bson.Raw, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, err
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	dio := options.MergeDropIndexesOptions(opts...)
+	if dio.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"maxTimeMS", bsonx.Int64(int64(*dio.MaxTime / time.Millisecond))})
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	return cmd.RoundTrip(ctx, ss.Description(), conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/dispatch.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/dispatch.go
new file mode 100644
index 0000000..2ec642a
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/dispatch.go
@@ -0,0 +1,67 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package driver
+
+import (
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+)
+
+// ErrCollation is caused if a collation is given for an invalid server version.
+var ErrCollation = errors.New("collation cannot be set for server versions < 3.4")
+
+// ErrArrayFilters is caused if array filters are given for an invalid server version.
+var ErrArrayFilters = errors.New("array filters cannot be set for server versions < 3.6")
+
+func interfaceToDocument(val interface{}, registry *bsoncodec.Registry) (bsonx.Doc, error) {
+	if val == nil {
+		return bsonx.Doc{}, nil
+	}
+
+	if registry == nil {
+		registry = bson.DefaultRegistry
+	}
+
+	if bs, ok := val.([]byte); ok {
+		// Slight optimization so we'll just use MarshalBSON and not go through the codec machinery.
+		val = bson.Raw(bs)
+	}
+
+	// TODO(skriptble): Use a pool of these instead.
+	buf := make([]byte, 0, 256)
+	b, err := bson.MarshalAppendWithRegistry(registry, buf, val)
+	if err != nil {
+		return nil, err
+	}
+	return bsonx.ReadDoc(b)
+}
+
+func interfaceToElement(key string, i interface{}, registry *bsoncodec.Registry) (bsonx.Elem, error) {
+	switch conv := i.(type) {
+	case string:
+		return bsonx.Elem{key, bsonx.String(conv)}, nil
+	case bsonx.Doc:
+		return bsonx.Elem{key, bsonx.Document(conv)}, nil
+	default:
+		doc, err := interfaceToDocument(i, registry)
+		if err != nil {
+			return bsonx.Elem{}, err
+		}
+
+		return bsonx.Elem{key, bsonx.Document(doc)}, nil
+	}
+}
+
+func closeImplicitSession(sess *session.Client) {
+	if sess != nil && sess.SessionType == session.Implicit {
+		sess.EndSession()
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/distinct.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/distinct.go
new file mode 100644
index 0000000..eed7390
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/distinct.go
@@ -0,0 +1,77 @@
+// 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 driver
+
+import (
+	"context"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"time"
+)
+
+// Distinct handles the full cycle dispatch and execution of a distinct command against the provided
+// topology.
+func Distinct(
+	ctx context.Context,
+	cmd command.Distinct,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	opts ...*options.DistinctOptions,
+) (result.Distinct, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.Distinct{}, err
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return result.Distinct{}, err
+	}
+	defer conn.Close()
+
+	rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
+	if err != nil {
+		return result.Distinct{}, err
+	}
+	cmd.ReadPref = rp
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.Distinct{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	distinctOpts := options.MergeDistinctOptions(opts...)
+
+	if distinctOpts.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{
+			"maxTimeMS", bsonx.Int64(int64(*distinctOpts.MaxTime / time.Millisecond)),
+		})
+	}
+	if distinctOpts.Collation != nil {
+		if desc.WireVersion.Max < 5 {
+			return result.Distinct{}, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(distinctOpts.Collation.ToDocument())})
+	}
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/drop_collection.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/drop_collection.go
new file mode 100644
index 0000000..657ba3f
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/drop_collection.go
@@ -0,0 +1,52 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// DropCollection handles the full cycle dispatch and execution of a dropCollection
+// command against the provided topology.
+func DropCollection(
+	ctx context.Context,
+	cmd command.DropCollection,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+) (bson.Raw, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, err
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	return cmd.RoundTrip(ctx, ss.Description(), conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/drop_database.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/drop_database.go
new file mode 100644
index 0000000..7c9422f
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/drop_database.go
@@ -0,0 +1,52 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// DropDatabase handles the full cycle dispatch and execution of a dropDatabase
+// command against the provided topology.
+func DropDatabase(
+	ctx context.Context,
+	cmd command.DropDatabase,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+) (bson.Raw, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, err
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	return cmd.RoundTrip(ctx, ss.Description(), conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/end_sessions.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/end_sessions.go
new file mode 100644
index 0000000..46bec84
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/end_sessions.go
@@ -0,0 +1,40 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// EndSessions handles the full cycle dispatch and execution of an endSessions command against the provided
+// topology.
+func EndSessions(
+	ctx context.Context,
+	cmd command.EndSessions,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+) ([]result.EndSessions, []error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, []error{err}
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, []error{err}
+	}
+	defer conn.Close()
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find.go
new file mode 100644
index 0000000..0287ca7
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find.go
@@ -0,0 +1,517 @@
+// 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 driver
+
+import (
+	"context"
+
+	"time"
+
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Find handles the full cycle dispatch and execution of a find command against the provided
+// topology.
+func Find(
+	ctx context.Context,
+	cmd command.Find,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	registry *bsoncodec.Registry,
+	opts ...*options.FindOptions,
+) (*BatchCursor, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, err
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	if desc.WireVersion.Max < 4 {
+		return legacyFind(ctx, cmd, registry, ss, conn, opts...)
+	}
+
+	rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
+	if err != nil {
+		return nil, err
+	}
+	cmd.ReadPref = rp
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	fo := options.MergeFindOptions(opts...)
+	if fo.AllowPartialResults != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"allowPartialResults", bsonx.Boolean(*fo.AllowPartialResults)})
+	}
+	if fo.BatchSize != nil {
+		elem := bsonx.Elem{"batchSize", bsonx.Int32(*fo.BatchSize)}
+		cmd.Opts = append(cmd.Opts, elem)
+		cmd.CursorOpts = append(cmd.CursorOpts, elem)
+
+		if fo.Limit != nil && *fo.BatchSize != 0 && *fo.Limit <= int64(*fo.BatchSize) {
+			cmd.Opts = append(cmd.Opts, bsonx.Elem{"singleBatch", bsonx.Boolean(true)})
+		}
+	}
+	if fo.Collation != nil {
+		if desc.WireVersion.Max < 5 {
+			return nil, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(fo.Collation.ToDocument())})
+	}
+	if fo.Comment != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"comment", bsonx.String(*fo.Comment)})
+	}
+	if fo.CursorType != nil {
+		switch *fo.CursorType {
+		case options.Tailable:
+			cmd.Opts = append(cmd.Opts, bsonx.Elem{"tailable", bsonx.Boolean(true)})
+		case options.TailableAwait:
+			cmd.Opts = append(cmd.Opts, bsonx.Elem{"tailable", bsonx.Boolean(true)}, bsonx.Elem{"awaitData", bsonx.Boolean(true)})
+		}
+	}
+	if fo.Hint != nil {
+		hintElem, err := interfaceToElement("hint", fo.Hint, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		cmd.Opts = append(cmd.Opts, hintElem)
+	}
+	if fo.Limit != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"limit", bsonx.Int64(*fo.Limit)})
+	}
+	if fo.Max != nil {
+		maxElem, err := interfaceToElement("max", fo.Max, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		cmd.Opts = append(cmd.Opts, maxElem)
+	}
+	if fo.MaxAwaitTime != nil {
+		// Specified as maxTimeMS on the in the getMore command and not given in initial find command.
+		cmd.CursorOpts = append(cmd.CursorOpts, bsonx.Elem{"maxTimeMS", bsonx.Int64(int64(*fo.MaxAwaitTime / time.Millisecond))})
+	}
+	if fo.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"maxTimeMS", bsonx.Int64(int64(*fo.MaxTime / time.Millisecond))})
+	}
+	if fo.Min != nil {
+		minElem, err := interfaceToElement("min", fo.Min, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		cmd.Opts = append(cmd.Opts, minElem)
+	}
+	if fo.NoCursorTimeout != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"noCursorTimeout", bsonx.Boolean(*fo.NoCursorTimeout)})
+	}
+	if fo.OplogReplay != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"oplogReplay", bsonx.Boolean(*fo.OplogReplay)})
+	}
+	if fo.Projection != nil {
+		projElem, err := interfaceToElement("projection", fo.Projection, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		cmd.Opts = append(cmd.Opts, projElem)
+	}
+	if fo.ReturnKey != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"returnKey", bsonx.Boolean(*fo.ReturnKey)})
+	}
+	if fo.ShowRecordID != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"showRecordId", bsonx.Boolean(*fo.ShowRecordID)})
+	}
+	if fo.Skip != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"skip", bsonx.Int64(*fo.Skip)})
+	}
+	if fo.Snapshot != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"snapshot", bsonx.Boolean(*fo.Snapshot)})
+	}
+	if fo.Sort != nil {
+		sortElem, err := interfaceToElement("sort", fo.Sort, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		cmd.Opts = append(cmd.Opts, sortElem)
+	}
+
+	res, err := cmd.RoundTrip(ctx, desc, conn)
+	if err != nil {
+		closeImplicitSession(cmd.Session)
+		return nil, err
+	}
+
+	return NewBatchCursor(bsoncore.Document(res), cmd.Session, cmd.Clock, ss.Server, cmd.CursorOpts...)
+}
+
+// legacyFind handles the dispatch and execution of a find operation against a pre-3.2 server.
+func legacyFind(
+	ctx context.Context,
+	cmd command.Find,
+	registry *bsoncodec.Registry,
+	ss *topology.SelectedServer,
+	conn connection.Connection,
+	opts ...*options.FindOptions,
+) (*BatchCursor, error) {
+	query := wiremessage.Query{
+		FullCollectionName: cmd.NS.DB + "." + cmd.NS.Collection,
+	}
+
+	fo := options.MergeFindOptions(opts...)
+	optsDoc, err := createLegacyOptionsDoc(fo, registry)
+	if err != nil {
+		return nil, err
+	}
+	if fo.Projection != nil {
+		projDoc, err := interfaceToDocument(fo.Projection, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		projRaw, err := projDoc.MarshalBSON()
+		if err != nil {
+			return nil, err
+		}
+		query.ReturnFieldsSelector = projRaw
+	}
+	if fo.Skip != nil {
+		query.NumberToSkip = int32(*fo.Skip)
+		query.SkipSet = true
+	}
+	// batch size of 1 not possible with OP_QUERY because the cursor will be closed immediately
+	if fo.BatchSize != nil && *fo.BatchSize == 1 {
+		query.NumberToReturn = 2
+	} else {
+		query.NumberToReturn = calculateNumberToReturn(fo)
+	}
+	query.Flags = calculateLegacyFlags(fo)
+
+	query.BatchSize = fo.BatchSize
+	if fo.Limit != nil {
+		i := int32(*fo.Limit)
+		query.Limit = &i
+	}
+
+	// set read preference and/or slaveOK flag
+	desc := ss.SelectedDescription()
+	if slaveOkNeeded(cmd.ReadPref, desc) {
+		query.Flags |= wiremessage.SlaveOK
+	}
+	optsDoc = addReadPref(cmd.ReadPref, desc.Server.Kind, optsDoc)
+
+	if cmd.Filter == nil {
+		cmd.Filter = bsonx.Doc{}
+	}
+
+	// filter must be wrapped in $query if other $modifiers are used
+	var queryDoc bsonx.Doc
+	if len(optsDoc) == 0 {
+		queryDoc = cmd.Filter
+	} else {
+		filterDoc := bsonx.Doc{
+			{"$query", bsonx.Document(cmd.Filter)},
+		}
+		// $query should go first
+		queryDoc = append(filterDoc, optsDoc...)
+	}
+
+	queryRaw, err := queryDoc.MarshalBSON()
+	if err != nil {
+		return nil, err
+	}
+	query.Query = queryRaw
+
+	reply, err := roundTripQuery(ctx, query, conn)
+	if err != nil {
+		return nil, err
+	}
+
+	var cursorLimit int32
+	var cursorBatchSize int32
+	if query.Limit != nil {
+		cursorLimit = int32(*query.Limit)
+		if cursorLimit < 0 {
+			cursorLimit *= -1
+		}
+	}
+	if query.BatchSize != nil {
+		cursorBatchSize = int32(*query.BatchSize)
+	}
+
+	return NewLegacyBatchCursor(cmd.NS, reply.CursorID, reply.Documents, cursorLimit, cursorBatchSize, ss.Server)
+}
+
+func createLegacyOptionsDoc(fo *options.FindOptions, registry *bsoncodec.Registry) (bsonx.Doc, error) {
+	var optsDoc bsonx.Doc
+
+	if fo.Collation != nil {
+		return nil, ErrCollation
+	}
+	if fo.Comment != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"$comment", bsonx.String(*fo.Comment)})
+	}
+	if fo.Hint != nil {
+		hintElem, err := interfaceToElement("$hint", fo.Hint, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		optsDoc = append(optsDoc, hintElem)
+	}
+	if fo.Max != nil {
+		maxElem, err := interfaceToElement("$max", fo.Max, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		optsDoc = append(optsDoc, maxElem)
+	}
+	if fo.MaxTime != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"$maxTimeMS", bsonx.Int64(int64(*fo.MaxTime / time.Millisecond))})
+	}
+	if fo.Min != nil {
+		minElem, err := interfaceToElement("$min", fo.Min, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		optsDoc = append(optsDoc, minElem)
+	}
+	if fo.ReturnKey != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"$returnKey", bsonx.Boolean(*fo.ReturnKey)})
+	}
+	if fo.ShowRecordID != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"$showDiskLoc", bsonx.Boolean(*fo.ShowRecordID)})
+	}
+	if fo.Snapshot != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"$snapshot", bsonx.Boolean(*fo.Snapshot)})
+	}
+	if fo.Sort != nil {
+		sortElem, err := interfaceToElement("$orderby", fo.Sort, registry)
+		if err != nil {
+			return nil, err
+		}
+
+		optsDoc = append(optsDoc, sortElem)
+	}
+
+	return optsDoc, nil
+}
+
+func calculateLegacyFlags(fo *options.FindOptions) wiremessage.QueryFlag {
+	var flags wiremessage.QueryFlag
+
+	if fo.AllowPartialResults != nil {
+		flags |= wiremessage.Partial
+	}
+	if fo.CursorType != nil {
+		switch *fo.CursorType {
+		case options.Tailable:
+			flags |= wiremessage.TailableCursor
+		case options.TailableAwait:
+			flags |= wiremessage.TailableCursor
+			flags |= wiremessage.AwaitData
+		}
+	}
+	if fo.NoCursorTimeout != nil {
+		flags |= wiremessage.NoCursorTimeout
+	}
+	if fo.OplogReplay != nil {
+		flags |= wiremessage.OplogReplay
+	}
+
+	return flags
+}
+
+// calculate the number to return for the first find query
+func calculateNumberToReturn(opts *options.FindOptions) int32 {
+	var numReturn int32
+	var limit int32
+	var batchSize int32
+
+	if opts.Limit != nil {
+		limit = int32(*opts.Limit)
+	}
+	if opts.BatchSize != nil {
+		batchSize = int32(*opts.BatchSize)
+	}
+
+	if limit < 0 {
+		numReturn = limit
+	} else if limit == 0 {
+		numReturn = batchSize
+	} else if limit < batchSize {
+		numReturn = limit
+	} else {
+		numReturn = batchSize
+	}
+
+	return numReturn
+}
+
+func slaveOkNeeded(rp *readpref.ReadPref, desc description.SelectedServer) bool {
+	if desc.Kind == description.Single && desc.Server.Kind != description.Mongos {
+		return true
+	}
+	if rp == nil {
+		// assume primary
+		return false
+	}
+
+	return rp.Mode() != readpref.PrimaryMode
+}
+
+func addReadPref(rp *readpref.ReadPref, kind description.ServerKind, query bsonx.Doc) bsonx.Doc {
+	if !readPrefNeeded(rp, kind) {
+		return query
+	}
+
+	doc := createReadPref(rp)
+	if doc == nil {
+		return query
+	}
+
+	return query.Append("$readPreference", bsonx.Document(doc))
+}
+
+func readPrefNeeded(rp *readpref.ReadPref, kind description.ServerKind) bool {
+	if kind != description.Mongos || rp == nil {
+		return false
+	}
+
+	// simple Primary or SecondaryPreferred is communicated via slaveOk to Mongos.
+	if rp.Mode() == readpref.PrimaryMode || rp.Mode() == readpref.SecondaryPreferredMode {
+		if _, ok := rp.MaxStaleness(); !ok && len(rp.TagSets()) == 0 {
+			return false
+		}
+	}
+
+	return true
+}
+
+func createReadPref(rp *readpref.ReadPref) bsonx.Doc {
+	if rp == nil {
+		return nil
+	}
+
+	doc := bsonx.Doc{}
+
+	switch rp.Mode() {
+	case readpref.PrimaryMode:
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("primary")})
+	case readpref.PrimaryPreferredMode:
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("primaryPreferred")})
+	case readpref.SecondaryPreferredMode:
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("secondaryPreferred")})
+	case readpref.SecondaryMode:
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("secondary")})
+	case readpref.NearestMode:
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("nearest")})
+	}
+
+	sets := make([]bsonx.Val, 0, len(rp.TagSets()))
+	for _, ts := range rp.TagSets() {
+		if len(ts) == 0 {
+			continue
+		}
+		set := bsonx.Doc{}
+		for _, t := range ts {
+			set = append(set, bsonx.Elem{t.Name, bsonx.String(t.Value)})
+		}
+		sets = append(sets, bsonx.Document(set))
+	}
+	if len(sets) > 0 {
+		doc = append(doc, bsonx.Elem{"tags", bsonx.Array(sets)})
+	}
+	if d, ok := rp.MaxStaleness(); ok {
+		doc = append(doc, bsonx.Elem{"maxStalenessSeconds", bsonx.Int32(int32(d.Seconds()))})
+	}
+
+	return doc
+}
+
+func roundTripQuery(ctx context.Context, query wiremessage.Query, conn connection.Connection) (wiremessage.Reply, error) {
+	err := conn.WriteWireMessage(ctx, query)
+	if err != nil {
+		if _, ok := err.(command.Error); ok {
+			return wiremessage.Reply{}, err
+		}
+		return wiremessage.Reply{}, command.Error{
+			Message: err.Error(),
+			Labels:  []string{command.NetworkError},
+		}
+	}
+
+	wm, err := conn.ReadWireMessage(ctx)
+	if err != nil {
+		if _, ok := err.(command.Error); ok {
+			return wiremessage.Reply{}, err
+		}
+		// Connection errors are transient
+		return wiremessage.Reply{}, command.Error{
+			Message: err.Error(),
+			Labels:  []string{command.NetworkError},
+		}
+	}
+
+	reply, ok := wm.(wiremessage.Reply)
+	if !ok {
+		return wiremessage.Reply{}, errors.New("did not receive OP_REPLY response")
+	}
+
+	err = validateOpReply(reply)
+	if err != nil {
+		return wiremessage.Reply{}, err
+	}
+
+	return reply, nil
+}
+
+func validateOpReply(reply wiremessage.Reply) error {
+	if int(reply.NumberReturned) != len(reply.Documents) {
+		return command.NewCommandResponseError(command.ReplyDocumentMismatch, nil)
+	}
+
+	if reply.ResponseFlags&wiremessage.QueryFailure == wiremessage.QueryFailure {
+		return command.QueryFailureError{
+			Message:  "query failure",
+			Response: reply.Documents[0],
+		}
+	}
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_delete.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_delete.go
new file mode 100644
index 0000000..8e45e88
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_delete.go
@@ -0,0 +1,137 @@
+// 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 driver
+
+import (
+	"context"
+
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// FindOneAndDelete handles the full cycle dispatch and execution of a FindOneAndDelete command against the provided
+// topology.
+func FindOneAndDelete(
+	ctx context.Context,
+	cmd command.FindOneAndDelete,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	retryWrite bool,
+	registry *bsoncodec.Registry,
+	opts ...*options.FindOneAndDeleteOptions,
+) (result.FindAndModify, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	do := options.MergeFindOneAndDeleteOptions(opts...)
+	if do.Collation != nil {
+		if ss.Description().WireVersion.Max < 5 {
+			return result.FindAndModify{}, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(do.Collation.ToDocument())})
+	}
+	if do.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"maxTimeMs", bsonx.Int64(int64(*do.MaxTime / time.Millisecond))})
+	}
+	if do.Projection != nil {
+		projElem, err := interfaceToElement("fields", do.Projection, registry)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+
+		cmd.Opts = append(cmd.Opts, projElem)
+	}
+	if do.Sort != nil {
+		sortElem, err := interfaceToElement("sort", do.Sort, registry)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+
+		cmd.Opts = append(cmd.Opts, sortElem)
+	}
+
+	// Execute in a single trip if retry writes not supported, or retry not enabled
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false // explicitly set to false to prevent encoding transaction number
+		}
+		return findOneAndDelete(ctx, cmd, ss, nil)
+	}
+
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, originalErr := findOneAndDelete(ctx, cmd, ss, nil)
+
+	// Retry if appropriate
+	if cerr, ok := originalErr.(command.Error); ok && cerr.Retryable() {
+		ss, err := topo.SelectServer(ctx, selector)
+
+		// Return original error if server selection fails or new server does not support retryable writes
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return result.FindAndModify{}, originalErr
+		}
+
+		return findOneAndDelete(ctx, cmd, ss, cerr)
+	}
+
+	return res, originalErr
+}
+
+func findOneAndDelete(
+	ctx context.Context,
+	cmd command.FindOneAndDelete,
+	ss *topology.SelectedServer,
+	oldErr error,
+) (result.FindAndModify, error) {
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		if oldErr != nil {
+			return result.FindAndModify{}, oldErr
+		}
+		return result.FindAndModify{}, err
+	}
+
+	if !writeconcern.AckWrite(cmd.WriteConcern) {
+		go func() {
+			defer func() { _ = recover() }()
+			defer conn.Close()
+
+			_, _ = cmd.RoundTrip(ctx, desc, conn)
+		}()
+
+		return result.FindAndModify{}, command.ErrUnacknowledgedWrite
+	}
+	defer conn.Close()
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_replace.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_replace.go
new file mode 100644
index 0000000..cde5bf5
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_replace.go
@@ -0,0 +1,146 @@
+// 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 driver
+
+import (
+	"context"
+
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// FindOneAndReplace handles the full cycle dispatch and execution of a FindOneAndReplace command against the provided
+// topology.
+func FindOneAndReplace(
+	ctx context.Context,
+	cmd command.FindOneAndReplace,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	retryWrite bool,
+	registry *bsoncodec.Registry,
+	opts ...*options.FindOneAndReplaceOptions,
+) (result.FindAndModify, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	ro := options.MergeFindOneAndReplaceOptions(opts...)
+	if ro.BypassDocumentValidation != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"byapssDocumentValidation", bsonx.Boolean(*ro.BypassDocumentValidation)})
+	}
+	if ro.Collation != nil {
+		if ss.Description().WireVersion.Max < 5 {
+			return result.FindAndModify{}, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(ro.Collation.ToDocument())})
+	}
+	if ro.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"maxTimeMS", bsonx.Int64(int64(*ro.MaxTime / time.Millisecond))})
+	}
+	if ro.Projection != nil {
+		maxElem, err := interfaceToElement("fields", ro.Projection, registry)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+
+		cmd.Opts = append(cmd.Opts, maxElem)
+	}
+	if ro.ReturnDocument != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"new", bsonx.Boolean(*ro.ReturnDocument == options.After)})
+	}
+	if ro.Sort != nil {
+		sortElem, err := interfaceToElement("sort", ro.Sort, registry)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+
+		cmd.Opts = append(cmd.Opts, sortElem)
+	}
+	if ro.Upsert != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"upsert", bsonx.Boolean(*ro.Upsert)})
+	}
+
+	// Execute in a single trip if retry writes not supported, or retry not enabled
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false // explicitly set to false to prevent encoding transaction number
+		}
+		return findOneAndReplace(ctx, cmd, ss, nil)
+	}
+
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, originalErr := findOneAndReplace(ctx, cmd, ss, nil)
+
+	// Retry if appropriate
+	if cerr, ok := originalErr.(command.Error); ok && cerr.Retryable() {
+		ss, err := topo.SelectServer(ctx, selector)
+
+		// Return original error if server selection fails or new server does not support retryable writes
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return result.FindAndModify{}, originalErr
+		}
+
+		return findOneAndReplace(ctx, cmd, ss, cerr)
+	}
+
+	return res, originalErr
+}
+
+func findOneAndReplace(
+	ctx context.Context,
+	cmd command.FindOneAndReplace,
+	ss *topology.SelectedServer,
+	oldErr error,
+) (result.FindAndModify, error) {
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		if oldErr != nil {
+			return result.FindAndModify{}, oldErr
+		}
+		return result.FindAndModify{}, err
+	}
+
+	if !writeconcern.AckWrite(cmd.WriteConcern) {
+		go func() {
+			defer func() { _ = recover() }()
+			defer conn.Close()
+
+			_, _ = cmd.RoundTrip(ctx, desc, conn)
+		}()
+
+		return result.FindAndModify{}, command.ErrUnacknowledgedWrite
+	}
+	defer conn.Close()
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_update.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_update.go
new file mode 100644
index 0000000..d6c8e67
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/find_one_and_update.go
@@ -0,0 +1,154 @@
+// 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 driver
+
+import (
+	"context"
+
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// FindOneAndUpdate handles the full cycle dispatch and execution of a FindOneAndUpdate command against the provided
+// topology.
+func FindOneAndUpdate(
+	ctx context.Context,
+	cmd command.FindOneAndUpdate,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	retryWrite bool,
+	registry *bsoncodec.Registry,
+	opts ...*options.FindOneAndUpdateOptions,
+) (result.FindAndModify, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	uo := options.MergeFindOneAndUpdateOptions(opts...)
+	if uo.ArrayFilters != nil {
+		arr, err := uo.ArrayFilters.ToArray()
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"arrayFilters", bsonx.Array(arr)})
+	}
+	if uo.BypassDocumentValidation != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"bypassDocumentValidation", bsonx.Boolean(*uo.BypassDocumentValidation)})
+	}
+	if uo.Collation != nil {
+		if ss.Description().WireVersion.Max < 5 {
+			return result.FindAndModify{}, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(uo.Collation.ToDocument())})
+	}
+	if uo.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"maxTimeMS", bsonx.Int64(int64(*uo.MaxTime / time.Millisecond))})
+	}
+	if uo.Projection != nil {
+		projElem, err := interfaceToElement("fields", uo.Projection, registry)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+
+		cmd.Opts = append(cmd.Opts, projElem)
+	}
+	if uo.ReturnDocument != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"new", bsonx.Boolean(*uo.ReturnDocument == options.After)})
+	}
+	if uo.Sort != nil {
+		sortElem, err := interfaceToElement("sort", uo.Sort, registry)
+		if err != nil {
+			return result.FindAndModify{}, err
+		}
+
+		cmd.Opts = append(cmd.Opts, sortElem)
+	}
+	if uo.Upsert != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"upsert", bsonx.Boolean(*uo.Upsert)})
+	}
+
+	// Execute in a single trip if retry writes not supported, or retry not enabled
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false // explicitly set to false to prevent encoding transaction number
+		}
+		return findOneAndUpdate(ctx, cmd, ss, nil)
+	}
+
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, originalErr := findOneAndUpdate(ctx, cmd, ss, nil)
+
+	// Retry if appropriate
+	if cerr, ok := originalErr.(command.Error); ok && cerr.Retryable() {
+		ss, err := topo.SelectServer(ctx, selector)
+
+		// Return original error if server selection fails or new server does not support retryable writes
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return result.FindAndModify{}, originalErr
+		}
+
+		return findOneAndUpdate(ctx, cmd, ss, cerr)
+	}
+
+	return res, originalErr
+}
+
+func findOneAndUpdate(
+	ctx context.Context,
+	cmd command.FindOneAndUpdate,
+	ss *topology.SelectedServer,
+	oldErr error,
+) (result.FindAndModify, error) {
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		if oldErr != nil {
+			return result.FindAndModify{}, oldErr
+		}
+		return result.FindAndModify{}, err
+	}
+
+	if !writeconcern.AckWrite(cmd.WriteConcern) {
+		go func() {
+			defer func() { _ = recover() }()
+			defer conn.Close()
+
+			_, _ = cmd.RoundTrip(ctx, desc, conn)
+		}()
+
+		return result.FindAndModify{}, command.ErrUnacknowledgedWrite
+	}
+	defer conn.Close()
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/insert.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/insert.go
new file mode 100644
index 0000000..214774c
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/insert.go
@@ -0,0 +1,118 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// Insert handles the full cycle dispatch and execution of an insert command against the provided
+// topology.
+func Insert(
+	ctx context.Context,
+	cmd command.Insert,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	retryWrite bool,
+	opts ...*options.InsertManyOptions,
+) (result.Insert, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.Insert{}, err
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.Insert{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	insertOpts := options.MergeInsertManyOptions(opts...)
+
+	if insertOpts.BypassDocumentValidation != nil && ss.Description().WireVersion.Includes(4) {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"bypassDocumentValidation", bsonx.Boolean(*insertOpts.BypassDocumentValidation)})
+	}
+	if insertOpts.Ordered != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"ordered", bsonx.Boolean(*insertOpts.Ordered)})
+	}
+
+	// Execute in a single trip if retry writes not supported, or retry not enabled
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false // explicitly set to false to prevent encoding transaction number
+		}
+		return insert(ctx, cmd, ss, nil)
+	}
+
+	// TODO figure out best place to put retry write.  Command shouldn't have to know about this field.
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, originalErr := insert(ctx, cmd, ss, nil)
+
+	// Retry if appropriate
+	if cerr, ok := originalErr.(command.Error); ok && cerr.Retryable() ||
+		res.WriteConcernError != nil && command.IsWriteConcernErrorRetryable(res.WriteConcernError) {
+		ss, err := topo.SelectServer(ctx, selector)
+
+		// Return original error if server selection fails or new server does not support retryable writes
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return res, originalErr
+		}
+
+		return insert(ctx, cmd, ss, cerr)
+	}
+
+	return res, originalErr
+}
+
+func insert(
+	ctx context.Context,
+	cmd command.Insert,
+	ss *topology.SelectedServer,
+	oldErr error,
+) (result.Insert, error) {
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		if oldErr != nil {
+			return result.Insert{}, oldErr
+		}
+		return result.Insert{}, err
+	}
+
+	if !writeconcern.AckWrite(cmd.WriteConcern) {
+		go func() {
+			defer func() { _ = recover() }()
+			defer conn.Close()
+
+			_, _ = cmd.RoundTrip(ctx, desc, conn)
+		}()
+
+		return result.Insert{}, command.ErrUnacknowledgedWrite
+	}
+	defer conn.Close()
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/kill_cursors.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/kill_cursors.go
new file mode 100644
index 0000000..574d027
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/kill_cursors.go
@@ -0,0 +1,37 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// KillCursors handles the full cycle dispatch and execution of an aggregate command against the provided
+// topology.
+func KillCursors(
+	ctx context.Context,
+	cmd command.KillCursors,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+) (result.KillCursors, error) {
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.KillCursors{}, err
+	}
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return result.KillCursors{}, err
+	}
+	defer conn.Close()
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_collections.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_collections.go
new file mode 100644
index 0000000..c52df2d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_collections.go
@@ -0,0 +1,133 @@
+// 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 driver
+
+import (
+	"context"
+
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// ErrFilterType is thrown when a non-string filter is specified.
+var ErrFilterType = errors.New("filter must be a string")
+
+// ListCollections handles the full cycle dispatch and execution of a listCollections command against the provided
+// topology.
+func ListCollections(
+	ctx context.Context,
+	cmd command.ListCollections,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	opts ...*options.ListCollectionsOptions,
+) (*ListCollectionsBatchCursor, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, err
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	if ss.Description().WireVersion.Max < 3 {
+		return legacyListCollections(ctx, cmd, ss, conn)
+	}
+
+	rp, err := getReadPrefBasedOnTransaction(cmd.ReadPref, cmd.Session)
+	if err != nil {
+		return nil, err
+	}
+	cmd.ReadPref = rp
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	lc := options.MergeListCollectionsOptions(opts...)
+	if lc.NameOnly != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"nameOnly", bsonx.Boolean(*lc.NameOnly)})
+	}
+
+	res, err := cmd.RoundTrip(ctx, ss.Description(), conn)
+	if err != nil {
+		closeImplicitSession(cmd.Session)
+		return nil, err
+	}
+
+	batchCursor, err := NewBatchCursor(bsoncore.Document(res), cmd.Session, cmd.Clock, ss.Server, cmd.CursorOpts...)
+	if err != nil {
+		closeImplicitSession(cmd.Session)
+		return nil, err
+	}
+
+	return NewListCollectionsBatchCursor(batchCursor)
+}
+
+func legacyListCollections(
+	ctx context.Context,
+	cmd command.ListCollections,
+	ss *topology.SelectedServer,
+	conn connection.Connection,
+) (*ListCollectionsBatchCursor, error) {
+	filter, err := transformFilter(cmd.Filter, cmd.DB)
+	if err != nil {
+		return nil, err
+	}
+
+	findCmd := command.Find{
+		NS:       command.NewNamespace(cmd.DB, "system.namespaces"),
+		ReadPref: cmd.ReadPref,
+		Filter:   filter,
+	}
+
+	// don't need registry because it's used to create BSON docs for find options that don't exist in this case
+	batchCursor, err := legacyFind(ctx, findCmd, nil, ss, conn)
+	if err != nil {
+		return nil, err
+	}
+
+	return NewLegacyListCollectionsBatchCursor(batchCursor)
+}
+
+// modify the user-supplied filter to prefix the "name" field with the database name.
+// returns the original filter if the name field is not present or a copy with the modified name field if it is
+func transformFilter(filter bsonx.Doc, dbName string) (bsonx.Doc, error) {
+	if filter == nil {
+		return filter, nil
+	}
+
+	if nameVal, err := filter.LookupErr("name"); err == nil {
+		name, ok := nameVal.StringValueOK()
+		if !ok {
+			return nil, ErrFilterType
+		}
+
+		filterCopy := filter.Copy()
+		filterCopy.Set("name", bsonx.String(dbName+"."+name))
+		return filterCopy, nil
+	}
+	return filter, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_collections_batch_cursor.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_collections_batch_cursor.go
new file mode 100644
index 0000000..11fa77d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_collections_batch_cursor.go
@@ -0,0 +1,121 @@
+package driver
+
+import (
+	"context"
+	"errors"
+	"strings"
+
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+)
+
+// ListCollectionsBatchCursor is a special batch cursor returned from ListCollections that properly
+// handles current and legacy ListCollections operations.
+type ListCollectionsBatchCursor struct {
+	legacy       bool
+	bc           *BatchCursor
+	currentBatch []byte
+	err          error
+}
+
+// NewListCollectionsBatchCursor creates a new non-legacy ListCollectionsCursor.
+func NewListCollectionsBatchCursor(bc *BatchCursor) (*ListCollectionsBatchCursor, error) {
+	if bc == nil {
+		return nil, errors.New("batch cursor must not be nil")
+	}
+	return &ListCollectionsBatchCursor{bc: bc}, nil
+}
+
+// NewLegacyListCollectionsBatchCursor creates a new legacy ListCollectionsCursor.
+func NewLegacyListCollectionsBatchCursor(bc *BatchCursor) (*ListCollectionsBatchCursor, error) {
+	if bc == nil {
+		return nil, errors.New("batch cursor must not be nil")
+	}
+	return &ListCollectionsBatchCursor{legacy: true, bc: bc}, nil
+}
+
+// ID returns the cursor ID for this batch cursor.
+func (lcbc *ListCollectionsBatchCursor) ID() int64 {
+	return lcbc.bc.ID()
+}
+
+// Next indicates if there is another batch available. Returning false does not necessarily indicate
+// that the cursor is closed. This method will return false when an empty batch is returned.
+//
+// If Next returns true, there is a valid batch of documents available. If Next returns false, there
+// is not a valid batch of documents available.
+func (lcbc *ListCollectionsBatchCursor) Next(ctx context.Context) bool {
+	if !lcbc.bc.Next(ctx) {
+		return false
+	}
+
+	if !lcbc.legacy {
+		lcbc.currentBatch = lcbc.bc.currentBatch
+		return true
+	}
+
+	batch := lcbc.bc.currentBatch
+	lcbc.currentBatch = lcbc.currentBatch[:0]
+	var doc bsoncore.Document
+	var ok bool
+	for {
+		doc, batch, ok = bsoncore.ReadDocument(batch)
+		if !ok {
+			break
+		}
+
+		doc, lcbc.err = lcbc.projectNameElement(doc)
+		if lcbc.err != nil {
+			return false
+		}
+		lcbc.currentBatch = append(lcbc.currentBatch, doc...)
+	}
+
+	return true
+}
+
+// Batch will append the current batch of documents to dst. RequiredBytes can be called to determine
+// the length of the current batch of documents.
+//
+// If there is no batch available, this method does nothing.
+func (lcbc *ListCollectionsBatchCursor) Batch(dst []byte) []byte {
+	return append(dst, lcbc.currentBatch...)
+}
+
+// RequiredBytes returns the number of bytes required for the current batch.
+func (lcbc *ListCollectionsBatchCursor) RequiredBytes() int { return len(lcbc.currentBatch) }
+
+// Err returns the latest error encountered.
+func (lcbc *ListCollectionsBatchCursor) Err() error {
+	if lcbc.err != nil {
+		return lcbc.err
+	}
+	return lcbc.bc.Err()
+}
+
+// Close closes this batch cursor.
+func (lcbc *ListCollectionsBatchCursor) Close(ctx context.Context) error { return lcbc.bc.Close(ctx) }
+
+// project out the database name for a legacy server
+func (*ListCollectionsBatchCursor) projectNameElement(rawDoc bsoncore.Document) (bsoncore.Document, error) {
+	elems, err := rawDoc.Elements()
+	if err != nil {
+		return nil, err
+	}
+
+	var filteredElems []byte
+	for _, elem := range elems {
+		key := elem.Key()
+		if key != "name" {
+			filteredElems = append(filteredElems, elem...)
+			continue
+		}
+
+		name := elem.Value().StringValue()
+		collName := name[strings.Index(name, ".")+1:]
+		filteredElems = bsoncore.AppendStringElement(filteredElems, "name", collName)
+	}
+
+	var filteredDoc []byte
+	filteredDoc = bsoncore.BuildDocument(filteredDoc, filteredElems)
+	return filteredDoc, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_databases.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_databases.go
new file mode 100644
index 0000000..608269b
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_databases.go
@@ -0,0 +1,60 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// ListDatabases handles the full cycle dispatch and execution of a listDatabases command against the provided
+// topology.
+func ListDatabases(
+	ctx context.Context,
+	cmd command.ListDatabases,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	opts ...*options.ListDatabasesOptions,
+) (result.ListDatabases, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.ListDatabases{}, err
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return result.ListDatabases{}, err
+	}
+	defer conn.Close()
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.ListDatabases{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	ld := options.MergeListDatabasesOptions(opts...)
+	if ld.NameOnly != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"nameOnly", bsonx.Boolean(*ld.NameOnly)})
+	}
+
+	return cmd.RoundTrip(ctx, ss.Description(), conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_indexes.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_indexes.go
new file mode 100644
index 0000000..d40ef96
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/list_indexes.go
@@ -0,0 +1,105 @@
+// 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 driver
+
+import (
+	"context"
+
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// ListIndexes handles the full cycle dispatch and execution of a listIndexes command against the provided
+// topology.
+func ListIndexes(
+	ctx context.Context,
+	cmd command.ListIndexes,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	opts ...*options.ListIndexesOptions,
+) (*BatchCursor, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, err
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	if ss.Description().WireVersion.Max < 3 {
+		return legacyListIndexes(ctx, cmd, ss, conn, opts...)
+	}
+
+	lio := options.MergeListIndexesOptions(opts...)
+	if lio.BatchSize != nil {
+		elem := bsonx.Elem{"batchSize", bsonx.Int32(*lio.BatchSize)}
+		cmd.Opts = append(cmd.Opts, elem)
+		cmd.CursorOpts = append(cmd.CursorOpts, elem)
+	}
+	if lio.MaxTime != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"maxTimeMS", bsonx.Int64(int64(*lio.MaxTime / time.Millisecond))})
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	res, err := cmd.RoundTrip(ctx, ss.Description(), conn)
+	if err != nil {
+		closeImplicitSession(cmd.Session)
+		return nil, err
+	}
+
+	return NewBatchCursor(bsoncore.Document(res), cmd.Session, cmd.Clock, ss.Server, cmd.CursorOpts...)
+}
+
+func legacyListIndexes(
+	ctx context.Context,
+	cmd command.ListIndexes,
+	ss *topology.SelectedServer,
+	conn connection.Connection,
+	opts ...*options.ListIndexesOptions,
+) (*BatchCursor, error) {
+	lio := options.MergeListIndexesOptions(opts...)
+	ns := cmd.NS.DB + "." + cmd.NS.Collection
+
+	findCmd := command.Find{
+		NS: command.NewNamespace(cmd.NS.DB, "system.indexes"),
+		Filter: bsonx.Doc{
+			{"ns", bsonx.String(ns)},
+		},
+	}
+
+	findOpts := options.Find()
+	if lio.BatchSize != nil {
+		findOpts.SetBatchSize(*lio.BatchSize)
+	}
+	if lio.MaxTime != nil {
+		findOpts.SetMaxTime(*lio.MaxTime)
+	}
+
+	return legacyFind(ctx, findCmd, nil, ss, conn, findOpts)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/models.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/models.go
new file mode 100644
index 0000000..17ceb60
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/models.go
@@ -0,0 +1,81 @@
+// 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 driver
+
+import (
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+)
+
+// WriteModel is the interface satisfied by all models for bulk writes.
+type WriteModel interface {
+	writeModel()
+}
+
+// InsertOneModel is the write model for insert operations.
+type InsertOneModel struct {
+	Document interface{}
+}
+
+func (InsertOneModel) writeModel() {}
+
+// DeleteOneModel is the write model for delete operations.
+type DeleteOneModel struct {
+	Filter    interface{}
+	Collation *options.Collation
+}
+
+func (DeleteOneModel) writeModel() {}
+
+// DeleteManyModel is the write model for deleteMany operations.
+type DeleteManyModel struct {
+	Filter    interface{}
+	Collation *options.Collation
+}
+
+func (DeleteManyModel) writeModel() {}
+
+// UpdateModel contains the fields that are shared between the ReplaceOneModel, UpdateOneModel, and UpdateManyModel types
+type UpdateModel struct {
+	Collation *options.Collation
+	Upsert    bool
+	UpsertSet bool
+}
+
+// ReplaceOneModel is the write model for replace operations.
+type ReplaceOneModel struct {
+	Filter      interface{}
+	Replacement interface{}
+	UpdateModel
+}
+
+func (ReplaceOneModel) writeModel() {}
+
+// UpdateOneModel is the write model for update operations.
+type UpdateOneModel struct {
+	Filter interface{}
+	Update interface{}
+	// default is to not send a value. for servers < 3.6, error raised if value given. for unack writes using opcodes,
+	// error raised if value given
+	ArrayFilters    options.ArrayFilters
+	ArrayFiltersSet bool
+	UpdateModel
+}
+
+func (UpdateOneModel) writeModel() {}
+
+// UpdateManyModel is the write model for updateMany operations.
+type UpdateManyModel struct {
+	Filter interface{}
+	Update interface{}
+	// default is to not send a value. for servers < 3.6, error raised if value given. for unack writes using opcodes,
+	// error raised if value given
+	ArrayFilters    options.ArrayFilters
+	ArrayFiltersSet bool
+	UpdateModel
+}
+
+func (UpdateManyModel) writeModel() {}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/read.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/read.go
new file mode 100644
index 0000000..e31877c
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/read.go
@@ -0,0 +1,85 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// Read handles the full cycle dispatch and execution of a read command against the provided
+// topology.
+func Read(
+	ctx context.Context,
+	cmd command.Read,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+) (bson.Raw, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, err
+	}
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	if cmd.Session != nil && cmd.Session.TransactionRunning() {
+		// When command.read is directly used, this implies an operation level
+		// read preference, so we do not override it with the transaction read pref.
+		err = checkTransactionReadPref(cmd.ReadPref)
+
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	return cmd.RoundTrip(ctx, ss.Description(), conn)
+}
+
+func getReadPrefBasedOnTransaction(current *readpref.ReadPref, sess *session.Client) (*readpref.ReadPref, error) {
+	if sess != nil && sess.TransactionRunning() {
+		// Transaction's read preference always takes priority
+		current = sess.CurrentRp
+		err := checkTransactionReadPref(current)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return current, nil
+}
+
+func checkTransactionReadPref(pref *readpref.ReadPref) error {
+	if pref != nil && (pref.Mode() == readpref.SecondaryMode ||
+		pref.Mode() == readpref.SecondaryPreferredMode ||
+		pref.Mode() == readpref.NearestMode ||
+		pref.Mode() == readpref.PrimaryPreferredMode) {
+		return command.ErrNonPrimaryRP
+	}
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/read_cursor.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/read_cursor.go
new file mode 100644
index 0000000..fdc792c
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/read_cursor.go
@@ -0,0 +1,69 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// ReadCursor handles the full dispatch cycle and execution of a read command against the provided topology and returns
+// a Cursor over the resulting BSON reader.
+func ReadCursor(
+	ctx context.Context,
+	cmd command.Read,
+	topo *topology.Topology,
+	selecctor description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	cursorOpts ...bsonx.Elem,
+) (*BatchCursor, error) {
+
+	ss, err := topo.SelectServer(ctx, selecctor)
+	if err != nil {
+		return nil, err
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+	defer conn.Close()
+
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, conn)
+	if err != nil {
+		if cmd.Session != nil && cmd.Session.SessionType == session.Implicit {
+			cmd.Session.EndSession()
+		}
+		return nil, err
+	}
+
+	cursor, err := NewBatchCursor(bsoncore.Document(rdr), cmd.Session, cmd.Clock, ss.Server, cursorOpts...)
+	if err != nil {
+		if cmd.Session != nil && cmd.Session.SessionType == session.Implicit {
+			cmd.Session.EndSession()
+		}
+		return nil, err
+	}
+
+	return cursor, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/client_session.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/client_session.go
new file mode 100644
index 0000000..405d507
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/client_session.go
@@ -0,0 +1,347 @@
+// 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 session
+
+import (
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/primitive"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+)
+
+// ErrSessionEnded is returned when a client session is used after a call to endSession().
+var ErrSessionEnded = errors.New("ended session was used")
+
+// ErrNoTransactStarted is returned if a transaction operation is called when no transaction has started.
+var ErrNoTransactStarted = errors.New("no transaction started")
+
+// ErrTransactInProgress is returned if startTransaction() is called when a transaction is in progress.
+var ErrTransactInProgress = errors.New("transaction already in progress")
+
+// ErrAbortAfterCommit is returned when abort is called after a commit.
+var ErrAbortAfterCommit = errors.New("cannot call abortTransaction after calling commitTransaction")
+
+// ErrAbortTwice is returned if abort is called after transaction is already aborted.
+var ErrAbortTwice = errors.New("cannot call abortTransaction twice")
+
+// ErrCommitAfterAbort is returned if commit is called after an abort.
+var ErrCommitAfterAbort = errors.New("cannot call commitTransaction after calling abortTransaction")
+
+// ErrUnackWCUnsupported is returned if an unacknowledged write concern is supported for a transaciton.
+var ErrUnackWCUnsupported = errors.New("transactions do not support unacknowledged write concerns")
+
+// Type describes the type of the session
+type Type uint8
+
+// These constants are the valid types for a client session.
+const (
+	Explicit Type = iota
+	Implicit
+)
+
+// State indicates the state of the FSM.
+type state uint8
+
+// Client Session states
+const (
+	None state = iota
+	Starting
+	InProgress
+	Committed
+	Aborted
+)
+
+// Client is a session for clients to run commands.
+type Client struct {
+	*Server
+	ClientID       uuid.UUID
+	ClusterTime    bson.Raw
+	Consistent     bool // causal consistency
+	OperationTime  *primitive.Timestamp
+	SessionType    Type
+	Terminated     bool
+	RetryingCommit bool
+	Committing     bool
+	Aborting       bool
+	RetryWrite     bool
+
+	// options for the current transaction
+	// most recently set by transactionopt
+	CurrentRc *readconcern.ReadConcern
+	CurrentRp *readpref.ReadPref
+	CurrentWc *writeconcern.WriteConcern
+
+	// default transaction options
+	transactionRc *readconcern.ReadConcern
+	transactionRp *readpref.ReadPref
+	transactionWc *writeconcern.WriteConcern
+
+	pool  *Pool
+	state state
+}
+
+func getClusterTime(clusterTime bson.Raw) (uint32, uint32) {
+	if clusterTime == nil {
+		return 0, 0
+	}
+
+	clusterTimeVal, err := clusterTime.LookupErr("$clusterTime")
+	if err != nil {
+		return 0, 0
+	}
+
+	timestampVal, err := bson.Raw(clusterTimeVal.Value).LookupErr("clusterTime")
+	if err != nil {
+		return 0, 0
+	}
+
+	return timestampVal.Timestamp()
+}
+
+// MaxClusterTime compares 2 clusterTime documents and returns the document representing the highest cluster time.
+func MaxClusterTime(ct1, ct2 bson.Raw) bson.Raw {
+	epoch1, ord1 := getClusterTime(ct1)
+	epoch2, ord2 := getClusterTime(ct2)
+
+	if epoch1 > epoch2 {
+		return ct1
+	} else if epoch1 < epoch2 {
+		return ct2
+	} else if ord1 > ord2 {
+		return ct1
+	} else if ord1 < ord2 {
+		return ct2
+	}
+
+	return ct1
+}
+
+// NewClientSession creates a Client.
+func NewClientSession(pool *Pool, clientID uuid.UUID, sessionType Type, opts ...*ClientOptions) (*Client, error) {
+	c := &Client{
+		Consistent:  true, // set default
+		ClientID:    clientID,
+		SessionType: sessionType,
+		pool:        pool,
+	}
+
+	mergedOpts := mergeClientOptions(opts...)
+	if mergedOpts.CausalConsistency != nil {
+		c.Consistent = *mergedOpts.CausalConsistency
+	}
+	if mergedOpts.DefaultReadPreference != nil {
+		c.transactionRp = mergedOpts.DefaultReadPreference
+	}
+	if mergedOpts.DefaultReadConcern != nil {
+		c.transactionRc = mergedOpts.DefaultReadConcern
+	}
+	if mergedOpts.DefaultWriteConcern != nil {
+		c.transactionWc = mergedOpts.DefaultWriteConcern
+	}
+
+	servSess, err := pool.GetSession()
+	if err != nil {
+		return nil, err
+	}
+
+	c.Server = servSess
+
+	return c, nil
+}
+
+// AdvanceClusterTime updates the session's cluster time.
+func (c *Client) AdvanceClusterTime(clusterTime bson.Raw) error {
+	if c.Terminated {
+		return ErrSessionEnded
+	}
+	c.ClusterTime = MaxClusterTime(c.ClusterTime, clusterTime)
+	return nil
+}
+
+// AdvanceOperationTime updates the session's operation time.
+func (c *Client) AdvanceOperationTime(opTime *primitive.Timestamp) error {
+	if c.Terminated {
+		return ErrSessionEnded
+	}
+
+	if c.OperationTime == nil {
+		c.OperationTime = opTime
+		return nil
+	}
+
+	if opTime.T > c.OperationTime.T {
+		c.OperationTime = opTime
+	} else if (opTime.T == c.OperationTime.T) && (opTime.I > c.OperationTime.I) {
+		c.OperationTime = opTime
+	}
+
+	return nil
+}
+
+// UpdateUseTime updates the session's last used time.
+// Must be called whenver this session is used to send a command to the server.
+func (c *Client) UpdateUseTime() error {
+	if c.Terminated {
+		return ErrSessionEnded
+	}
+	c.updateUseTime()
+	return nil
+}
+
+// EndSession ends the session.
+func (c *Client) EndSession() {
+	if c.Terminated {
+		return
+	}
+
+	c.Terminated = true
+	c.pool.ReturnSession(c.Server)
+
+	return
+}
+
+// TransactionInProgress returns true if the client session is in an active transaction.
+func (c *Client) TransactionInProgress() bool {
+	return c.state == InProgress
+}
+
+// TransactionStarting returns true if the client session is starting a transaction.
+func (c *Client) TransactionStarting() bool {
+	return c.state == Starting
+}
+
+// TransactionRunning returns true if the client session has started the transaction
+// and it hasn't been committed or aborted
+func (c *Client) TransactionRunning() bool {
+	return c.state == Starting || c.state == InProgress
+}
+
+// TransactionCommitted returns true of the client session just committed a transaciton.
+func (c *Client) TransactionCommitted() bool {
+	return c.state == Committed
+}
+
+// CheckStartTransaction checks to see if allowed to start transaction and returns
+// an error if not allowed
+func (c *Client) CheckStartTransaction() error {
+	if c.state == InProgress || c.state == Starting {
+		return ErrTransactInProgress
+	}
+	return nil
+}
+
+// StartTransaction initializes the transaction options and advances the state machine.
+// It does not contact the server to start the transaction.
+func (c *Client) StartTransaction(opts *TransactionOptions) error {
+	err := c.CheckStartTransaction()
+	if err != nil {
+		return err
+	}
+
+	c.IncrementTxnNumber()
+	c.RetryingCommit = false
+
+	if opts != nil {
+		c.CurrentRc = opts.ReadConcern
+		c.CurrentRp = opts.ReadPreference
+		c.CurrentWc = opts.WriteConcern
+	}
+
+	if c.CurrentRc == nil {
+		c.CurrentRc = c.transactionRc
+	}
+
+	if c.CurrentRp == nil {
+		c.CurrentRp = c.transactionRp
+	}
+
+	if c.CurrentWc == nil {
+		c.CurrentWc = c.transactionWc
+	}
+
+	if !writeconcern.AckWrite(c.CurrentWc) {
+		c.clearTransactionOpts()
+		return ErrUnackWCUnsupported
+	}
+
+	c.state = Starting
+	return nil
+}
+
+// CheckCommitTransaction checks to see if allowed to commit transaction and returns
+// an error if not allowed.
+func (c *Client) CheckCommitTransaction() error {
+	if c.state == None {
+		return ErrNoTransactStarted
+	} else if c.state == Aborted {
+		return ErrCommitAfterAbort
+	}
+	return nil
+}
+
+// CommitTransaction updates the state for a successfully committed transaction and returns
+// an error if not permissible.  It does not actually perform the commit.
+func (c *Client) CommitTransaction() error {
+	err := c.CheckCommitTransaction()
+	if err != nil {
+		return err
+	}
+	c.state = Committed
+	return nil
+}
+
+// CheckAbortTransaction checks to see if allowed to abort transaction and returns
+// an error if not allowed.
+func (c *Client) CheckAbortTransaction() error {
+	if c.state == None {
+		return ErrNoTransactStarted
+	} else if c.state == Committed {
+		return ErrAbortAfterCommit
+	} else if c.state == Aborted {
+		return ErrAbortTwice
+	}
+	return nil
+}
+
+// AbortTransaction updates the state for a successfully committed transaction and returns
+// an error if not permissible.  It does not actually perform the abort.
+func (c *Client) AbortTransaction() error {
+	err := c.CheckAbortTransaction()
+	if err != nil {
+		return err
+	}
+	c.state = Aborted
+	c.clearTransactionOpts()
+	return nil
+}
+
+// ApplyCommand advances the state machine upon command execution.
+func (c *Client) ApplyCommand() {
+	if c.Committing {
+		// Do not change state if committing after already committed
+		return
+	}
+	if c.state == Starting {
+		c.state = InProgress
+	} else if c.state == Committed || c.state == Aborted {
+		c.clearTransactionOpts()
+		c.state = None
+	}
+}
+
+func (c *Client) clearTransactionOpts() {
+	c.RetryingCommit = false
+	c.Aborting = false
+	c.Committing = false
+	c.CurrentWc = nil
+	c.CurrentRp = nil
+	c.CurrentRc = nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/cluster_clock.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/cluster_clock.go
new file mode 100644
index 0000000..85376bf
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/cluster_clock.go
@@ -0,0 +1,36 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package session
+
+import (
+	"sync"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+)
+
+// ClusterClock represents a logical clock for keeping track of cluster time.
+type ClusterClock struct {
+	clusterTime bson.Raw
+	lock        sync.Mutex
+}
+
+// GetClusterTime returns the cluster's current time.
+func (cc *ClusterClock) GetClusterTime() bson.Raw {
+	var ct bson.Raw
+	cc.lock.Lock()
+	ct = cc.clusterTime
+	cc.lock.Unlock()
+
+	return ct
+}
+
+// AdvanceClusterTime updates the cluster's current time.
+func (cc *ClusterClock) AdvanceClusterTime(clusterTime bson.Raw) {
+	cc.lock.Lock()
+	cc.clusterTime = MaxClusterTime(cc.clusterTime, clusterTime)
+	cc.lock.Unlock()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/options.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/options.go
new file mode 100644
index 0000000..ac10518
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/options.go
@@ -0,0 +1,51 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package session
+
+import (
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+)
+
+// ClientOptions represents all possible options for creating a client session.
+type ClientOptions struct {
+	CausalConsistency     *bool
+	DefaultReadConcern    *readconcern.ReadConcern
+	DefaultWriteConcern   *writeconcern.WriteConcern
+	DefaultReadPreference *readpref.ReadPref
+}
+
+// TransactionOptions represents all possible options for starting a transaction in a session.
+type TransactionOptions struct {
+	ReadConcern    *readconcern.ReadConcern
+	WriteConcern   *writeconcern.WriteConcern
+	ReadPreference *readpref.ReadPref
+}
+
+func mergeClientOptions(opts ...*ClientOptions) *ClientOptions {
+	c := &ClientOptions{}
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.CausalConsistency != nil {
+			c.CausalConsistency = opt.CausalConsistency
+		}
+		if opt.DefaultReadConcern != nil {
+			c.DefaultReadConcern = opt.DefaultReadConcern
+		}
+		if opt.DefaultReadPreference != nil {
+			c.DefaultReadPreference = opt.DefaultReadPreference
+		}
+		if opt.DefaultWriteConcern != nil {
+			c.DefaultWriteConcern = opt.DefaultWriteConcern
+		}
+	}
+
+	return c
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/server_session.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/server_session.go
new file mode 100644
index 0000000..06aa51f
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/server_session.go
@@ -0,0 +1,63 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package session
+
+import (
+	"time"
+
+	"crypto/rand"
+
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+)
+
+var rander = rand.Reader
+
+// Server is an open session with the server.
+type Server struct {
+	SessionID bsonx.Doc
+	TxnNumber int64
+	LastUsed  time.Time
+}
+
+// returns whether or not a session has expired given a timeout in minutes
+// a session is considered expired if it has less than 1 minute left before becoming stale
+func (ss *Server) expired(timeoutMinutes uint32) bool {
+	if timeoutMinutes <= 0 {
+		return true
+	}
+	timeUnused := time.Since(ss.LastUsed).Minutes()
+	return timeUnused > float64(timeoutMinutes-1)
+}
+
+// update the last used time for this session.
+// must be called whenever this server session is used to send a command to the server.
+func (ss *Server) updateUseTime() {
+	ss.LastUsed = time.Now()
+}
+
+func newServerSession() (*Server, error) {
+	id, err := uuid.New()
+	if err != nil {
+		return nil, err
+	}
+
+	idDoc := bsonx.Doc{{"id", bsonx.Binary(UUIDSubtype, id[:])}}
+
+	return &Server{
+		SessionID: idDoc,
+		LastUsed:  time.Now(),
+	}, nil
+}
+
+// IncrementTxnNumber increments the transaction number.
+func (ss *Server) IncrementTxnNumber() {
+	ss.TxnNumber++
+}
+
+// UUIDSubtype is the BSON binary subtype that a UUID should be encoded as
+const UUIDSubtype byte = 4
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/session_pool.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/session_pool.go
new file mode 100644
index 0000000..af749da
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/session/session_pool.go
@@ -0,0 +1,175 @@
+// 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 session
+
+import (
+	"sync"
+
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// Node represents a server session in a linked list
+type Node struct {
+	*Server
+	next *Node
+	prev *Node
+}
+
+// Pool is a pool of server sessions that can be reused.
+type Pool struct {
+	descChan <-chan description.Topology
+	head     *Node
+	tail     *Node
+	timeout  uint32
+	mutex    sync.Mutex // mutex to protect list and sessionTimeout
+
+	checkedOut int // number of sessions checked out of pool
+}
+
+func (p *Pool) createServerSession() (*Server, error) {
+	s, err := newServerSession()
+	if err != nil {
+		return nil, err
+	}
+
+	p.checkedOut++
+	return s, nil
+}
+
+// NewPool creates a new server session pool
+func NewPool(descChan <-chan description.Topology) *Pool {
+	p := &Pool{
+		descChan: descChan,
+	}
+
+	return p
+}
+
+// assumes caller has mutex to protect the pool
+func (p *Pool) updateTimeout() {
+	select {
+	case newDesc := <-p.descChan:
+		p.timeout = newDesc.SessionTimeoutMinutes
+	default:
+		// no new description waiting
+	}
+}
+
+// GetSession retrieves an unexpired session from the pool.
+func (p *Pool) GetSession() (*Server, error) {
+	p.mutex.Lock() // prevent changing the linked list while seeing if sessions have expired
+	defer p.mutex.Unlock()
+
+	// empty pool
+	if p.head == nil && p.tail == nil {
+		return p.createServerSession()
+	}
+
+	p.updateTimeout()
+	for p.head != nil {
+		// pull session from head of queue and return if it is valid for at least 1 more minute
+		if p.head.expired(p.timeout) {
+			p.head = p.head.next
+			continue
+		}
+
+		// found unexpired session
+		session := p.head.Server
+		if p.head.next != nil {
+			p.head.next.prev = nil
+		}
+		if p.tail == p.head {
+			p.tail = nil
+			p.head = nil
+		} else {
+			p.head = p.head.next
+		}
+
+		p.checkedOut++
+		return session, nil
+	}
+
+	// no valid session found
+	p.tail = nil // empty list
+	return p.createServerSession()
+}
+
+// ReturnSession returns a session to the pool if it has not expired.
+func (p *Pool) ReturnSession(ss *Server) {
+	if ss == nil {
+		return
+	}
+
+	p.mutex.Lock()
+	defer p.mutex.Unlock()
+
+	p.checkedOut--
+	p.updateTimeout()
+	// check sessions at end of queue for expired
+	// stop checking after hitting the first valid session
+	for p.tail != nil && p.tail.expired(p.timeout) {
+		if p.tail.prev != nil {
+			p.tail.prev.next = nil
+		}
+		p.tail = p.tail.prev
+	}
+
+	// session expired
+	if ss.expired(p.timeout) {
+		return
+	}
+
+	newNode := &Node{
+		Server: ss,
+		next:   nil,
+		prev:   nil,
+	}
+
+	// empty list
+	if p.tail == nil {
+		p.head = newNode
+		p.tail = newNode
+		return
+	}
+
+	// at least 1 valid session in list
+	newNode.next = p.head
+	p.head.prev = newNode
+	p.head = newNode
+}
+
+// IDSlice returns a slice of session IDs for each session in the pool
+func (p *Pool) IDSlice() []bsonx.Doc {
+	p.mutex.Lock()
+	defer p.mutex.Unlock()
+
+	ids := []bsonx.Doc{}
+	for node := p.head; node != nil; node = node.next {
+		ids = append(ids, node.SessionID)
+	}
+
+	return ids
+}
+
+// String implements the Stringer interface
+func (p *Pool) String() string {
+	p.mutex.Lock()
+	defer p.mutex.Unlock()
+
+	s := ""
+	for head := p.head; head != nil; head = head.next {
+		s += head.SessionID.String() + "\n"
+	}
+
+	return s
+}
+
+// CheckedOut returns number of sessions checked out from pool.
+func (p *Pool) CheckedOut() int {
+	return p.checkedOut
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/connection.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/connection.go
new file mode 100644
index 0000000..d59f5b5
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/connection.go
@@ -0,0 +1,96 @@
+// 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 topology
+
+import (
+	"context"
+	"net"
+
+	"strings"
+
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// sconn is a wrapper around a connection.Connection. This type is returned by
+// a Server so that it can track network errors and when a non-timeout network
+// error is returned, the pool on the server can be cleared.
+type sconn struct {
+	connection.Connection
+	s  *Server
+	id uint64
+}
+
+var notMasterCodes = []int32{10107, 13435}
+var recoveringCodes = []int32{11600, 11602, 13436, 189, 91}
+
+func (sc *sconn) ReadWireMessage(ctx context.Context) (wiremessage.WireMessage, error) {
+	wm, err := sc.Connection.ReadWireMessage(ctx)
+	if err != nil {
+		sc.processErr(err)
+	} else {
+		e := command.DecodeError(wm)
+		sc.processErr(e)
+	}
+	return wm, err
+}
+
+func (sc *sconn) WriteWireMessage(ctx context.Context, wm wiremessage.WireMessage) error {
+	err := sc.Connection.WriteWireMessage(ctx, wm)
+	sc.processErr(err)
+	return err
+}
+
+func (sc *sconn) processErr(err error) {
+	// TODO(GODRIVER-524) handle the rest of sdam error handling
+	// Invalidate server description if not master or node recovering error occurs
+	if cerr, ok := err.(command.Error); ok && (isRecoveringError(cerr) || isNotMasterError(cerr)) {
+		desc := sc.s.Description()
+		desc.Kind = description.Unknown
+		desc.LastError = err
+		// updates description to unknown
+		sc.s.updateDescription(desc, false)
+	}
+
+	ne, ok := err.(connection.NetworkError)
+	if !ok {
+		return
+	}
+
+	if netErr, ok := ne.Wrapped.(net.Error); ok && netErr.Timeout() {
+		return
+	}
+	if ne.Wrapped == context.Canceled || ne.Wrapped == context.DeadlineExceeded {
+		return
+	}
+
+	desc := sc.s.Description()
+	desc.Kind = description.Unknown
+	desc.LastError = err
+	// updates description to unknown
+	sc.s.updateDescription(desc, false)
+}
+
+func isRecoveringError(err command.Error) bool {
+	for _, c := range recoveringCodes {
+		if c == err.Code {
+			return true
+		}
+	}
+	return strings.Contains(err.Error(), "node is recovering")
+}
+
+func isNotMasterError(err command.Error) bool {
+	for _, c := range notMasterCodes {
+		if c == err.Code {
+			return true
+		}
+	}
+	return strings.Contains(err.Error(), "not master")
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/fsm.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/fsm.go
new file mode 100644
index 0000000..3682b57
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/fsm.go
@@ -0,0 +1,350 @@
+// 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 topology
+
+import (
+	"bytes"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson/primitive"
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+var supportedWireVersions = description.NewVersionRange(2, 6)
+var minSupportedMongoDBVersion = "2.6"
+
+type fsm struct {
+	description.Topology
+	SetName       string
+	maxElectionID primitive.ObjectID
+	maxSetVersion uint32
+}
+
+func newFSM() *fsm {
+	return new(fsm)
+}
+
+// apply should operate on immutable TopologyDescriptions and Descriptions. This way we don't have to
+// lock for the entire time we're applying server description.
+func (f *fsm) apply(s description.Server) (description.Topology, error) {
+
+	newServers := make([]description.Server, len(f.Servers))
+	copy(newServers, f.Servers)
+
+	oldMinutes := f.SessionTimeoutMinutes
+	f.Topology = description.Topology{
+		Kind:    f.Kind,
+		Servers: newServers,
+	}
+
+	// For data bearing servers, set SessionTimeoutMinutes to the lowest among them
+	if oldMinutes == 0 {
+		// If timeout currently 0, check all servers to see if any still don't have a timeout
+		// If they all have timeout, pick the lowest.
+		timeout := s.SessionTimeoutMinutes
+		for _, server := range f.Servers {
+			if server.DataBearing() && server.SessionTimeoutMinutes < timeout {
+				timeout = server.SessionTimeoutMinutes
+			}
+		}
+		f.SessionTimeoutMinutes = timeout
+	} else {
+		if s.DataBearing() && oldMinutes > s.SessionTimeoutMinutes {
+			f.SessionTimeoutMinutes = s.SessionTimeoutMinutes
+		} else {
+			f.SessionTimeoutMinutes = oldMinutes
+		}
+	}
+
+	if _, ok := f.findServer(s.Addr); !ok {
+		return f.Topology, nil
+	}
+
+	if s.WireVersion != nil {
+		if s.WireVersion.Max < supportedWireVersions.Min {
+			return description.Topology{}, fmt.Errorf(
+				"server at %s reports wire version %d, but this version of the Go driver requires "+
+					"at least %d (MongoDB %s)",
+				s.Addr.String(),
+				s.WireVersion.Max,
+				supportedWireVersions.Min,
+				minSupportedMongoDBVersion,
+			)
+		}
+
+		if s.WireVersion.Min > supportedWireVersions.Max {
+			return description.Topology{}, fmt.Errorf(
+				"server at %s requires wire version %d, but this version of the Go driver only "+
+					"supports up to %d",
+				s.Addr.String(),
+				s.WireVersion.Min,
+				supportedWireVersions.Max,
+			)
+		}
+	}
+
+	switch f.Kind {
+	case description.Unknown:
+		f.applyToUnknown(s)
+	case description.Sharded:
+		f.applyToSharded(s)
+	case description.ReplicaSetNoPrimary:
+		f.applyToReplicaSetNoPrimary(s)
+	case description.ReplicaSetWithPrimary:
+		f.applyToReplicaSetWithPrimary(s)
+	case description.Single:
+		f.applyToSingle(s)
+	}
+
+	return f.Topology, nil
+}
+
+func (f *fsm) applyToReplicaSetNoPrimary(s description.Server) {
+	switch s.Kind {
+	case description.Standalone, description.Mongos:
+		f.removeServerByAddr(s.Addr)
+	case description.RSPrimary:
+		f.updateRSFromPrimary(s)
+	case description.RSSecondary, description.RSArbiter, description.RSMember:
+		f.updateRSWithoutPrimary(s)
+	case description.Unknown, description.RSGhost:
+		f.replaceServer(s)
+	}
+}
+
+func (f *fsm) applyToReplicaSetWithPrimary(s description.Server) {
+	switch s.Kind {
+	case description.Standalone, description.Mongos:
+		f.removeServerByAddr(s.Addr)
+		f.checkIfHasPrimary()
+	case description.RSPrimary:
+		f.updateRSFromPrimary(s)
+	case description.RSSecondary, description.RSArbiter, description.RSMember:
+		f.updateRSWithPrimaryFromMember(s)
+	case description.Unknown, description.RSGhost:
+		f.replaceServer(s)
+		f.checkIfHasPrimary()
+	}
+}
+
+func (f *fsm) applyToSharded(s description.Server) {
+	switch s.Kind {
+	case description.Mongos, description.Unknown:
+		f.replaceServer(s)
+	case description.Standalone, description.RSPrimary, description.RSSecondary, description.RSArbiter, description.RSMember, description.RSGhost:
+		f.removeServerByAddr(s.Addr)
+	}
+}
+
+func (f *fsm) applyToSingle(s description.Server) {
+	switch s.Kind {
+	case description.Unknown:
+		f.replaceServer(s)
+	case description.Standalone, description.Mongos:
+		if f.SetName != "" {
+			f.removeServerByAddr(s.Addr)
+			return
+		}
+
+		f.replaceServer(s)
+	case description.RSPrimary, description.RSSecondary, description.RSArbiter, description.RSMember, description.RSGhost:
+		if f.SetName != "" && f.SetName != s.SetName {
+			f.removeServerByAddr(s.Addr)
+			return
+		}
+
+		f.replaceServer(s)
+	}
+}
+
+func (f *fsm) applyToUnknown(s description.Server) {
+	switch s.Kind {
+	case description.Mongos:
+		f.setKind(description.Sharded)
+		f.replaceServer(s)
+	case description.RSPrimary:
+		f.updateRSFromPrimary(s)
+	case description.RSSecondary, description.RSArbiter, description.RSMember:
+		f.setKind(description.ReplicaSetNoPrimary)
+		f.updateRSWithoutPrimary(s)
+	case description.Standalone:
+		f.updateUnknownWithStandalone(s)
+	case description.Unknown, description.RSGhost:
+		f.replaceServer(s)
+	}
+}
+
+func (f *fsm) checkIfHasPrimary() {
+	if _, ok := f.findPrimary(); ok {
+		f.setKind(description.ReplicaSetWithPrimary)
+	} else {
+		f.setKind(description.ReplicaSetNoPrimary)
+	}
+}
+
+func (f *fsm) updateRSFromPrimary(s description.Server) {
+	if f.SetName == "" {
+		f.SetName = s.SetName
+	} else if f.SetName != s.SetName {
+		f.removeServerByAddr(s.Addr)
+		f.checkIfHasPrimary()
+		return
+	}
+
+	if s.SetVersion != 0 && !bytes.Equal(s.ElectionID[:], primitive.NilObjectID[:]) {
+		if f.maxSetVersion > s.SetVersion || bytes.Compare(f.maxElectionID[:], s.ElectionID[:]) == 1 {
+			f.replaceServer(description.Server{
+				Addr:      s.Addr,
+				LastError: fmt.Errorf("was a primary, but its set version or election id is stale"),
+			})
+			f.checkIfHasPrimary()
+			return
+		}
+
+		f.maxElectionID = s.ElectionID
+	}
+
+	if s.SetVersion > f.maxSetVersion {
+		f.maxSetVersion = s.SetVersion
+	}
+
+	if j, ok := f.findPrimary(); ok {
+		f.setServer(j, description.Server{
+			Addr:      f.Servers[j].Addr,
+			LastError: fmt.Errorf("was a primary, but a new primary was discovered"),
+		})
+	}
+
+	f.replaceServer(s)
+
+	for j := len(f.Servers) - 1; j >= 0; j-- {
+		found := false
+		for _, member := range s.Members {
+			if member == f.Servers[j].Addr {
+				found = true
+				break
+			}
+		}
+		if !found {
+			f.removeServer(j)
+		}
+	}
+
+	for _, member := range s.Members {
+		if _, ok := f.findServer(member); !ok {
+			f.addServer(member)
+		}
+	}
+
+	f.checkIfHasPrimary()
+}
+
+func (f *fsm) updateRSWithPrimaryFromMember(s description.Server) {
+	if f.SetName != s.SetName {
+		f.removeServerByAddr(s.Addr)
+		f.checkIfHasPrimary()
+		return
+	}
+
+	if s.Addr != s.CanonicalAddr {
+		f.removeServerByAddr(s.Addr)
+		f.checkIfHasPrimary()
+		return
+	}
+
+	f.replaceServer(s)
+
+	if _, ok := f.findPrimary(); !ok {
+		f.setKind(description.ReplicaSetNoPrimary)
+	}
+}
+
+func (f *fsm) updateRSWithoutPrimary(s description.Server) {
+	if f.SetName == "" {
+		f.SetName = s.SetName
+	} else if f.SetName != s.SetName {
+		f.removeServerByAddr(s.Addr)
+		return
+	}
+
+	for _, member := range s.Members {
+		if _, ok := f.findServer(member); !ok {
+			f.addServer(member)
+		}
+	}
+
+	if s.Addr != s.CanonicalAddr {
+		f.removeServerByAddr(s.Addr)
+		return
+	}
+
+	f.replaceServer(s)
+}
+
+func (f *fsm) updateUnknownWithStandalone(s description.Server) {
+	if len(f.Servers) > 1 {
+		f.removeServerByAddr(s.Addr)
+		return
+	}
+
+	f.setKind(description.Single)
+	f.replaceServer(s)
+}
+
+func (f *fsm) addServer(addr address.Address) {
+	f.Servers = append(f.Servers, description.Server{
+		Addr: addr.Canonicalize(),
+	})
+}
+
+func (f *fsm) findPrimary() (int, bool) {
+	for i, s := range f.Servers {
+		if s.Kind == description.RSPrimary {
+			return i, true
+		}
+	}
+
+	return 0, false
+}
+
+func (f *fsm) findServer(addr address.Address) (int, bool) {
+	canon := addr.Canonicalize()
+	for i, s := range f.Servers {
+		if canon == s.Addr {
+			return i, true
+		}
+	}
+
+	return 0, false
+}
+
+func (f *fsm) removeServer(i int) {
+	f.Servers = append(f.Servers[:i], f.Servers[i+1:]...)
+}
+
+func (f *fsm) removeServerByAddr(addr address.Address) {
+	if i, ok := f.findServer(addr); ok {
+		f.removeServer(i)
+	}
+}
+
+func (f *fsm) replaceServer(s description.Server) bool {
+	if i, ok := f.findServer(s.Addr); ok {
+		f.setServer(i, s)
+		return true
+	}
+	return false
+}
+
+func (f *fsm) setServer(i int, s description.Server) {
+	f.Servers[i] = s
+}
+
+func (f *fsm) setKind(k description.TopologyKind) {
+	f.Kind = k
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/server.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/server.go
new file mode 100644
index 0000000..3a7ace2
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/server.go
@@ -0,0 +1,506 @@
+// 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 topology
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"math"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/event"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/auth"
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+const minHeartbeatInterval = 500 * time.Millisecond
+const connectionSemaphoreSize = math.MaxInt64
+
+// ErrServerClosed occurs when an attempt to get a connection is made after
+// the server has been closed.
+var ErrServerClosed = errors.New("server is closed")
+
+// ErrServerConnected occurs when at attempt to connect is made after a server
+// has already been connected.
+var ErrServerConnected = errors.New("server is connected")
+
+// SelectedServer represents a specific server that was selected during server selection.
+// It contains the kind of the typology it was selected from.
+type SelectedServer struct {
+	*Server
+
+	Kind description.TopologyKind
+}
+
+// Description returns a description of the server as of the last heartbeat.
+func (ss *SelectedServer) Description() description.SelectedServer {
+	sdesc := ss.Server.Description()
+	return description.SelectedServer{
+		Server: sdesc,
+		Kind:   ss.Kind,
+	}
+}
+
+// These constants represent the connection states of a server.
+const (
+	disconnected int32 = iota
+	disconnecting
+	connected
+	connecting
+)
+
+func connectionStateString(state int32) string {
+	switch state {
+	case 0:
+		return "Disconnected"
+	case 1:
+		return "Disconnecting"
+	case 2:
+		return "Connected"
+	case 3:
+		return "Connecting"
+	}
+
+	return ""
+}
+
+// Server is a single server within a topology.
+type Server struct {
+	cfg     *serverConfig
+	address address.Address
+
+	connectionstate int32
+	done            chan struct{}
+	checkNow        chan struct{}
+	closewg         sync.WaitGroup
+	pool            connection.Pool
+
+	desc atomic.Value // holds a description.Server
+
+	averageRTTSet bool
+	averageRTT    time.Duration
+
+	subLock             sync.Mutex
+	subscribers         map[uint64]chan description.Server
+	currentSubscriberID uint64
+
+	subscriptionsClosed bool
+}
+
+// ConnectServer creates a new Server and then initializes it using the
+// Connect method.
+func ConnectServer(ctx context.Context, addr address.Address, opts ...ServerOption) (*Server, error) {
+	srvr, err := NewServer(addr, opts...)
+	if err != nil {
+		return nil, err
+	}
+	err = srvr.Connect(ctx)
+	if err != nil {
+		return nil, err
+	}
+	return srvr, nil
+}
+
+// NewServer creates a new server. The mongodb server at the address will be monitored
+// on an internal monitoring goroutine.
+func NewServer(addr address.Address, opts ...ServerOption) (*Server, error) {
+	cfg, err := newServerConfig(opts...)
+	if err != nil {
+		return nil, err
+	}
+
+	s := &Server{
+		cfg:     cfg,
+		address: addr,
+
+		done:     make(chan struct{}),
+		checkNow: make(chan struct{}, 1),
+
+		subscribers: make(map[uint64]chan description.Server),
+	}
+	s.desc.Store(description.Server{Addr: addr})
+
+	var maxConns uint64
+	if cfg.maxConns == 0 {
+		maxConns = math.MaxInt64
+	} else {
+		maxConns = uint64(cfg.maxConns)
+	}
+
+	s.pool, err = connection.NewPool(addr, uint64(cfg.maxIdleConns), maxConns, cfg.connectionOpts...)
+	if err != nil {
+		return nil, err
+	}
+
+	return s, nil
+}
+
+// Connect initialzies the Server by starting background monitoring goroutines.
+// This method must be called before a Server can be used.
+func (s *Server) Connect(ctx context.Context) error {
+	if !atomic.CompareAndSwapInt32(&s.connectionstate, disconnected, connected) {
+		return ErrServerConnected
+	}
+	s.desc.Store(description.Server{Addr: s.address})
+	go s.update()
+	s.closewg.Add(1)
+	return s.pool.Connect(ctx)
+}
+
+// Disconnect closes sockets to the server referenced by this Server.
+// Subscriptions to this Server will be closed. Disconnect will shutdown
+// any monitoring goroutines, close the idle connection pool, and will
+// wait until all the in use connections have been returned to the connection
+// pool and are closed before returning. If the context expires via
+// cancellation, deadline, or timeout before the in use connections have been
+// returned, the in use connections will be closed, resulting in the failure of
+// any in flight read or write operations. If this method returns with no
+// errors, all connections associated with this Server have been closed.
+func (s *Server) Disconnect(ctx context.Context) error {
+	if !atomic.CompareAndSwapInt32(&s.connectionstate, connected, disconnecting) {
+		return ErrServerClosed
+	}
+
+	// For every call to Connect there must be at least 1 goroutine that is
+	// waiting on the done channel.
+	s.done <- struct{}{}
+	err := s.pool.Disconnect(ctx)
+	if err != nil {
+		return err
+	}
+
+	s.closewg.Wait()
+	atomic.StoreInt32(&s.connectionstate, disconnected)
+
+	return nil
+}
+
+// Connection gets a connection to the server.
+func (s *Server) Connection(ctx context.Context) (connection.Connection, error) {
+	if atomic.LoadInt32(&s.connectionstate) != connected {
+		return nil, ErrServerClosed
+	}
+	conn, desc, err := s.pool.Get(ctx)
+	if err != nil {
+		if _, ok := err.(*auth.Error); ok {
+			// authentication error --> drain connection
+			_ = s.pool.Drain()
+		}
+		if _, ok := err.(*connection.NetworkError); ok {
+			// update description to unknown and clears the connection pool
+			if desc != nil {
+				desc.Kind = description.Unknown
+				desc.LastError = err
+				s.updateDescription(*desc, false)
+			} else {
+				_ = s.pool.Drain()
+			}
+		}
+		return nil, err
+	}
+	if desc != nil {
+		go s.updateDescription(*desc, false)
+	}
+	sc := &sconn{Connection: conn, s: s}
+	return sc, nil
+}
+
+// Description returns a description of the server as of the last heartbeat.
+func (s *Server) Description() description.Server {
+	return s.desc.Load().(description.Server)
+}
+
+// SelectedDescription returns a description.SelectedServer with a Kind of
+// Single. This can be used when performing tasks like monitoring a batch
+// of servers and you want to run one off commands against those servers.
+func (s *Server) SelectedDescription() description.SelectedServer {
+	sdesc := s.Description()
+	return description.SelectedServer{
+		Server: sdesc,
+		Kind:   description.Single,
+	}
+}
+
+// Subscribe returns a ServerSubscription which has a channel on which all
+// updated server descriptions will be sent. The channel will have a buffer
+// size of one, and will be pre-populated with the current description.
+func (s *Server) Subscribe() (*ServerSubscription, error) {
+	if atomic.LoadInt32(&s.connectionstate) != connected {
+		return nil, ErrSubscribeAfterClosed
+	}
+	ch := make(chan description.Server, 1)
+	ch <- s.desc.Load().(description.Server)
+
+	s.subLock.Lock()
+	defer s.subLock.Unlock()
+	if s.subscriptionsClosed {
+		return nil, ErrSubscribeAfterClosed
+	}
+	id := s.currentSubscriberID
+	s.subscribers[id] = ch
+	s.currentSubscriberID++
+
+	ss := &ServerSubscription{
+		C:  ch,
+		s:  s,
+		id: id,
+	}
+
+	return ss, nil
+}
+
+// RequestImmediateCheck will cause the server to send a heartbeat immediately
+// instead of waiting for the heartbeat timeout.
+func (s *Server) RequestImmediateCheck() {
+	select {
+	case s.checkNow <- struct{}{}:
+	default:
+	}
+}
+
+// update handles performing heartbeats and updating any subscribers of the
+// newest description.Server retrieved.
+func (s *Server) update() {
+	defer s.closewg.Done()
+	heartbeatTicker := time.NewTicker(s.cfg.heartbeatInterval)
+	rateLimiter := time.NewTicker(minHeartbeatInterval)
+	defer heartbeatTicker.Stop()
+	defer rateLimiter.Stop()
+	checkNow := s.checkNow
+	done := s.done
+
+	var doneOnce bool
+	defer func() {
+		if r := recover(); r != nil {
+			if doneOnce {
+				return
+			}
+			// We keep this goroutine alive attempting to read from the done channel.
+			<-done
+		}
+	}()
+
+	var conn connection.Connection
+	var desc description.Server
+
+	desc, conn = s.heartbeat(nil)
+	s.updateDescription(desc, true)
+
+	closeServer := func() {
+		doneOnce = true
+		s.subLock.Lock()
+		for id, c := range s.subscribers {
+			close(c)
+			delete(s.subscribers, id)
+		}
+		s.subscriptionsClosed = true
+		s.subLock.Unlock()
+		if conn == nil {
+			return
+		}
+		conn.Close()
+	}
+	for {
+		select {
+		case <-heartbeatTicker.C:
+		case <-checkNow:
+		case <-done:
+			closeServer()
+			return
+		}
+
+		select {
+		case <-rateLimiter.C:
+		case <-done:
+			closeServer()
+			return
+		}
+
+		desc, conn = s.heartbeat(conn)
+		s.updateDescription(desc, false)
+	}
+}
+
+// updateDescription handles updating the description on the Server, notifying
+// subscribers, and potentially draining the connection pool. The initial
+// parameter is used to determine if this is the first description from the
+// server.
+func (s *Server) updateDescription(desc description.Server, initial bool) {
+	defer func() {
+		//  ¯\_(ツ)_/¯
+		_ = recover()
+	}()
+	s.desc.Store(desc)
+
+	s.subLock.Lock()
+	for _, c := range s.subscribers {
+		select {
+		// drain the channel if it isn't empty
+		case <-c:
+		default:
+		}
+		c <- desc
+	}
+	s.subLock.Unlock()
+
+	if initial {
+		// We don't clear the pool on the first update on the description.
+		return
+	}
+
+	switch desc.Kind {
+	case description.Unknown:
+		_ = s.pool.Drain()
+	}
+}
+
+// heartbeat sends a heartbeat to the server using the given connection. The connection can be nil.
+func (s *Server) heartbeat(conn connection.Connection) (description.Server, connection.Connection) {
+	const maxRetry = 2
+	var saved error
+	var desc description.Server
+	var set bool
+	var err error
+	ctx := context.Background()
+
+	for i := 1; i <= maxRetry; i++ {
+		if conn != nil && conn.Expired() {
+			conn.Close()
+			conn = nil
+		}
+
+		if conn == nil {
+			opts := []connection.Option{
+				connection.WithConnectTimeout(func(time.Duration) time.Duration { return s.cfg.heartbeatTimeout }),
+				connection.WithReadTimeout(func(time.Duration) time.Duration { return s.cfg.heartbeatTimeout }),
+				connection.WithWriteTimeout(func(time.Duration) time.Duration { return s.cfg.heartbeatTimeout }),
+			}
+			opts = append(opts, s.cfg.connectionOpts...)
+			// We override whatever handshaker is currently attached to the options with an empty
+			// one because need to make sure we don't do auth.
+			opts = append(opts, connection.WithHandshaker(func(h connection.Handshaker) connection.Handshaker {
+				return nil
+			}))
+
+			// Override any command monitors specified in options with nil to avoid monitoring heartbeats.
+			opts = append(opts, connection.WithMonitor(func(*event.CommandMonitor) *event.CommandMonitor {
+				return nil
+			}))
+			conn, _, err = connection.New(ctx, s.address, opts...)
+			if err != nil {
+				saved = err
+				if conn != nil {
+					conn.Close()
+				}
+				conn = nil
+				continue
+			}
+		}
+
+		now := time.Now()
+
+		isMasterCmd := &command.IsMaster{Compressors: s.cfg.compressionOpts}
+		isMaster, err := isMasterCmd.RoundTrip(ctx, conn)
+		if err != nil {
+			saved = err
+			conn.Close()
+			conn = nil
+			continue
+		}
+
+		clusterTime := isMaster.ClusterTime
+		if s.cfg.clock != nil {
+			s.cfg.clock.AdvanceClusterTime(clusterTime)
+		}
+
+		delay := time.Since(now)
+		desc = description.NewServer(s.address, isMaster).SetAverageRTT(s.updateAverageRTT(delay))
+		desc.HeartbeatInterval = s.cfg.heartbeatInterval
+		set = true
+
+		break
+	}
+
+	if !set {
+		desc = description.Server{
+			Addr:      s.address,
+			LastError: saved,
+		}
+	}
+
+	return desc, conn
+}
+
+func (s *Server) updateAverageRTT(delay time.Duration) time.Duration {
+	if !s.averageRTTSet {
+		s.averageRTT = delay
+	} else {
+		alpha := 0.2
+		s.averageRTT = time.Duration(alpha*float64(delay) + (1-alpha)*float64(s.averageRTT))
+	}
+	return s.averageRTT
+}
+
+// Drain will drain the connection pool of this server. This is mainly here so the
+// pool for the server doesn't need to be directly exposed and so that when an error
+// is returned from reading or writing, a client can drain the pool for this server.
+// This is exposed here so we don't have to wrap the Connection type and sniff responses
+// for errors that would cause the pool to be drained, which can in turn centralize the
+// logic for handling errors in the Client type.
+func (s *Server) Drain() error { return s.pool.Drain() }
+
+// String implements the Stringer interface.
+func (s *Server) String() string {
+	desc := s.Description()
+	str := fmt.Sprintf("Addr: %s, Type: %s, State: %s",
+		s.address, desc.Kind, connectionStateString(s.connectionstate))
+	if len(desc.Tags) != 0 {
+		str += fmt.Sprintf(", Tag sets: %s", desc.Tags)
+	}
+	if s.connectionstate == connected {
+		str += fmt.Sprintf(", Avergage RTT: %d", s.averageRTT)
+	}
+	if desc.LastError != nil {
+		str += fmt.Sprintf(", Last error: %s", desc.LastError)
+	}
+
+	return str
+}
+
+// ServerSubscription represents a subscription to the description.Server updates for
+// a specific server.
+type ServerSubscription struct {
+	C  <-chan description.Server
+	s  *Server
+	id uint64
+}
+
+// Unsubscribe unsubscribes this ServerSubscription from updates and closes the
+// subscription channel.
+func (ss *ServerSubscription) Unsubscribe() error {
+	ss.s.subLock.Lock()
+	defer ss.s.subLock.Unlock()
+	if ss.s.subscriptionsClosed {
+		return nil
+	}
+
+	ch, ok := ss.s.subscribers[ss.id]
+	if !ok {
+		return nil
+	}
+
+	close(ch)
+	delete(ss.s.subscribers, ss.id)
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/server_options.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/server_options.go
new file mode 100644
index 0000000..0ebbecf
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/server_options.go
@@ -0,0 +1,121 @@
+// 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 topology
+
+import (
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+)
+
+var defaultRegistry = bson.NewRegistryBuilder().Build()
+
+type serverConfig struct {
+	clock             *session.ClusterClock
+	compressionOpts   []string
+	connectionOpts    []connection.Option
+	appname           string
+	heartbeatInterval time.Duration
+	heartbeatTimeout  time.Duration
+	maxConns          uint16
+	maxIdleConns      uint16
+	registry          *bsoncodec.Registry
+}
+
+func newServerConfig(opts ...ServerOption) (*serverConfig, error) {
+	cfg := &serverConfig{
+		heartbeatInterval: 10 * time.Second,
+		heartbeatTimeout:  10 * time.Second,
+		maxConns:          100,
+		maxIdleConns:      100,
+		registry:          defaultRegistry,
+	}
+
+	for _, opt := range opts {
+		err := opt(cfg)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return cfg, nil
+}
+
+// ServerOption configures a server.
+type ServerOption func(*serverConfig) error
+
+// WithConnectionOptions configures the server's connections.
+func WithConnectionOptions(fn func(...connection.Option) []connection.Option) ServerOption {
+	return func(cfg *serverConfig) error {
+		cfg.connectionOpts = fn(cfg.connectionOpts...)
+		return nil
+	}
+}
+
+// WithCompressionOptions configures the server's compressors.
+func WithCompressionOptions(fn func(...string) []string) ServerOption {
+	return func(cfg *serverConfig) error {
+		cfg.compressionOpts = fn(cfg.compressionOpts...)
+		return nil
+	}
+}
+
+// WithHeartbeatInterval configures a server's heartbeat interval.
+func WithHeartbeatInterval(fn func(time.Duration) time.Duration) ServerOption {
+	return func(cfg *serverConfig) error {
+		cfg.heartbeatInterval = fn(cfg.heartbeatInterval)
+		return nil
+	}
+}
+
+// WithHeartbeatTimeout configures how long to wait for a heartbeat socket to
+// connection.
+func WithHeartbeatTimeout(fn func(time.Duration) time.Duration) ServerOption {
+	return func(cfg *serverConfig) error {
+		cfg.heartbeatTimeout = fn(cfg.heartbeatTimeout)
+		return nil
+	}
+}
+
+// WithMaxConnections configures the maximum number of connections to allow for
+// a given server. If max is 0, then there is no upper limit to the number of
+// connections.
+func WithMaxConnections(fn func(uint16) uint16) ServerOption {
+	return func(cfg *serverConfig) error {
+		cfg.maxConns = fn(cfg.maxConns)
+		return nil
+	}
+}
+
+// WithMaxIdleConnections configures the maximum number of idle connections
+// allowed for the server.
+func WithMaxIdleConnections(fn func(uint16) uint16) ServerOption {
+	return func(cfg *serverConfig) error {
+		cfg.maxIdleConns = fn(cfg.maxIdleConns)
+		return nil
+	}
+}
+
+// WithClock configures the ClusterClock for the server to use.
+func WithClock(fn func(clock *session.ClusterClock) *session.ClusterClock) ServerOption {
+	return func(cfg *serverConfig) error {
+		cfg.clock = fn(cfg.clock)
+		return nil
+	}
+}
+
+// WithRegistry configures the registry for the server to use when creating
+// cursors.
+func WithRegistry(fn func(*bsoncodec.Registry) *bsoncodec.Registry) ServerOption {
+	return func(cfg *serverConfig) error {
+		cfg.registry = fn(cfg.registry)
+		return nil
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/topology.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/topology.go
new file mode 100644
index 0000000..09a319c
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/topology.go
@@ -0,0 +1,471 @@
+// 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 topology contains types that handles the discovery, monitoring, and selection
+// of servers. This package is designed to expose enough inner workings of service discovery
+// and monitoring to allow low level applications to have fine grained control, while hiding
+// most of the detailed implementation of the algorithms.
+package topology
+
+import (
+	"context"
+	"errors"
+	"math/rand"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// ErrSubscribeAfterClosed is returned when a user attempts to subscribe to a
+// closed Server or Topology.
+var ErrSubscribeAfterClosed = errors.New("cannot subscribe after close")
+
+// ErrTopologyClosed is returned when a user attempts to call a method on a
+// closed Topology.
+var ErrTopologyClosed = errors.New("topology is closed")
+
+// ErrTopologyConnected is returned whena  user attempts to connect to an
+// already connected Topology.
+var ErrTopologyConnected = errors.New("topology is connected or connecting")
+
+// ErrServerSelectionTimeout is returned from server selection when the server
+// selection process took longer than allowed by the timeout.
+var ErrServerSelectionTimeout = errors.New("server selection timeout")
+
+// MonitorMode represents the way in which a server is monitored.
+type MonitorMode uint8
+
+// These constants are the available monitoring modes.
+const (
+	AutomaticMode MonitorMode = iota
+	SingleMode
+)
+
+// Topology represents a MongoDB deployment.
+type Topology struct {
+	registry *bsoncodec.Registry
+
+	connectionstate int32
+
+	cfg *config
+
+	desc atomic.Value // holds a description.Topology
+
+	done chan struct{}
+
+	fsm       *fsm
+	changes   chan description.Server
+	changeswg sync.WaitGroup
+
+	SessionPool *session.Pool
+
+	// This should really be encapsulated into it's own type. This will likely
+	// require a redesign so we can share a minimum of data between the
+	// subscribers and the topology.
+	subscribers         map[uint64]chan description.Topology
+	currentSubscriberID uint64
+	subscriptionsClosed bool
+	subLock             sync.Mutex
+
+	// We should redesign how we connect and handle individal servers. This is
+	// too difficult to maintain and it's rather easy to accidentally access
+	// the servers without acquiring the lock or checking if the servers are
+	// closed. This lock should also be an RWMutex.
+	serversLock   sync.Mutex
+	serversClosed bool
+	servers       map[address.Address]*Server
+
+	wg sync.WaitGroup
+}
+
+// New creates a new topology.
+func New(opts ...Option) (*Topology, error) {
+	cfg, err := newConfig(opts...)
+	if err != nil {
+		return nil, err
+	}
+
+	t := &Topology{
+		cfg:         cfg,
+		done:        make(chan struct{}),
+		fsm:         newFSM(),
+		changes:     make(chan description.Server),
+		subscribers: make(map[uint64]chan description.Topology),
+		servers:     make(map[address.Address]*Server),
+	}
+	t.desc.Store(description.Topology{})
+
+	if cfg.replicaSetName != "" {
+		t.fsm.SetName = cfg.replicaSetName
+		t.fsm.Kind = description.ReplicaSetNoPrimary
+	}
+
+	if cfg.mode == SingleMode {
+		t.fsm.Kind = description.Single
+	}
+
+	return t, nil
+}
+
+// Connect initializes a Topology and starts the monitoring process. This function
+// must be called to properly monitor the topology.
+func (t *Topology) Connect(ctx context.Context) error {
+	if !atomic.CompareAndSwapInt32(&t.connectionstate, disconnected, connecting) {
+		return ErrTopologyConnected
+	}
+
+	t.desc.Store(description.Topology{})
+	var err error
+	t.serversLock.Lock()
+	for _, a := range t.cfg.seedList {
+		addr := address.Address(a).Canonicalize()
+		t.fsm.Servers = append(t.fsm.Servers, description.Server{Addr: addr})
+		err = t.addServer(ctx, addr)
+	}
+	t.serversLock.Unlock()
+
+	go t.update()
+	t.changeswg.Add(1)
+
+	t.subscriptionsClosed = false // explicitly set in case topology was disconnected and then reconnected
+
+	atomic.StoreInt32(&t.connectionstate, connected)
+
+	// After connection, make a subscription to keep the pool updated
+	sub, err := t.Subscribe()
+	t.SessionPool = session.NewPool(sub.C)
+	return err
+}
+
+// Disconnect closes the topology. It stops the monitoring thread and
+// closes all open subscriptions.
+func (t *Topology) Disconnect(ctx context.Context) error {
+	if !atomic.CompareAndSwapInt32(&t.connectionstate, connected, disconnecting) {
+		return ErrTopologyClosed
+	}
+
+	t.serversLock.Lock()
+	t.serversClosed = true
+	for addr, server := range t.servers {
+		t.removeServer(ctx, addr, server)
+	}
+	t.serversLock.Unlock()
+
+	t.wg.Wait()
+	t.done <- struct{}{}
+	t.changeswg.Wait()
+
+	t.desc.Store(description.Topology{})
+
+	atomic.StoreInt32(&t.connectionstate, disconnected)
+	return nil
+}
+
+// Description returns a description of the topology.
+func (t *Topology) Description() description.Topology {
+	td, ok := t.desc.Load().(description.Topology)
+	if !ok {
+		td = description.Topology{}
+	}
+	return td
+}
+
+// Subscribe returns a Subscription on which all updated description.Topologys
+// will be sent. The channel of the subscription will have a buffer size of one,
+// and will be pre-populated with the current description.Topology.
+func (t *Topology) Subscribe() (*Subscription, error) {
+	if atomic.LoadInt32(&t.connectionstate) != connected {
+		return nil, errors.New("cannot subscribe to Topology that is not connected")
+	}
+	ch := make(chan description.Topology, 1)
+	td, ok := t.desc.Load().(description.Topology)
+	if !ok {
+		td = description.Topology{}
+	}
+	ch <- td
+
+	t.subLock.Lock()
+	defer t.subLock.Unlock()
+	if t.subscriptionsClosed {
+		return nil, ErrSubscribeAfterClosed
+	}
+	id := t.currentSubscriberID
+	t.subscribers[id] = ch
+	t.currentSubscriberID++
+
+	return &Subscription{
+		C:  ch,
+		t:  t,
+		id: id,
+	}, nil
+}
+
+// RequestImmediateCheck will send heartbeats to all the servers in the
+// topology right away, instead of waiting for the heartbeat timeout.
+func (t *Topology) RequestImmediateCheck() {
+	if atomic.LoadInt32(&t.connectionstate) != connected {
+		return
+	}
+	t.serversLock.Lock()
+	for _, server := range t.servers {
+		server.RequestImmediateCheck()
+	}
+	t.serversLock.Unlock()
+}
+
+// SupportsSessions returns true if the topology supports sessions.
+func (t *Topology) SupportsSessions() bool {
+	return t.Description().SessionTimeoutMinutes != 0 && t.Description().Kind != description.Single
+}
+
+// SelectServer selects a server given a selector.SelectServer complies with the
+// server selection spec, and will time out after severSelectionTimeout or when the
+// parent context is done.
+func (t *Topology) SelectServer(ctx context.Context, ss description.ServerSelector) (*SelectedServer, error) {
+	if atomic.LoadInt32(&t.connectionstate) != connected {
+		return nil, ErrTopologyClosed
+	}
+	var ssTimeoutCh <-chan time.Time
+
+	if t.cfg.serverSelectionTimeout > 0 {
+		ssTimeout := time.NewTimer(t.cfg.serverSelectionTimeout)
+		ssTimeoutCh = ssTimeout.C
+		defer ssTimeout.Stop()
+	}
+
+	sub, err := t.Subscribe()
+	if err != nil {
+		return nil, err
+	}
+	defer sub.Unsubscribe()
+
+	for {
+		suitable, err := t.selectServer(ctx, sub.C, ss, ssTimeoutCh)
+		if err != nil {
+			return nil, err
+		}
+
+		selected := suitable[rand.Intn(len(suitable))]
+		selectedS, err := t.FindServer(selected)
+		switch {
+		case err != nil:
+			return nil, err
+		case selectedS != nil:
+			return selectedS, nil
+		default:
+			// We don't have an actual server for the provided description.
+			// This could happen for a number of reasons, including that the
+			// server has since stopped being a part of this topology, or that
+			// the server selector returned no suitable servers.
+		}
+	}
+}
+
+// FindServer will attempt to find a server that fits the given server description.
+// This method will return nil, nil if a matching server could not be found.
+func (t *Topology) FindServer(selected description.Server) (*SelectedServer, error) {
+	if atomic.LoadInt32(&t.connectionstate) != connected {
+		return nil, ErrTopologyClosed
+	}
+	t.serversLock.Lock()
+	defer t.serversLock.Unlock()
+	server, ok := t.servers[selected.Addr]
+	if !ok {
+		return nil, nil
+	}
+
+	desc := t.Description()
+	return &SelectedServer{
+		Server: server,
+		Kind:   desc.Kind,
+	}, nil
+}
+
+func wrapServerSelectionError(err error, t *Topology) error {
+	return fmt.Errorf("server selection error: %v\ncurrent topology: %s", err, t.String())
+}
+
+// selectServer is the core piece of server selection. It handles getting
+// topology descriptions and running sever selection on those descriptions.
+func (t *Topology) selectServer(ctx context.Context, subscriptionCh <-chan description.Topology, ss description.ServerSelector, timeoutCh <-chan time.Time) ([]description.Server, error) {
+	var current description.Topology
+	for {
+		select {
+		case <-ctx.Done():
+			return nil, ctx.Err()
+		case <-timeoutCh:
+			return nil, wrapServerSelectionError(ErrServerSelectionTimeout, t)
+		case current = <-subscriptionCh:
+		}
+
+		var allowed []description.Server
+		for _, s := range current.Servers {
+			if s.Kind != description.Unknown {
+				allowed = append(allowed, s)
+			}
+		}
+
+		suitable, err := ss.SelectServer(current, allowed)
+		if err != nil {
+			return nil, wrapServerSelectionError(err, t)
+		}
+
+		if len(suitable) > 0 {
+			return suitable, nil
+		}
+
+		t.RequestImmediateCheck()
+	}
+}
+
+func (t *Topology) update() {
+	defer t.changeswg.Done()
+	defer func() {
+		//  ¯\_(ツ)_/¯
+		if r := recover(); r != nil {
+			<-t.done
+		}
+	}()
+
+	for {
+		select {
+		case change := <-t.changes:
+			current, err := t.apply(context.TODO(), change)
+			if err != nil {
+				continue
+			}
+
+			t.desc.Store(current)
+			t.subLock.Lock()
+			for _, ch := range t.subscribers {
+				// We drain the description if there's one in the channel
+				select {
+				case <-ch:
+				default:
+				}
+				ch <- current
+			}
+			t.subLock.Unlock()
+		case <-t.done:
+			t.subLock.Lock()
+			for id, ch := range t.subscribers {
+				close(ch)
+				delete(t.subscribers, id)
+			}
+			t.subscriptionsClosed = true
+			t.subLock.Unlock()
+			return
+		}
+	}
+}
+
+func (t *Topology) apply(ctx context.Context, desc description.Server) (description.Topology, error) {
+	var err error
+	prev := t.fsm.Topology
+
+	current, err := t.fsm.apply(desc)
+	if err != nil {
+		return description.Topology{}, err
+	}
+
+	diff := description.DiffTopology(prev, current)
+	t.serversLock.Lock()
+	if t.serversClosed {
+		t.serversLock.Unlock()
+		return description.Topology{}, nil
+	}
+
+	for _, removed := range diff.Removed {
+		if s, ok := t.servers[removed.Addr]; ok {
+			t.removeServer(ctx, removed.Addr, s)
+		}
+	}
+
+	for _, added := range diff.Added {
+		_ = t.addServer(ctx, added.Addr)
+	}
+	t.serversLock.Unlock()
+	return current, nil
+}
+
+func (t *Topology) addServer(ctx context.Context, addr address.Address) error {
+	if _, ok := t.servers[addr]; ok {
+		return nil
+	}
+
+	svr, err := ConnectServer(ctx, addr, t.cfg.serverOpts...)
+	if err != nil {
+		return err
+	}
+
+	t.servers[addr] = svr
+	var sub *ServerSubscription
+	sub, err = svr.Subscribe()
+	if err != nil {
+		return err
+	}
+
+	t.wg.Add(1)
+	go func() {
+		for c := range sub.C {
+			t.changes <- c
+		}
+
+		t.wg.Done()
+	}()
+
+	return nil
+}
+
+func (t *Topology) removeServer(ctx context.Context, addr address.Address, server *Server) {
+	_ = server.Disconnect(ctx)
+	delete(t.servers, addr)
+}
+
+// String implements the Stringer interface
+func (t *Topology) String() string {
+	desc := t.Description()
+	str := fmt.Sprintf("Type: %s\nServers:\n", desc.Kind)
+	for _, s := range t.servers {
+		str += s.String() + "\n"
+	}
+	return str
+}
+
+// Subscription is a subscription to updates to the description of the Topology that created this
+// Subscription.
+type Subscription struct {
+	C  <-chan description.Topology
+	t  *Topology
+	id uint64
+}
+
+// Unsubscribe unsubscribes this Subscription from updates and closes the
+// subscription channel.
+func (s *Subscription) Unsubscribe() error {
+	s.t.subLock.Lock()
+	defer s.t.subLock.Unlock()
+	if s.t.subscriptionsClosed {
+		return nil
+	}
+
+	ch, ok := s.t.subscribers[s.id]
+	if !ok {
+		return nil
+	}
+
+	close(ch)
+	delete(s.t.subscribers, s.id)
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/topology_options.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/topology_options.go
new file mode 100644
index 0000000..9fa98e6
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/topology/topology_options.go
@@ -0,0 +1,269 @@
+// 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 topology
+
+import (
+	"bytes"
+	"strings"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/auth"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/compressor"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+	"github.com/mongodb/mongo-go-driver/x/network/connstring"
+)
+
+// Option is a configuration option for a topology.
+type Option func(*config) error
+
+type config struct {
+	mode                   MonitorMode
+	replicaSetName         string
+	seedList               []string
+	serverOpts             []ServerOption
+	cs                     connstring.ConnString
+	serverSelectionTimeout time.Duration
+}
+
+func newConfig(opts ...Option) (*config, error) {
+	cfg := &config{
+		seedList:               []string{"localhost:27017"},
+		serverSelectionTimeout: 30 * time.Second,
+	}
+
+	for _, opt := range opts {
+		err := opt(cfg)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return cfg, nil
+}
+
+// WithConnString configures the topology using the connection string.
+func WithConnString(fn func(connstring.ConnString) connstring.ConnString) Option {
+	return func(c *config) error {
+		cs := fn(c.cs)
+		c.cs = cs
+
+		if cs.ServerSelectionTimeoutSet {
+			c.serverSelectionTimeout = cs.ServerSelectionTimeout
+		}
+
+		var connOpts []connection.Option
+
+		if cs.AppName != "" {
+			connOpts = append(connOpts, connection.WithAppName(func(string) string { return cs.AppName }))
+		}
+
+		switch cs.Connect {
+		case connstring.SingleConnect:
+			c.mode = SingleMode
+		}
+
+		c.seedList = cs.Hosts
+
+		if cs.ConnectTimeout > 0 {
+			c.serverOpts = append(c.serverOpts, WithHeartbeatTimeout(func(time.Duration) time.Duration { return cs.ConnectTimeout }))
+			connOpts = append(connOpts, connection.WithConnectTimeout(func(time.Duration) time.Duration { return cs.ConnectTimeout }))
+		}
+
+		if cs.SocketTimeoutSet {
+			connOpts = append(
+				connOpts,
+				connection.WithReadTimeout(func(time.Duration) time.Duration { return cs.SocketTimeout }),
+				connection.WithWriteTimeout(func(time.Duration) time.Duration { return cs.SocketTimeout }),
+			)
+		}
+
+		if cs.HeartbeatInterval > 0 {
+			c.serverOpts = append(c.serverOpts, WithHeartbeatInterval(func(time.Duration) time.Duration { return cs.HeartbeatInterval }))
+		}
+
+		if cs.MaxConnIdleTime > 0 {
+			connOpts = append(connOpts, connection.WithIdleTimeout(func(time.Duration) time.Duration { return cs.MaxConnIdleTime }))
+		}
+
+		if cs.MaxPoolSizeSet {
+			c.serverOpts = append(c.serverOpts, WithMaxConnections(func(uint16) uint16 { return cs.MaxPoolSize }))
+			c.serverOpts = append(c.serverOpts, WithMaxIdleConnections(func(uint16) uint16 { return cs.MaxPoolSize }))
+		}
+
+		if cs.ReplicaSet != "" {
+			c.replicaSetName = cs.ReplicaSet
+		}
+
+		var x509Username string
+		if cs.SSL {
+			tlsConfig := connection.NewTLSConfig()
+
+			if cs.SSLCaFileSet {
+				err := tlsConfig.AddCACertFromFile(cs.SSLCaFile)
+				if err != nil {
+					return err
+				}
+			}
+
+			if cs.SSLInsecure {
+				tlsConfig.SetInsecure(true)
+			}
+
+			if cs.SSLClientCertificateKeyFileSet {
+				if cs.SSLClientCertificateKeyPasswordSet && cs.SSLClientCertificateKeyPassword != nil {
+					tlsConfig.SetClientCertDecryptPassword(cs.SSLClientCertificateKeyPassword)
+				}
+				s, err := tlsConfig.AddClientCertFromFile(cs.SSLClientCertificateKeyFile)
+				if err != nil {
+					return err
+				}
+
+				// The Go x509 package gives the subject with the pairs in reverse order that we want.
+				pairs := strings.Split(s, ",")
+				b := bytes.NewBufferString("")
+
+				for i := len(pairs) - 1; i >= 0; i-- {
+					b.WriteString(pairs[i])
+
+					if i > 0 {
+						b.WriteString(",")
+					}
+				}
+
+				x509Username = b.String()
+			}
+
+			connOpts = append(connOpts, connection.WithTLSConfig(func(*connection.TLSConfig) *connection.TLSConfig { return tlsConfig }))
+		}
+
+		if cs.Username != "" || cs.AuthMechanism == auth.MongoDBX509 || cs.AuthMechanism == auth.GSSAPI {
+			cred := &auth.Cred{
+				Source:      "admin",
+				Username:    cs.Username,
+				Password:    cs.Password,
+				PasswordSet: cs.PasswordSet,
+				Props:       cs.AuthMechanismProperties,
+			}
+
+			if cs.AuthSource != "" {
+				cred.Source = cs.AuthSource
+			} else {
+				switch cs.AuthMechanism {
+				case auth.MongoDBX509:
+					if cred.Username == "" {
+						cred.Username = x509Username
+					}
+					fallthrough
+				case auth.GSSAPI, auth.PLAIN:
+					cred.Source = "$external"
+				default:
+					cred.Source = cs.Database
+				}
+			}
+
+			authenticator, err := auth.CreateAuthenticator(cs.AuthMechanism, cred)
+			if err != nil {
+				return err
+			}
+
+			connOpts = append(connOpts, connection.WithHandshaker(func(h connection.Handshaker) connection.Handshaker {
+				options := &auth.HandshakeOptions{
+					AppName:       cs.AppName,
+					Authenticator: authenticator,
+					Compressors:   cs.Compressors,
+				}
+				if cs.AuthMechanism == "" {
+					// Required for SASL mechanism negotiation during handshake
+					options.DBUser = cred.Source + "." + cred.Username
+				}
+				return auth.Handshaker(h, options)
+			}))
+		} else {
+			// We need to add a non-auth Handshaker to the connection options
+			connOpts = append(connOpts, connection.WithHandshaker(func(h connection.Handshaker) connection.Handshaker {
+				return &command.Handshake{Client: command.ClientDoc(cs.AppName), Compressors: cs.Compressors}
+			}))
+		}
+
+		if len(cs.Compressors) > 0 {
+			comp := make([]compressor.Compressor, 0, len(cs.Compressors))
+
+			for _, c := range cs.Compressors {
+				switch c {
+				case "snappy":
+					comp = append(comp, compressor.CreateSnappy())
+				case "zlib":
+					zlibComp, err := compressor.CreateZlib(cs.ZlibLevel)
+					if err != nil {
+						return err
+					}
+
+					comp = append(comp, zlibComp)
+				}
+			}
+
+			connOpts = append(connOpts, connection.WithCompressors(func(compressors []compressor.Compressor) []compressor.Compressor {
+				return append(compressors, comp...)
+			}))
+
+			c.serverOpts = append(c.serverOpts, WithCompressionOptions(func(opts ...string) []string {
+				return append(opts, cs.Compressors...)
+			}))
+		}
+
+		if len(connOpts) > 0 {
+			c.serverOpts = append(c.serverOpts, WithConnectionOptions(func(opts ...connection.Option) []connection.Option {
+				return append(opts, connOpts...)
+			}))
+		}
+
+		return nil
+	}
+}
+
+// WithMode configures the topology's monitor mode.
+func WithMode(fn func(MonitorMode) MonitorMode) Option {
+	return func(cfg *config) error {
+		cfg.mode = fn(cfg.mode)
+		return nil
+	}
+}
+
+// WithReplicaSetName configures the topology's default replica set name.
+func WithReplicaSetName(fn func(string) string) Option {
+	return func(cfg *config) error {
+		cfg.replicaSetName = fn(cfg.replicaSetName)
+		return nil
+	}
+}
+
+// WithSeedList configures a topology's seed list.
+func WithSeedList(fn func(...string) []string) Option {
+	return func(cfg *config) error {
+		cfg.seedList = fn(cfg.seedList...)
+		return nil
+	}
+}
+
+// WithServerOptions configures a topology's server options for when a new server
+// needs to be created.
+func WithServerOptions(fn func(...ServerOption) []ServerOption) Option {
+	return func(cfg *config) error {
+		cfg.serverOpts = fn(cfg.serverOpts...)
+		return nil
+	}
+}
+
+// WithServerSelectionTimeout configures a topology's server selection timeout.
+// A server selection timeout of 0 means there is no timeout for server selection.
+func WithServerSelectionTimeout(fn func(time.Duration) time.Duration) Option {
+	return func(cfg *config) error {
+		cfg.serverSelectionTimeout = fn(cfg.serverSelectionTimeout)
+		return nil
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/update.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/update.go
new file mode 100644
index 0000000..d8d8d16
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/update.go
@@ -0,0 +1,134 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// Update handles the full cycle dispatch and execution of an update command against the provided
+// topology.
+func Update(
+	ctx context.Context,
+	cmd command.Update,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+	retryWrite bool,
+	opts ...*options.UpdateOptions,
+) (result.Update, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return result.Update{}, err
+	}
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return result.Update{}, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	updateOpts := options.MergeUpdateOptions(opts...)
+
+	if updateOpts.ArrayFilters != nil {
+		if ss.Description().WireVersion.Max < 6 {
+			return result.Update{}, ErrArrayFilters
+		}
+		arr, err := updateOpts.ArrayFilters.ToArray()
+		if err != nil {
+			return result.Update{}, err
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"arrayFilters", bsonx.Array(arr)})
+	}
+	if updateOpts.BypassDocumentValidation != nil && ss.Description().WireVersion.Includes(4) {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"bypassDocumentValidation", bsonx.Boolean(*updateOpts.BypassDocumentValidation)})
+	}
+	if updateOpts.Collation != nil {
+		if ss.Description().WireVersion.Max < 5 {
+			return result.Update{}, ErrCollation
+		}
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"collation", bsonx.Document(updateOpts.Collation.ToDocument())})
+	}
+	if updateOpts.Upsert != nil {
+		cmd.Opts = append(cmd.Opts, bsonx.Elem{"upsert", bsonx.Boolean(*updateOpts.Upsert)})
+	}
+
+	// Execute in a single trip if retry writes not supported, or retry not enabled
+	if !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) || !retryWrite {
+		if cmd.Session != nil {
+			cmd.Session.RetryWrite = false // explicitly set to false to prevent encoding transaction number
+		}
+		return update(ctx, cmd, ss, nil)
+	}
+
+	cmd.Session.RetryWrite = retryWrite
+	cmd.Session.IncrementTxnNumber()
+
+	res, originalErr := update(ctx, cmd, ss, nil)
+
+	// Retry if appropriate
+	if cerr, ok := originalErr.(command.Error); ok && cerr.Retryable() ||
+		res.WriteConcernError != nil && command.IsWriteConcernErrorRetryable(res.WriteConcernError) {
+		ss, err := topo.SelectServer(ctx, selector)
+
+		// Return original error if server selection fails or new server does not support retryable writes
+		if err != nil || !retrySupported(topo, ss.Description(), cmd.Session, cmd.WriteConcern) {
+			return res, originalErr
+		}
+
+		return update(ctx, cmd, ss, cerr)
+	}
+	return res, originalErr
+
+}
+
+func update(
+	ctx context.Context,
+	cmd command.Update,
+	ss *topology.SelectedServer,
+	oldErr error,
+) (result.Update, error) {
+	desc := ss.Description()
+
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		if oldErr != nil {
+			return result.Update{}, oldErr
+		}
+		return result.Update{}, err
+	}
+
+	if !writeconcern.AckWrite(cmd.WriteConcern) {
+		go func() {
+			defer func() { _ = recover() }()
+			defer conn.Close()
+
+			_, _ = cmd.RoundTrip(ctx, desc, conn)
+		}()
+
+		return result.Update{}, command.ErrUnacknowledgedWrite
+	}
+	defer conn.Close()
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid/uuid.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid/uuid.go
new file mode 100644
index 0000000..7ad5eea
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid/uuid.go
@@ -0,0 +1,37 @@
+// 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 uuid
+
+import (
+	"bytes"
+	"crypto/rand"
+	"io"
+)
+
+// UUID represents a UUID.
+type UUID [16]byte
+
+var rander = rand.Reader
+
+// New generates a new uuid.
+func New() (UUID, error) {
+	var uuid [16]byte
+
+	_, err := io.ReadFull(rander, uuid[:])
+	if err != nil {
+		return [16]byte{}, err
+	}
+	uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
+	uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
+
+	return uuid, nil
+}
+
+// Equal returns true if two UUIDs are equal.
+func Equal(a, b UUID) bool {
+	return bytes.Equal([]byte(a[:]), []byte(b[:]))
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/write.go b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/write.go
new file mode 100644
index 0000000..6447a49
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/mongo/driver/write.go
@@ -0,0 +1,79 @@
+// 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 driver
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// Write handles the full cycle dispatch and execution of a write command against the provided
+// topology.
+func Write(
+	ctx context.Context,
+	cmd command.Write,
+	topo *topology.Topology,
+	selector description.ServerSelector,
+	clientID uuid.UUID,
+	pool *session.Pool,
+) (bson.Raw, error) {
+
+	ss, err := topo.SelectServer(ctx, selector)
+	if err != nil {
+		return nil, err
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	if !writeconcern.AckWrite(cmd.WriteConcern) {
+		go func() {
+			defer func() { _ = recover() }()
+			defer conn.Close()
+
+			_, _ = cmd.RoundTrip(ctx, desc, conn)
+		}()
+
+		return nil, command.ErrUnacknowledgedWrite
+	}
+	defer conn.Close()
+
+	// If no explicit session and deployment supports sessions, start implicit session.
+	if cmd.Session == nil && topo.SupportsSessions() {
+		cmd.Session, err = session.NewClientSession(pool, clientID, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+		defer cmd.Session.EndSession()
+	}
+
+	return cmd.RoundTrip(ctx, desc, conn)
+}
+
+// Retryable writes are supported if the server supports sessions, the operation is not
+// within a transaction, and the write is acknowledged
+func retrySupported(
+	topo *topology.Topology,
+	desc description.SelectedServer,
+	sess *session.Client,
+	wc *writeconcern.WriteConcern,
+) bool {
+	return topo.SupportsSessions() &&
+		description.SessionsSupported(desc.WireVersion) &&
+		!(sess.TransactionInProgress() || sess.TransactionStarting()) &&
+		writeconcern.AckWrite(wc)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/address/addr.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/address/addr.go
new file mode 100644
index 0000000..c2a3bb7
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/address/addr.go
@@ -0,0 +1,49 @@
+// 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 address
+
+import (
+	"net"
+	"strings"
+)
+
+const defaultPort = "27017"
+
+// Address is a network address. It can either be an IP address or a DNS name.
+type Address string
+
+// Network is the network protocol for this address. In most cases this will be
+// "tcp" or "unix".
+func (a Address) Network() string {
+	if strings.HasSuffix(string(a), "sock") {
+		return "unix"
+	}
+	return "tcp"
+}
+
+// String is the canonical version of this address, e.g. localhost:27017,
+// 1.2.3.4:27017, example.com:27017.
+func (a Address) String() string {
+	// TODO: unicode case folding?
+	s := strings.ToLower(string(a))
+	if len(s) == 0 {
+		return ""
+	}
+	if a.Network() != "unix" {
+		_, _, err := net.SplitHostPort(s)
+		if err != nil && strings.Contains(err.Error(), "missing port in address") {
+			s += ":" + defaultPort
+		}
+	}
+
+	return s
+}
+
+// Canonicalize creates a canonicalized address.
+func (a Address) Canonicalize() Address {
+	return Address(a.String())
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/abort_transaction.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/abort_transaction.go
new file mode 100644
index 0000000..54e5cca
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/abort_transaction.go
@@ -0,0 +1,89 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// AbortTransaction represents the abortTransaction() command
+type AbortTransaction struct {
+	Session *session.Client
+	err     error
+	result  result.TransactionResult
+}
+
+// Encode will encode this command into a wiremessage for the given server description.
+func (at *AbortTransaction) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd := at.encode(desc)
+	return cmd.Encode(desc)
+}
+
+func (at *AbortTransaction) encode(desc description.SelectedServer) *Write {
+	cmd := bsonx.Doc{{"abortTransaction", bsonx.Int32(1)}}
+	return &Write{
+		DB:           "admin",
+		Command:      cmd,
+		Session:      at.Session,
+		WriteConcern: at.Session.CurrentWc,
+	}
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding are deferred until
+// either the Result or Err methods are called.
+func (at *AbortTransaction) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *AbortTransaction {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		at.err = err
+		return at
+	}
+
+	return at.decode(desc, rdr)
+}
+
+func (at *AbortTransaction) decode(desc description.SelectedServer, rdr bson.Raw) *AbortTransaction {
+	at.err = bson.Unmarshal(rdr, &at.result)
+	if at.err == nil && at.result.WriteConcernError != nil {
+		at.err = Error{
+			Code:    int32(at.result.WriteConcernError.Code),
+			Message: at.result.WriteConcernError.ErrMsg,
+		}
+	}
+	return at
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (at *AbortTransaction) Result() (result.TransactionResult, error) {
+	if at.err != nil {
+		return result.TransactionResult{}, at.err
+	}
+
+	return at.result, nil
+}
+
+// Err returns the error set on this command
+func (at *AbortTransaction) Err() error {
+	return at.err
+}
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter
+func (at *AbortTransaction) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.TransactionResult, error) {
+	cmd := at.encode(desc)
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.TransactionResult{}, err
+	}
+
+	return at.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/aggregate.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/aggregate.go
new file mode 100644
index 0000000..106f583
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/aggregate.go
@@ -0,0 +1,159 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Aggregate represents the aggregate command.
+//
+// The aggregate command performs an aggregation.
+type Aggregate struct {
+	NS           Namespace
+	Pipeline     bsonx.Arr
+	CursorOpts   []bsonx.Elem
+	Opts         []bsonx.Elem
+	ReadPref     *readpref.ReadPref
+	WriteConcern *writeconcern.WriteConcern
+	ReadConcern  *readconcern.ReadConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (a *Aggregate) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := a.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (a *Aggregate) encode(desc description.SelectedServer) (*Read, error) {
+	if err := a.NS.Validate(); err != nil {
+		return nil, err
+	}
+
+	command := bsonx.Doc{
+		{"aggregate", bsonx.String(a.NS.Collection)},
+		{"pipeline", bsonx.Array(a.Pipeline)},
+	}
+
+	cursor := bsonx.Doc{}
+	hasOutStage := a.HasDollarOut()
+
+	for _, opt := range a.Opts {
+		switch opt.Key {
+		case "batchSize":
+			if opt.Value.Int32() == 0 && hasOutStage {
+				continue
+			}
+			cursor = append(cursor, opt)
+		default:
+			command = append(command, opt)
+		}
+	}
+	command = append(command, bsonx.Elem{"cursor", bsonx.Document(cursor)})
+
+	// add write concern because it won't be added by the Read command's Encode()
+	if desc.WireVersion.Max >= 5 && hasOutStage && a.WriteConcern != nil {
+		t, data, err := a.WriteConcern.MarshalBSONValue()
+		if err != nil {
+			return nil, err
+		}
+		var xval bsonx.Val
+		err = xval.UnmarshalBSONValue(t, data)
+		if err != nil {
+			return nil, err
+		}
+		command = append(command, bsonx.Elem{Key: "writeConcern", Value: xval})
+	}
+
+	return &Read{
+		DB:          a.NS.DB,
+		Command:     command,
+		ReadPref:    a.ReadPref,
+		ReadConcern: a.ReadConcern,
+		Clock:       a.Clock,
+		Session:     a.Session,
+	}, nil
+}
+
+// HasDollarOut returns true if the Pipeline field contains a $out stage.
+func (a *Aggregate) HasDollarOut() bool {
+	if a.Pipeline == nil {
+		return false
+	}
+	if len(a.Pipeline) == 0 {
+		return false
+	}
+
+	val := a.Pipeline[len(a.Pipeline)-1]
+
+	doc, ok := val.DocumentOK()
+	if !ok || len(doc) != 1 {
+		return false
+	}
+	return doc[0].Key == "$out"
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (a *Aggregate) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Aggregate {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		a.err = err
+		return a
+	}
+
+	return a.decode(desc, rdr)
+}
+
+func (a *Aggregate) decode(desc description.SelectedServer, rdr bson.Raw) *Aggregate {
+	a.result = rdr
+	return a
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (a *Aggregate) Result() (bson.Raw, error) {
+	if a.err != nil {
+		return nil, a.err
+	}
+	return a.result, nil
+}
+
+// Err returns the error set on this command.
+func (a *Aggregate) Err() error { return a.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (a *Aggregate) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	cmd, err := a.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return nil, err
+	}
+
+	return a.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/buildinfo.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/buildinfo.go
new file mode 100644
index 0000000..6bd09fa
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/buildinfo.go
@@ -0,0 +1,95 @@
+// 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 command
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// BuildInfo represents the buildInfo command.
+//
+// The buildInfo command is used for getting the build information for a
+// MongoDB server.
+type BuildInfo struct {
+	err error
+	res result.BuildInfo
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (bi *BuildInfo) Encode() (wiremessage.WireMessage, error) {
+	// This can probably just be a global variable that we reuse.
+	cmd := bsonx.Doc{{"buildInfo", bsonx.Int32(1)}}
+	rdr, err := cmd.MarshalBSON()
+	if err != nil {
+		return nil, err
+	}
+	query := wiremessage.Query{
+		MsgHeader:          wiremessage.Header{RequestID: wiremessage.NextRequestID()},
+		FullCollectionName: "admin.$cmd",
+		Flags:              wiremessage.SlaveOK,
+		NumberToReturn:     -1,
+		Query:              rdr,
+	}
+	return query, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (bi *BuildInfo) Decode(wm wiremessage.WireMessage) *BuildInfo {
+	reply, ok := wm.(wiremessage.Reply)
+	if !ok {
+		bi.err = fmt.Errorf("unsupported response wiremessage type %T", wm)
+		return bi
+	}
+	rdr, err := decodeCommandOpReply(reply)
+	if err != nil {
+		bi.err = err
+		return bi
+	}
+	err = bson.Unmarshal(rdr, &bi.res)
+	if err != nil {
+		bi.err = err
+		return bi
+	}
+	return bi
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (bi *BuildInfo) Result() (result.BuildInfo, error) {
+	if bi.err != nil {
+		return result.BuildInfo{}, bi.err
+	}
+
+	return bi.res, nil
+}
+
+// Err returns the error set on this command.
+func (bi *BuildInfo) Err() error { return bi.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (bi *BuildInfo) RoundTrip(ctx context.Context, rw wiremessage.ReadWriter) (result.BuildInfo, error) {
+	wm, err := bi.Encode()
+	if err != nil {
+		return result.BuildInfo{}, err
+	}
+
+	err = rw.WriteWireMessage(ctx, wm)
+	if err != nil {
+		return result.BuildInfo{}, err
+	}
+	wm, err = rw.ReadWireMessage(ctx)
+	if err != nil {
+		return result.BuildInfo{}, err
+	}
+	return bi.Decode(wm).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/command.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/command.go
new file mode 100644
index 0000000..859f797
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/command.go
@@ -0,0 +1,708 @@
+// 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 command
+
+import (
+	"errors"
+
+	"context"
+
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/bson/primitive"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// WriteBatch represents a single batch for a write operation.
+type WriteBatch struct {
+	*Write
+	numDocs int
+}
+
+// DecodeError attempts to decode the wiremessage as an error
+func DecodeError(wm wiremessage.WireMessage) error {
+	var rdr bson.Raw
+	switch msg := wm.(type) {
+	case wiremessage.Msg:
+		for _, section := range msg.Sections {
+			switch converted := section.(type) {
+			case wiremessage.SectionBody:
+				rdr = converted.Document
+			}
+		}
+	case wiremessage.Reply:
+		if msg.ResponseFlags&wiremessage.QueryFailure != wiremessage.QueryFailure {
+			return nil
+		}
+		rdr = msg.Documents[0]
+	}
+
+	err := rdr.Validate()
+	if err != nil {
+		return nil
+	}
+
+	extractedError := extractError(rdr)
+
+	// If parsed successfully return the error
+	if _, ok := extractedError.(Error); ok {
+		return err
+	}
+
+	return nil
+}
+
+// helper method to extract an error from a reader if there is one; first returned item is the
+// error if it exists, the second holds parsing errors
+func extractError(rdr bson.Raw) error {
+	var errmsg, codeName string
+	var code int32
+	var labels []string
+	elems, err := rdr.Elements()
+	if err != nil {
+		return err
+	}
+
+	for _, elem := range elems {
+		switch elem.Key() {
+		case "ok":
+			switch elem.Value().Type {
+			case bson.TypeInt32:
+				if elem.Value().Int32() == 1 {
+					return nil
+				}
+			case bson.TypeInt64:
+				if elem.Value().Int64() == 1 {
+					return nil
+				}
+			case bson.TypeDouble:
+				if elem.Value().Double() == 1 {
+					return nil
+				}
+			}
+		case "errmsg":
+			if str, okay := elem.Value().StringValueOK(); okay {
+				errmsg = str
+			}
+		case "codeName":
+			if str, okay := elem.Value().StringValueOK(); okay {
+				codeName = str
+			}
+		case "code":
+			if c, okay := elem.Value().Int32OK(); okay {
+				code = c
+			}
+		case "errorLabels":
+			if arr, okay := elem.Value().ArrayOK(); okay {
+				elems, err := arr.Elements()
+				if err != nil {
+					continue
+				}
+				for _, elem := range elems {
+					if str, ok := elem.Value().StringValueOK(); ok {
+						labels = append(labels, str)
+					}
+				}
+
+			}
+		}
+	}
+
+	if errmsg == "" {
+		errmsg = "command failed"
+	}
+
+	return Error{
+		Code:    code,
+		Message: errmsg,
+		Name:    codeName,
+		Labels:  labels,
+	}
+}
+
+func responseClusterTime(response bson.Raw) bson.Raw {
+	clusterTime, err := response.LookupErr("$clusterTime")
+	if err != nil {
+		// $clusterTime not included by the server
+		return nil
+	}
+	idx, doc := bsoncore.AppendDocumentStart(nil)
+	doc = bsoncore.AppendHeader(doc, clusterTime.Type, "$clusterTime")
+	doc = append(doc, clusterTime.Value...)
+	doc, _ = bsoncore.AppendDocumentEnd(doc, idx)
+	return doc
+}
+
+func updateClusterTimes(sess *session.Client, clock *session.ClusterClock, response bson.Raw) error {
+	clusterTime := responseClusterTime(response)
+	if clusterTime == nil {
+		return nil
+	}
+
+	if sess != nil {
+		err := sess.AdvanceClusterTime(clusterTime)
+		if err != nil {
+			return err
+		}
+	}
+
+	if clock != nil {
+		clock.AdvanceClusterTime(clusterTime)
+	}
+
+	return nil
+}
+
+func updateOperationTime(sess *session.Client, response bson.Raw) error {
+	if sess == nil {
+		return nil
+	}
+
+	opTimeElem, err := response.LookupErr("operationTime")
+	if err != nil {
+		// operationTime not included by the server
+		return nil
+	}
+
+	t, i := opTimeElem.Timestamp()
+	return sess.AdvanceOperationTime(&primitive.Timestamp{
+		T: t,
+		I: i,
+	})
+}
+
+func marshalCommand(cmd bsonx.Doc) (bson.Raw, error) {
+	if cmd == nil {
+		return bson.Raw{5, 0, 0, 0, 0}, nil
+	}
+
+	return cmd.MarshalBSON()
+}
+
+// adds session related fields to a BSON doc representing a command
+func addSessionFields(cmd bsonx.Doc, desc description.SelectedServer, client *session.Client) (bsonx.Doc, error) {
+	if client == nil || !description.SessionsSupported(desc.WireVersion) || desc.SessionTimeoutMinutes == 0 {
+		return cmd, nil
+	}
+
+	if client.Terminated {
+		return cmd, session.ErrSessionEnded
+	}
+
+	if _, err := cmd.LookupElementErr("lsid"); err != nil {
+		cmd = cmd.Delete("lsid")
+	}
+
+	cmd = append(cmd, bsonx.Elem{"lsid", bsonx.Document(client.SessionID)})
+
+	if client.TransactionRunning() ||
+		client.RetryingCommit {
+		cmd = addTransaction(cmd, client)
+	}
+
+	client.ApplyCommand() // advance the state machine based on a command executing
+
+	return cmd, nil
+}
+
+// if in a transaction, add the transaction fields
+func addTransaction(cmd bsonx.Doc, client *session.Client) bsonx.Doc {
+	cmd = append(cmd, bsonx.Elem{"txnNumber", bsonx.Int64(client.TxnNumber)})
+	if client.TransactionStarting() {
+		// When starting transaction, always transition to the next state, even on error
+		cmd = append(cmd, bsonx.Elem{"startTransaction", bsonx.Boolean(true)})
+	}
+	return append(cmd, bsonx.Elem{"autocommit", bsonx.Boolean(false)})
+}
+
+func addClusterTime(cmd bsonx.Doc, desc description.SelectedServer, sess *session.Client, clock *session.ClusterClock) bsonx.Doc {
+	if (clock == nil && sess == nil) || !description.SessionsSupported(desc.WireVersion) {
+		return cmd
+	}
+
+	var clusterTime bson.Raw
+	if clock != nil {
+		clusterTime = clock.GetClusterTime()
+	}
+
+	if sess != nil {
+		if clusterTime == nil {
+			clusterTime = sess.ClusterTime
+		} else {
+			clusterTime = session.MaxClusterTime(clusterTime, sess.ClusterTime)
+		}
+	}
+
+	if clusterTime == nil {
+		return cmd
+	}
+
+	d, err := bsonx.ReadDoc(clusterTime)
+	if err != nil {
+		return cmd // broken clusterTime
+	}
+
+	cmd = cmd.Delete("$clusterTime")
+
+	return append(cmd, d...)
+}
+
+// add a read concern to a BSON doc representing a command
+func addReadConcern(cmd bsonx.Doc, desc description.SelectedServer, rc *readconcern.ReadConcern, sess *session.Client) (bsonx.Doc, error) {
+	// Starting transaction's read concern overrides all others
+	if sess != nil && sess.TransactionStarting() && sess.CurrentRc != nil {
+		rc = sess.CurrentRc
+	}
+
+	// start transaction must append afterclustertime IF causally consistent and operation time exists
+	if rc == nil && sess != nil && sess.TransactionStarting() && sess.Consistent && sess.OperationTime != nil {
+		rc = readconcern.New()
+	}
+
+	if rc == nil {
+		return cmd, nil
+	}
+
+	t, data, err := rc.MarshalBSONValue()
+	if err != nil {
+		return cmd, err
+	}
+
+	var rcDoc bsonx.Doc
+	err = rcDoc.UnmarshalBSONValue(t, data)
+	if err != nil {
+		return cmd, err
+	}
+	if description.SessionsSupported(desc.WireVersion) && sess != nil && sess.Consistent && sess.OperationTime != nil {
+		rcDoc = append(rcDoc, bsonx.Elem{"afterClusterTime", bsonx.Timestamp(sess.OperationTime.T, sess.OperationTime.I)})
+	}
+
+	cmd = cmd.Delete("readConcern")
+
+	if len(rcDoc) != 0 {
+		cmd = append(cmd, bsonx.Elem{"readConcern", bsonx.Document(rcDoc)})
+	}
+	return cmd, nil
+}
+
+// add a write concern to a BSON doc representing a command
+func addWriteConcern(cmd bsonx.Doc, wc *writeconcern.WriteConcern) (bsonx.Doc, error) {
+	if wc == nil {
+		return cmd, nil
+	}
+
+	t, data, err := wc.MarshalBSONValue()
+	if err != nil {
+		if err == writeconcern.ErrEmptyWriteConcern {
+			return cmd, nil
+		}
+		return cmd, err
+	}
+
+	var xval bsonx.Val
+	err = xval.UnmarshalBSONValue(t, data)
+	if err != nil {
+		return cmd, err
+	}
+
+	// delete if doc already has write concern
+	cmd = cmd.Delete("writeConcern")
+
+	return append(cmd, bsonx.Elem{Key: "writeConcern", Value: xval}), nil
+}
+
+// Get the error labels from a command response
+func getErrorLabels(rdr *bson.Raw) ([]string, error) {
+	var labels []string
+	labelsElem, err := rdr.LookupErr("errorLabels")
+	if err != bsoncore.ErrElementNotFound {
+		return nil, err
+	}
+	if labelsElem.Type == bsontype.Array {
+		labelsIt, err := labelsElem.Array().Elements()
+		if err != nil {
+			return nil, err
+		}
+		for _, elem := range labelsIt {
+			labels = append(labels, elem.Value().StringValue())
+		}
+	}
+	return labels, nil
+}
+
+// Remove command arguments for insert, update, and delete commands from the BSON document so they can be encoded
+// as a Section 1 payload in OP_MSG
+func opmsgRemoveArray(cmd bsonx.Doc) (bsonx.Doc, bsonx.Arr, string) {
+	var array bsonx.Arr
+	var id string
+
+	keys := []string{"documents", "updates", "deletes"}
+
+	for _, key := range keys {
+		val, err := cmd.LookupErr(key)
+		if err != nil {
+			continue
+		}
+
+		array = val.Array()
+		cmd = cmd.Delete(key)
+		id = key
+		break
+	}
+
+	return cmd, array, id
+}
+
+// Add the $db and $readPreference keys to the command
+// If the command has no read preference, pass nil for rpDoc
+func opmsgAddGlobals(cmd bsonx.Doc, dbName string, rpDoc bsonx.Doc) (bson.Raw, error) {
+	cmd = append(cmd, bsonx.Elem{"$db", bsonx.String(dbName)})
+	if rpDoc != nil {
+		cmd = append(cmd, bsonx.Elem{"$readPreference", bsonx.Document(rpDoc)})
+	}
+
+	return cmd.MarshalBSON() // bsonx.Doc.MarshalBSON never returns an error.
+}
+
+func opmsgCreateDocSequence(arr bsonx.Arr, identifier string) (wiremessage.SectionDocumentSequence, error) {
+	docSequence := wiremessage.SectionDocumentSequence{
+		PayloadType: wiremessage.DocumentSequence,
+		Identifier:  identifier,
+		Documents:   make([]bson.Raw, 0, len(arr)),
+	}
+
+	for _, val := range arr {
+		d, _ := val.Document().MarshalBSON()
+		docSequence.Documents = append(docSequence.Documents, d)
+	}
+
+	docSequence.Size = int32(docSequence.PayloadLen())
+	return docSequence, nil
+}
+
+func splitBatches(docs []bsonx.Doc, maxCount, targetBatchSize int) ([][]bsonx.Doc, error) {
+	batches := [][]bsonx.Doc{}
+
+	if targetBatchSize > reservedCommandBufferBytes {
+		targetBatchSize -= reservedCommandBufferBytes
+	}
+
+	if maxCount <= 0 {
+		maxCount = 1
+	}
+
+	startAt := 0
+splitInserts:
+	for {
+		size := 0
+		batch := []bsonx.Doc{}
+	assembleBatch:
+		for idx := startAt; idx < len(docs); idx++ {
+			raw, _ := docs[idx].MarshalBSON()
+
+			if len(raw) > targetBatchSize {
+				return nil, ErrDocumentTooLarge
+			}
+			if size+len(raw) > targetBatchSize {
+				break assembleBatch
+			}
+
+			size += len(raw)
+			batch = append(batch, docs[idx])
+			startAt++
+			if len(batch) == maxCount {
+				break assembleBatch
+			}
+		}
+		batches = append(batches, batch)
+		if startAt == len(docs) {
+			break splitInserts
+		}
+	}
+
+	return batches, nil
+}
+
+func encodeBatch(
+	docs []bsonx.Doc,
+	opts []bsonx.Elem,
+	cmdKind WriteCommandKind,
+	collName string,
+) (bsonx.Doc, error) {
+	var cmdName string
+	var docString string
+
+	switch cmdKind {
+	case InsertCommand:
+		cmdName = "insert"
+		docString = "documents"
+	case UpdateCommand:
+		cmdName = "update"
+		docString = "updates"
+	case DeleteCommand:
+		cmdName = "delete"
+		docString = "deletes"
+	}
+
+	cmd := bsonx.Doc{{cmdName, bsonx.String(collName)}}
+
+	vals := make(bsonx.Arr, 0, len(docs))
+	for _, doc := range docs {
+		vals = append(vals, bsonx.Document(doc))
+	}
+	cmd = append(cmd, bsonx.Elem{docString, bsonx.Array(vals)})
+	cmd = append(cmd, opts...)
+
+	return cmd, nil
+}
+
+// converts batches of Write Commands to wire messages
+func batchesToWireMessage(batches []*WriteBatch, desc description.SelectedServer) ([]wiremessage.WireMessage, error) {
+	wms := make([]wiremessage.WireMessage, len(batches))
+	for _, cmd := range batches {
+		wm, err := cmd.Encode(desc)
+		if err != nil {
+			return nil, err
+		}
+
+		wms = append(wms, wm)
+	}
+
+	return wms, nil
+}
+
+// Roundtrips the write batches, returning the result structs (as interface),
+// the write batches that weren't round tripped and any errors
+func roundTripBatches(
+	ctx context.Context,
+	desc description.SelectedServer,
+	rw wiremessage.ReadWriter,
+	batches []*WriteBatch,
+	continueOnError bool,
+	sess *session.Client,
+	cmdKind WriteCommandKind,
+) (interface{}, []*WriteBatch, error) {
+	var res interface{}
+	var upsertIndex int64 // the operation index for the upserted IDs map
+
+	// hold onto txnNumber, reset it when loop exits to ensure reuse of same
+	// transaction number if retry is needed
+	var txnNumber int64
+	if sess != nil && sess.RetryWrite {
+		txnNumber = sess.TxnNumber
+	}
+	for j, cmd := range batches {
+		rdr, err := cmd.RoundTrip(ctx, desc, rw)
+		if err != nil {
+			if sess != nil && sess.RetryWrite {
+				sess.TxnNumber = txnNumber + int64(j)
+			}
+			return res, batches, err
+		}
+
+		// TODO can probably DRY up this code
+		switch cmdKind {
+		case InsertCommand:
+			if res == nil {
+				res = result.Insert{}
+			}
+
+			conv, _ := res.(result.Insert)
+			insertCmd := &Insert{}
+			r, err := insertCmd.decode(desc, rdr).Result()
+			if err != nil {
+				return res, batches, err
+			}
+
+			conv.WriteErrors = append(conv.WriteErrors, r.WriteErrors...)
+
+			if r.WriteConcernError != nil {
+				conv.WriteConcernError = r.WriteConcernError
+				if sess != nil && sess.RetryWrite {
+					sess.TxnNumber = txnNumber
+					return conv, batches, nil // report writeconcernerror for retry
+				}
+			}
+
+			conv.N += r.N
+
+			if !continueOnError && len(conv.WriteErrors) > 0 {
+				return conv, batches, nil
+			}
+
+			res = conv
+		case UpdateCommand:
+			if res == nil {
+				res = result.Update{}
+			}
+
+			conv, _ := res.(result.Update)
+			updateCmd := &Update{}
+			r, err := updateCmd.decode(desc, rdr).Result()
+			if err != nil {
+				return conv, batches, err
+			}
+
+			conv.WriteErrors = append(conv.WriteErrors, r.WriteErrors...)
+
+			if r.WriteConcernError != nil {
+				conv.WriteConcernError = r.WriteConcernError
+				if sess != nil && sess.RetryWrite {
+					sess.TxnNumber = txnNumber
+					return conv, batches, nil // report writeconcernerror for retry
+				}
+			}
+
+			conv.MatchedCount += r.MatchedCount
+			conv.ModifiedCount += r.ModifiedCount
+			for _, upsert := range r.Upserted {
+				conv.Upserted = append(conv.Upserted, result.Upsert{
+					Index: upsert.Index + upsertIndex,
+					ID:    upsert.ID,
+				})
+			}
+
+			if !continueOnError && len(conv.WriteErrors) > 0 {
+				return conv, batches, nil
+			}
+
+			res = conv
+			upsertIndex += int64(cmd.numDocs)
+		case DeleteCommand:
+			if res == nil {
+				res = result.Delete{}
+			}
+
+			conv, _ := res.(result.Delete)
+			deleteCmd := &Delete{}
+			r, err := deleteCmd.decode(desc, rdr).Result()
+			if err != nil {
+				return conv, batches, err
+			}
+
+			conv.WriteErrors = append(conv.WriteErrors, r.WriteErrors...)
+
+			if r.WriteConcernError != nil {
+				conv.WriteConcernError = r.WriteConcernError
+				if sess != nil && sess.RetryWrite {
+					sess.TxnNumber = txnNumber
+					return conv, batches, nil // report writeconcernerror for retry
+				}
+			}
+
+			conv.N += r.N
+
+			if !continueOnError && len(conv.WriteErrors) > 0 {
+				return conv, batches, nil
+			}
+
+			res = conv
+		}
+
+		// Increment txnNumber for each batch
+		if sess != nil && sess.RetryWrite {
+			sess.IncrementTxnNumber()
+			batches = batches[1:] // if batch encoded successfully, remove it from the slice
+		}
+	}
+
+	if sess != nil && sess.RetryWrite {
+		// if retryable write succeeded, transaction number will be incremented one extra time,
+		// so we decrement it here
+		sess.TxnNumber--
+	}
+
+	return res, batches, nil
+}
+
+// get the firstBatch, cursor ID, and namespace from a bson.Raw
+func getCursorValues(result bson.Raw) ([]bson.RawValue, Namespace, int64, error) {
+	cur, err := result.LookupErr("cursor")
+	if err != nil {
+		return nil, Namespace{}, 0, err
+	}
+	if cur.Type != bson.TypeEmbeddedDocument {
+		return nil, Namespace{}, 0, fmt.Errorf("cursor should be an embedded document but it is a BSON %s", cur.Type)
+	}
+
+	elems, err := cur.Document().Elements()
+	if err != nil {
+		return nil, Namespace{}, 0, err
+	}
+
+	var ok bool
+	var arr bson.Raw
+	var namespace Namespace
+	var cursorID int64
+
+	for _, elem := range elems {
+		switch elem.Key() {
+		case "firstBatch":
+			arr, ok = elem.Value().ArrayOK()
+			if !ok {
+				return nil, Namespace{}, 0, fmt.Errorf("firstBatch should be an array but it is a BSON %s", elem.Value().Type)
+			}
+			if err != nil {
+				return nil, Namespace{}, 0, err
+			}
+		case "ns":
+			if elem.Value().Type != bson.TypeString {
+				return nil, Namespace{}, 0, fmt.Errorf("namespace should be a string but it is a BSON %s", elem.Value().Type)
+			}
+			namespace = ParseNamespace(elem.Value().StringValue())
+			err = namespace.Validate()
+			if err != nil {
+				return nil, Namespace{}, 0, err
+			}
+		case "id":
+			cursorID, ok = elem.Value().Int64OK()
+			if !ok {
+				return nil, Namespace{}, 0, fmt.Errorf("id should be an int64 but it is a BSON %s", elem.Value().Type)
+			}
+		}
+	}
+
+	vals, err := arr.Values()
+	if err != nil {
+		return nil, Namespace{}, 0, err
+	}
+
+	return vals, namespace, cursorID, nil
+}
+
+func getBatchSize(opts []bsonx.Elem) int32 {
+	for _, opt := range opts {
+		if opt.Key == "batchSize" {
+			return opt.Value.Int32()
+		}
+	}
+
+	return 0
+}
+
+// ErrUnacknowledgedWrite is returned from functions that have an unacknowledged
+// write concern.
+var ErrUnacknowledgedWrite = errors.New("unacknowledged write")
+
+// WriteCommandKind is the type of command represented by a Write
+type WriteCommandKind int8
+
+// These constants represent the valid types of write commands.
+const (
+	InsertCommand WriteCommandKind = iota
+	UpdateCommand
+	DeleteCommand
+)
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/commit_transaction.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/commit_transaction.go
new file mode 100644
index 0000000..e04bd6f
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/commit_transaction.go
@@ -0,0 +1,89 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// CommitTransaction represents the commitTransaction() command
+type CommitTransaction struct {
+	Session *session.Client
+	err     error
+	result  result.TransactionResult
+}
+
+// Encode will encode this command into a wiremessage for the given server description.
+func (ct *CommitTransaction) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd := ct.encode(desc)
+	return cmd.Encode(desc)
+}
+
+func (ct *CommitTransaction) encode(desc description.SelectedServer) *Write {
+	cmd := bsonx.Doc{{"commitTransaction", bsonx.Int32(1)}}
+	return &Write{
+		DB:           "admin",
+		Command:      cmd,
+		Session:      ct.Session,
+		WriteConcern: ct.Session.CurrentWc,
+	}
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding are deferred until
+// either the Result or Err methods are called.
+func (ct *CommitTransaction) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *CommitTransaction {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		ct.err = err
+		return ct
+	}
+
+	return ct.decode(desc, rdr)
+}
+
+func (ct *CommitTransaction) decode(desc description.SelectedServer, rdr bson.Raw) *CommitTransaction {
+	ct.err = bson.Unmarshal(rdr, &ct.result)
+	if ct.err == nil && ct.result.WriteConcernError != nil {
+		ct.err = Error{
+			Code:    int32(ct.result.WriteConcernError.Code),
+			Message: ct.result.WriteConcernError.ErrMsg,
+		}
+	}
+	return ct
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (ct *CommitTransaction) Result() (result.TransactionResult, error) {
+	if ct.err != nil {
+		return result.TransactionResult{}, ct.err
+	}
+
+	return ct.result, nil
+}
+
+// Err returns the error set on this command
+func (ct *CommitTransaction) Err() error {
+	return ct.err
+}
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter
+func (ct *CommitTransaction) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.TransactionResult, error) {
+	cmd := ct.encode(desc)
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.TransactionResult{}, err
+	}
+
+	return ct.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/count.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/count.go
new file mode 100644
index 0000000..419a78b
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/count.go
@@ -0,0 +1,128 @@
+// 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 command
+
+import (
+	"context"
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Count represents the count command.
+//
+// The count command counts how many documents in a collection match the given query.
+type Count struct {
+	NS          Namespace
+	Query       bsonx.Doc
+	Opts        []bsonx.Elem
+	ReadPref    *readpref.ReadPref
+	ReadConcern *readconcern.ReadConcern
+	Clock       *session.ClusterClock
+	Session     *session.Client
+
+	result int64
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (c *Count) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := c.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (c *Count) encode(desc description.SelectedServer) (*Read, error) {
+	if err := c.NS.Validate(); err != nil {
+		return nil, err
+	}
+
+	command := bsonx.Doc{{"count", bsonx.String(c.NS.Collection)}, {"query", bsonx.Document(c.Query)}}
+	command = append(command, c.Opts...)
+
+	return &Read{
+		Clock:       c.Clock,
+		DB:          c.NS.DB,
+		ReadPref:    c.ReadPref,
+		Command:     command,
+		ReadConcern: c.ReadConcern,
+		Session:     c.Session,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (c *Count) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Count {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		c.err = err
+		return c
+	}
+
+	return c.decode(desc, rdr)
+}
+
+func (c *Count) decode(desc description.SelectedServer, rdr bson.Raw) *Count {
+	val, err := rdr.LookupErr("n")
+	switch {
+	case err == bsoncore.ErrElementNotFound:
+		c.err = errors.New("invalid response from server, no 'n' field")
+		return c
+	case err != nil:
+		c.err = err
+		return c
+	}
+
+	switch val.Type {
+	case bson.TypeInt32:
+		c.result = int64(val.Int32())
+	case bson.TypeInt64:
+		c.result = val.Int64()
+	case bson.TypeDouble:
+		c.result = int64(val.Double())
+	default:
+		c.err = errors.New("invalid response from server, value field is not a number")
+	}
+
+	return c
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (c *Count) Result() (int64, error) {
+	if c.err != nil {
+		return 0, c.err
+	}
+	return c.result, nil
+}
+
+// Err returns the error set on this command.
+func (c *Count) Err() error { return c.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (c *Count) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (int64, error) {
+	cmd, err := c.encode(desc)
+	if err != nil {
+		return 0, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return 0, err
+	}
+
+	return c.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/count_documents.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/count_documents.go
new file mode 100644
index 0000000..a9a27f1
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/count_documents.go
@@ -0,0 +1,122 @@
+// 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 command
+
+import (
+	"context"
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// CountDocuments represents the CountDocuments command.
+//
+// The countDocuments command counts how many documents in a collection match the given query.
+type CountDocuments struct {
+	NS          Namespace
+	Pipeline    bsonx.Arr
+	Opts        []bsonx.Elem
+	ReadPref    *readpref.ReadPref
+	ReadConcern *readconcern.ReadConcern
+	Clock       *session.ClusterClock
+	Session     *session.Client
+
+	result int64
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (c *CountDocuments) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	if err := c.NS.Validate(); err != nil {
+		return nil, err
+	}
+	command := bsonx.Doc{{"aggregate", bsonx.String(c.NS.Collection)}, {"pipeline", bsonx.Array(c.Pipeline)}}
+
+	command = append(command, bsonx.Elem{"cursor", bsonx.Document(bsonx.Doc{})})
+	command = append(command, c.Opts...)
+
+	return (&Read{DB: c.NS.DB, ReadPref: c.ReadPref, Command: command}).Encode(desc)
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (c *CountDocuments) Decode(ctx context.Context, desc description.SelectedServer, wm wiremessage.WireMessage) *CountDocuments {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		c.err = err
+		return c
+	}
+
+	cursor, err := rdr.LookupErr("cursor")
+	if err != nil || cursor.Type != bsontype.EmbeddedDocument {
+		c.err = errors.New("Invalid response from server, no 'cursor' field")
+		return c
+	}
+	batch, err := cursor.Document().LookupErr("firstBatch")
+	if err != nil || batch.Type != bsontype.Array {
+		c.err = errors.New("Invalid response from server, no 'firstBatch' field")
+		return c
+	}
+
+	elem, err := batch.Array().IndexErr(0)
+	if err != nil || elem.Value().Type != bsontype.EmbeddedDocument {
+		c.result = 0
+		return c
+	}
+
+	val, err := elem.Value().Document().LookupErr("n")
+	if err != nil {
+		c.err = errors.New("Invalid response from server, no 'n' field")
+		return c
+	}
+
+	switch val.Type {
+	case bsontype.Int32:
+		c.result = int64(val.Int32())
+	case bsontype.Int64:
+		c.result = val.Int64()
+	default:
+		c.err = errors.New("Invalid response from server, value field is not a number")
+	}
+
+	return c
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (c *CountDocuments) Result() (int64, error) {
+	if c.err != nil {
+		return 0, c.err
+	}
+	return c.result, nil
+}
+
+// Err returns the error set on this command.
+func (c *CountDocuments) Err() error { return c.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (c *CountDocuments) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (int64, error) {
+	wm, err := c.Encode(desc)
+	if err != nil {
+		return 0, err
+	}
+
+	err = rw.WriteWireMessage(ctx, wm)
+	if err != nil {
+		return 0, err
+	}
+	wm, err = rw.ReadWireMessage(ctx)
+	if err != nil {
+		return 0, err
+	}
+	return c.Decode(ctx, desc, wm).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/create_indexes.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/create_indexes.go
new file mode 100644
index 0000000..e2b33c3
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/create_indexes.go
@@ -0,0 +1,106 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// CreateIndexes represents the createIndexes command.
+//
+// The createIndexes command creates indexes for a namespace.
+type CreateIndexes struct {
+	NS           Namespace
+	Indexes      bsonx.Arr
+	Opts         []bsonx.Elem
+	WriteConcern *writeconcern.WriteConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result result.CreateIndexes
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (ci *CreateIndexes) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := ci.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (ci *CreateIndexes) encode(desc description.SelectedServer) (*Write, error) {
+	cmd := bsonx.Doc{
+		{"createIndexes", bsonx.String(ci.NS.Collection)},
+		{"indexes", bsonx.Array(ci.Indexes)},
+	}
+	cmd = append(cmd, ci.Opts...)
+
+	write := &Write{
+		Clock:   ci.Clock,
+		DB:      ci.NS.DB,
+		Command: cmd,
+		Session: ci.Session,
+	}
+	if desc.WireVersion != nil && desc.WireVersion.Max >= 5 {
+		write.WriteConcern = ci.WriteConcern
+	}
+	return write, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (ci *CreateIndexes) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *CreateIndexes {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		ci.err = err
+		return ci
+	}
+
+	return ci.decode(desc, rdr)
+}
+
+func (ci *CreateIndexes) decode(desc description.SelectedServer, rdr bson.Raw) *CreateIndexes {
+	ci.err = bson.Unmarshal(rdr, &ci.result)
+	return ci
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (ci *CreateIndexes) Result() (result.CreateIndexes, error) {
+	if ci.err != nil {
+		return result.CreateIndexes{}, ci.err
+	}
+	return ci.result, nil
+}
+
+// Err returns the error set on this command.
+func (ci *CreateIndexes) Err() error { return ci.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (ci *CreateIndexes) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.CreateIndexes, error) {
+	cmd, err := ci.encode(desc)
+	if err != nil {
+		return result.CreateIndexes{}, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.CreateIndexes{}, err
+	}
+
+	return ci.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/delete.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/delete.go
new file mode 100644
index 0000000..de20dd7
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/delete.go
@@ -0,0 +1,154 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Delete represents the delete command.
+//
+// The delete command executes a delete with a given set of delete documents
+// and options.
+type Delete struct {
+	ContinueOnError bool
+	NS              Namespace
+	Deletes         []bsonx.Doc
+	Opts            []bsonx.Elem
+	WriteConcern    *writeconcern.WriteConcern
+	Clock           *session.ClusterClock
+	Session         *session.Client
+
+	batches []*WriteBatch
+	result  result.Delete
+	err     error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (d *Delete) Encode(desc description.SelectedServer) ([]wiremessage.WireMessage, error) {
+	err := d.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return batchesToWireMessage(d.batches, desc)
+}
+
+func (d *Delete) encode(desc description.SelectedServer) error {
+	batches, err := splitBatches(d.Deletes, int(desc.MaxBatchCount), int(desc.MaxDocumentSize))
+	if err != nil {
+		return err
+	}
+
+	for _, docs := range batches {
+		cmd, err := d.encodeBatch(docs, desc)
+		if err != nil {
+			return err
+		}
+
+		d.batches = append(d.batches, cmd)
+	}
+
+	return nil
+}
+
+func (d *Delete) encodeBatch(docs []bsonx.Doc, desc description.SelectedServer) (*WriteBatch, error) {
+	copyDocs := make([]bsonx.Doc, 0, len(docs))
+	for _, doc := range docs {
+		copyDocs = append(copyDocs, doc.Copy())
+	}
+
+	var options []bsonx.Elem
+	for _, opt := range d.Opts {
+		if opt.Key == "collation" {
+			for idx := range copyDocs {
+				copyDocs[idx] = append(copyDocs[idx], opt)
+			}
+		} else {
+			options = append(options, opt)
+		}
+	}
+
+	command, err := encodeBatch(copyDocs, options, DeleteCommand, d.NS.Collection)
+	if err != nil {
+		return nil, err
+	}
+
+	return &WriteBatch{
+		&Write{
+			Clock:        d.Clock,
+			DB:           d.NS.DB,
+			Command:      command,
+			WriteConcern: d.WriteConcern,
+			Session:      d.Session,
+		},
+		len(docs),
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (d *Delete) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Delete {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		d.err = err
+		return d
+	}
+
+	return d.decode(desc, rdr)
+}
+
+func (d *Delete) decode(desc description.SelectedServer, rdr bson.Raw) *Delete {
+	d.err = bson.Unmarshal(rdr, &d.result)
+	return d
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (d *Delete) Result() (result.Delete, error) {
+	if d.err != nil {
+		return result.Delete{}, d.err
+	}
+	return d.result, nil
+}
+
+// Err returns the error set on this command.
+func (d *Delete) Err() error { return d.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (d *Delete) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.Delete, error) {
+	if d.batches == nil {
+		if err := d.encode(desc); err != nil {
+			return result.Delete{}, err
+		}
+	}
+
+	r, batches, err := roundTripBatches(
+		ctx, desc, rw,
+		d.batches,
+		d.ContinueOnError,
+		d.Session,
+		DeleteCommand,
+	)
+
+	if batches != nil {
+		d.batches = batches
+	}
+
+	if err != nil {
+		return result.Delete{}, err
+	}
+
+	return r.(result.Delete), nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/distinct.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/distinct.go
new file mode 100644
index 0000000..ba793e1
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/distinct.go
@@ -0,0 +1,115 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Distinct represents the disctinct command.
+//
+// The distinct command returns the distinct values for a specified field
+// across a single collection.
+type Distinct struct {
+	NS          Namespace
+	Field       string
+	Query       bsonx.Doc
+	Opts        []bsonx.Elem
+	ReadPref    *readpref.ReadPref
+	ReadConcern *readconcern.ReadConcern
+	Clock       *session.ClusterClock
+	Session     *session.Client
+
+	result result.Distinct
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (d *Distinct) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := d.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (d *Distinct) encode(desc description.SelectedServer) (*Read, error) {
+	if err := d.NS.Validate(); err != nil {
+		return nil, err
+	}
+
+	command := bsonx.Doc{{"distinct", bsonx.String(d.NS.Collection)}, {"key", bsonx.String(d.Field)}}
+
+	if d.Query != nil {
+		command = append(command, bsonx.Elem{"query", bsonx.Document(d.Query)})
+	}
+
+	command = append(command, d.Opts...)
+
+	return &Read{
+		Clock:       d.Clock,
+		DB:          d.NS.DB,
+		ReadPref:    d.ReadPref,
+		Command:     command,
+		ReadConcern: d.ReadConcern,
+		Session:     d.Session,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (d *Distinct) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Distinct {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		d.err = err
+		return d
+	}
+
+	return d.decode(desc, rdr)
+}
+
+func (d *Distinct) decode(desc description.SelectedServer, rdr bson.Raw) *Distinct {
+	d.err = bson.Unmarshal(rdr, &d.result)
+	return d
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (d *Distinct) Result() (result.Distinct, error) {
+	if d.err != nil {
+		return result.Distinct{}, d.err
+	}
+	return d.result, nil
+}
+
+// Err returns the error set on this command.
+func (d *Distinct) Err() error { return d.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (d *Distinct) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.Distinct, error) {
+	cmd, err := d.encode(desc)
+	if err != nil {
+		return result.Distinct{}, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.Distinct{}, err
+	}
+
+	return d.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/doc.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/doc.go
new file mode 100644
index 0000000..ea7a308
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/doc.go
@@ -0,0 +1,16 @@
+// 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 command contains abstractions for operations that can be performed against a MongoDB
+// deployment. The types in this package are meant to provide a general set of commands that a
+// user can run against a MongoDB database without knowing the version of the database.
+//
+// Each type consists of two levels of interaction. The lowest level are the Encode and Decode
+// methods. These are meant to be symmetric eventually, but currently only support the driver
+// side of commands. The higher level is the RoundTrip method. This only makes sense from the
+// driver side of commands and this method handles the encoding of the request and decoding of
+// the response using the given wiremessage.ReadWriter.
+package command
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_collection.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_collection.go
new file mode 100644
index 0000000..c067ccc
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_collection.go
@@ -0,0 +1,101 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// DropCollection represents the drop command.
+//
+// The dropCollections command drops collection for a database.
+type DropCollection struct {
+	DB           string
+	Collection   string
+	WriteConcern *writeconcern.WriteConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (dc *DropCollection) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := dc.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (dc *DropCollection) encode(desc description.SelectedServer) (*Write, error) {
+	cmd := bsonx.Doc{{"drop", bsonx.String(dc.Collection)}}
+
+	write := &Write{
+		Clock:   dc.Clock,
+		DB:      dc.DB,
+		Command: cmd,
+		Session: dc.Session,
+	}
+	if desc.WireVersion != nil && desc.WireVersion.Max >= 5 {
+		write.WriteConcern = dc.WriteConcern
+	}
+	return write, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (dc *DropCollection) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *DropCollection {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		dc.err = err
+		return dc
+	}
+
+	return dc.decode(desc, rdr)
+}
+
+func (dc *DropCollection) decode(desc description.SelectedServer, rdr bson.Raw) *DropCollection {
+	dc.result = rdr
+	return dc
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (dc *DropCollection) Result() (bson.Raw, error) {
+	if dc.err != nil {
+		return nil, dc.err
+	}
+
+	return dc.result, nil
+}
+
+// Err returns the error set on this command.
+func (dc *DropCollection) Err() error { return dc.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (dc *DropCollection) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	cmd, err := dc.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return nil, err
+	}
+
+	return dc.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_database.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_database.go
new file mode 100644
index 0000000..e3b3f7c
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_database.go
@@ -0,0 +1,100 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// DropDatabase represents the DropDatabase command.
+//
+// The DropDatabases command drops database.
+type DropDatabase struct {
+	DB           string
+	WriteConcern *writeconcern.WriteConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (dd *DropDatabase) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := dd.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (dd *DropDatabase) encode(desc description.SelectedServer) (*Write, error) {
+	cmd := bsonx.Doc{{"dropDatabase", bsonx.Int32(1)}}
+
+	write := &Write{
+		Clock:   dd.Clock,
+		DB:      dd.DB,
+		Command: cmd,
+		Session: dd.Session,
+	}
+	if desc.WireVersion != nil && desc.WireVersion.Max >= 5 {
+		write.WriteConcern = dd.WriteConcern
+	}
+	return write, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (dd *DropDatabase) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *DropDatabase {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		dd.err = err
+		return dd
+	}
+
+	return dd.decode(desc, rdr)
+}
+
+func (dd *DropDatabase) decode(desc description.SelectedServer, rdr bson.Raw) *DropDatabase {
+	dd.result = rdr
+	return dd
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (dd *DropDatabase) Result() (bson.Raw, error) {
+	if dd.err != nil {
+		return nil, dd.err
+	}
+
+	return dd.result, nil
+}
+
+// Err returns the error set on this command.
+func (dd *DropDatabase) Err() error { return dd.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (dd *DropDatabase) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	cmd, err := dd.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return nil, err
+	}
+
+	return dd.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_indexes.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_indexes.go
new file mode 100644
index 0000000..bf6a7d6
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/drop_indexes.go
@@ -0,0 +1,106 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// DropIndexes represents the dropIndexes command.
+//
+// The dropIndexes command drops indexes for a namespace.
+type DropIndexes struct {
+	NS           Namespace
+	Index        string
+	Opts         []bsonx.Elem
+	WriteConcern *writeconcern.WriteConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (di *DropIndexes) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := di.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (di *DropIndexes) encode(desc description.SelectedServer) (*Write, error) {
+	cmd := bsonx.Doc{
+		{"dropIndexes", bsonx.String(di.NS.Collection)},
+		{"index", bsonx.String(di.Index)},
+	}
+	cmd = append(cmd, di.Opts...)
+
+	write := &Write{
+		Clock:   di.Clock,
+		DB:      di.NS.DB,
+		Command: cmd,
+		Session: di.Session,
+	}
+	if desc.WireVersion != nil && desc.WireVersion.Max >= 5 {
+		write.WriteConcern = di.WriteConcern
+	}
+	return write, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (di *DropIndexes) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *DropIndexes {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		di.err = err
+		return di
+	}
+
+	return di.decode(desc, rdr)
+}
+
+func (di *DropIndexes) decode(desc description.SelectedServer, rdr bson.Raw) *DropIndexes {
+	di.result = rdr
+	return di
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (di *DropIndexes) Result() (bson.Raw, error) {
+	if di.err != nil {
+		return nil, di.err
+	}
+
+	return di.result, nil
+}
+
+// Err returns the error set on this command.
+func (di *DropIndexes) Err() error { return di.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (di *DropIndexes) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	cmd, err := di.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	di.result, err = cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return nil, err
+	}
+
+	return di.Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/end_sessions.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/end_sessions.go
new file mode 100644
index 0000000..11ac140
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/end_sessions.go
@@ -0,0 +1,138 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// must be sent to admin db
+// { endSessions: [ {id: uuid}, ... ], $clusterTime: ... }
+// only send $clusterTime when gossiping the cluster time
+// send 10k sessions at a time
+
+// EndSessions represents an endSessions command.
+type EndSessions struct {
+	Clock      *session.ClusterClock
+	SessionIDs []bsonx.Doc
+
+	results []result.EndSessions
+	errors  []error
+}
+
+// BatchSize is the max number of sessions to be included in 1 endSessions command.
+const BatchSize = 10000
+
+func (es *EndSessions) split() [][]bsonx.Doc {
+	batches := [][]bsonx.Doc{}
+	docIndex := 0
+	totalNumDocs := len(es.SessionIDs)
+
+createBatches:
+	for {
+		batch := []bsonx.Doc{}
+
+		for i := 0; i < BatchSize; i++ {
+			if docIndex == totalNumDocs {
+				break createBatches
+			}
+
+			batch = append(batch, es.SessionIDs[docIndex])
+			docIndex++
+		}
+
+		batches = append(batches, batch)
+	}
+
+	return batches
+}
+
+func (es *EndSessions) encodeBatch(batch []bsonx.Doc, desc description.SelectedServer) *Write {
+	vals := make(bsonx.Arr, 0, len(batch))
+	for _, doc := range batch {
+		vals = append(vals, bsonx.Document(doc))
+	}
+
+	cmd := bsonx.Doc{{"endSessions", bsonx.Array(vals)}}
+
+	return &Write{
+		Clock:   es.Clock,
+		DB:      "admin",
+		Command: cmd,
+	}
+}
+
+// Encode will encode this command into a series of wire messages for the given server description.
+func (es *EndSessions) Encode(desc description.SelectedServer) ([]wiremessage.WireMessage, error) {
+	cmds := es.encode(desc)
+	wms := make([]wiremessage.WireMessage, len(cmds))
+
+	for _, cmd := range cmds {
+		wm, err := cmd.Encode(desc)
+		if err != nil {
+			return nil, err
+		}
+
+		wms = append(wms, wm)
+	}
+
+	return wms, nil
+}
+
+func (es *EndSessions) encode(desc description.SelectedServer) []*Write {
+	out := []*Write{}
+	batches := es.split()
+
+	for _, batch := range batches {
+		out = append(out, es.encodeBatch(batch, desc))
+	}
+
+	return out
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (es *EndSessions) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *EndSessions {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		es.errors = append(es.errors, err)
+		return es
+	}
+
+	return es.decode(desc, rdr)
+}
+
+func (es *EndSessions) decode(desc description.SelectedServer, rdr bson.Raw) *EndSessions {
+	var res result.EndSessions
+	es.errors = append(es.errors, bson.Unmarshal(rdr, &res))
+	es.results = append(es.results, res)
+	return es
+}
+
+// Result returns the results of the decoded wire messages.
+func (es *EndSessions) Result() ([]result.EndSessions, []error) {
+	return es.results, es.errors
+}
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter
+func (es *EndSessions) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) ([]result.EndSessions, []error) {
+	cmds := es.encode(desc)
+
+	for _, cmd := range cmds {
+		rdr, _ := cmd.RoundTrip(ctx, desc, rw) // ignore any errors returned by the command
+		es.decode(desc, rdr)
+	}
+
+	return es.Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/errors.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/errors.go
new file mode 100644
index 0000000..5ecb48c
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/errors.go
@@ -0,0 +1,141 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package command
+
+import (
+	"errors"
+	"fmt"
+
+	"strings"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+var (
+	// ErrUnknownCommandFailure occurs when a command fails for an unknown reason.
+	ErrUnknownCommandFailure = errors.New("unknown command failure")
+	// ErrNoCommandResponse occurs when the server sent no response document to a command.
+	ErrNoCommandResponse = errors.New("no command response document")
+	// ErrMultiDocCommandResponse occurs when the server sent multiple documents in response to a command.
+	ErrMultiDocCommandResponse = errors.New("command returned multiple documents")
+	// ErrNoDocCommandResponse occurs when the server indicated a response existed, but none was found.
+	ErrNoDocCommandResponse = errors.New("command returned no documents")
+	// ErrDocumentTooLarge occurs when a document that is larger than the maximum size accepted by a
+	// server is passed to an insert command.
+	ErrDocumentTooLarge = errors.New("an inserted document is too large")
+	// ErrNonPrimaryRP occurs when a nonprimary read preference is used with a transaction.
+	ErrNonPrimaryRP = errors.New("read preference in a transaction must be primary")
+	// UnknownTransactionCommitResult is an error label for unknown transaction commit results.
+	UnknownTransactionCommitResult = "UnknownTransactionCommitResult"
+	// TransientTransactionError is an error label for transient errors with transactions.
+	TransientTransactionError = "TransientTransactionError"
+	// NetworkError is an error label for network errors.
+	NetworkError = "NetworkError"
+	// ReplyDocumentMismatch is an error label for OP_QUERY field mismatch errors.
+	ReplyDocumentMismatch = "malformed OP_REPLY: NumberReturned does not match number of documents returned"
+)
+
+var retryableCodes = []int32{11600, 11602, 10107, 13435, 13436, 189, 91, 7, 6, 89, 9001}
+
+// QueryFailureError is an error representing a command failure as a document.
+type QueryFailureError struct {
+	Message  string
+	Response bson.Raw
+}
+
+// Error implements the error interface.
+func (e QueryFailureError) Error() string {
+	return fmt.Sprintf("%s: %v", e.Message, e.Response)
+}
+
+// ResponseError is an error parsing the response to a command.
+type ResponseError struct {
+	Message string
+	Wrapped error
+}
+
+// NewCommandResponseError creates a CommandResponseError.
+func NewCommandResponseError(msg string, err error) ResponseError {
+	return ResponseError{Message: msg, Wrapped: err}
+}
+
+// Error implements the error interface.
+func (e ResponseError) Error() string {
+	if e.Wrapped != nil {
+		return fmt.Sprintf("%s: %s", e.Message, e.Wrapped)
+	}
+	return fmt.Sprintf("%s", e.Message)
+}
+
+// Error is a command execution error from the database.
+type Error struct {
+	Code    int32
+	Message string
+	Labels  []string
+	Name    string
+}
+
+// Error implements the error interface.
+func (e Error) Error() string {
+	if e.Name != "" {
+		return fmt.Sprintf("(%v) %v", e.Name, e.Message)
+	}
+	return e.Message
+}
+
+// HasErrorLabel returns true if the error contains the specified label.
+func (e Error) HasErrorLabel(label string) bool {
+	if e.Labels != nil {
+		for _, l := range e.Labels {
+			if l == label {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// Retryable returns true if the error is retryable
+func (e Error) Retryable() bool {
+	for _, label := range e.Labels {
+		if label == NetworkError {
+			return true
+		}
+	}
+	for _, code := range retryableCodes {
+		if e.Code == code {
+			return true
+		}
+	}
+	if strings.Contains(e.Message, "not master") || strings.Contains(e.Message, "node is recovering") {
+		return true
+	}
+
+	return false
+}
+
+// IsWriteConcernErrorRetryable returns true if the write concern error is retryable.
+func IsWriteConcernErrorRetryable(wce *result.WriteConcernError) bool {
+	for _, code := range retryableCodes {
+		if int32(wce.Code) == code {
+			return true
+		}
+	}
+	if strings.Contains(wce.ErrMsg, "not master") || strings.Contains(wce.ErrMsg, "node is recovering") {
+		return true
+	}
+
+	return false
+}
+
+// IsNotFound indicates if the error is from a namespace not being found.
+func IsNotFound(err error) bool {
+	e, ok := err.(Error)
+	// need message check because legacy servers don't include the error code
+	return ok && (e.Code == 26 || e.Message == "ns not found")
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find.go
new file mode 100644
index 0000000..e9d135e
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find.go
@@ -0,0 +1,113 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Find represents the find command.
+//
+// The find command finds documents within a collection that match a filter.
+type Find struct {
+	NS          Namespace
+	Filter      bsonx.Doc
+	CursorOpts  []bsonx.Elem
+	Opts        []bsonx.Elem
+	ReadPref    *readpref.ReadPref
+	ReadConcern *readconcern.ReadConcern
+	Clock       *session.ClusterClock
+	Session     *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (f *Find) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := f.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (f *Find) encode(desc description.SelectedServer) (*Read, error) {
+	if err := f.NS.Validate(); err != nil {
+		return nil, err
+	}
+
+	command := bsonx.Doc{{"find", bsonx.String(f.NS.Collection)}}
+
+	if f.Filter != nil {
+		command = append(command, bsonx.Elem{"filter", bsonx.Document(f.Filter)})
+	}
+
+	command = append(command, f.Opts...)
+
+	return &Read{
+		Clock:       f.Clock,
+		DB:          f.NS.DB,
+		ReadPref:    f.ReadPref,
+		Command:     command,
+		ReadConcern: f.ReadConcern,
+		Session:     f.Session,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (f *Find) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Find {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		f.err = err
+		return f
+	}
+
+	return f.decode(desc, rdr)
+}
+
+func (f *Find) decode(desc description.SelectedServer, rdr bson.Raw) *Find {
+	f.result = rdr
+	return f
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (f *Find) Result() (bson.Raw, error) {
+	if f.err != nil {
+		return nil, f.err
+	}
+
+	return f.result, nil
+}
+
+// Err returns the error set on this command.
+func (f *Find) Err() error { return f.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (f *Find) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	cmd, err := f.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return nil, err
+	}
+
+	return f.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_and_modify.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_and_modify.go
new file mode 100644
index 0000000..260ee37
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_and_modify.go
@@ -0,0 +1,51 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package command
+
+import (
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// unmarshalFindAndModifyResult turns the provided bson.Reader into a findAndModify result.
+func unmarshalFindAndModifyResult(rdr bson.Raw) (result.FindAndModify, error) {
+	var res result.FindAndModify
+
+	val, err := rdr.LookupErr("value")
+	switch {
+	case err == bsoncore.ErrElementNotFound:
+		return result.FindAndModify{}, errors.New("invalid response from server, no value field")
+	case err != nil:
+		return result.FindAndModify{}, err
+	}
+
+	switch val.Type {
+	case bson.TypeNull:
+	case bson.TypeEmbeddedDocument:
+		res.Value = val.Document()
+	default:
+		return result.FindAndModify{}, errors.New("invalid response from server, 'value' field is not a document")
+	}
+
+	if val, err := rdr.LookupErr("lastErrorObject", "updatedExisting"); err == nil {
+		b, ok := val.BooleanOK()
+		if ok {
+			res.LastErrorObject.UpdatedExisting = b
+		}
+	}
+
+	if val, err := rdr.LookupErr("lastErrorObject", "upserted"); err == nil {
+		oid, ok := val.ObjectIDOK()
+		if ok {
+			res.LastErrorObject.Upserted = oid
+		}
+	}
+	return res, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_delete.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_delete.go
new file mode 100644
index 0000000..f5c36d2
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_delete.go
@@ -0,0 +1,111 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// FindOneAndDelete represents the findOneAndDelete operation.
+//
+// The findOneAndDelete command deletes a single document that matches a query and returns it.
+type FindOneAndDelete struct {
+	NS           Namespace
+	Query        bsonx.Doc
+	Opts         []bsonx.Elem
+	WriteConcern *writeconcern.WriteConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result result.FindAndModify
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (f *FindOneAndDelete) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := f.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (f *FindOneAndDelete) encode(desc description.SelectedServer) (*Write, error) {
+	if err := f.NS.Validate(); err != nil {
+		return nil, err
+	}
+
+	command := bsonx.Doc{
+		{"findAndModify", bsonx.String(f.NS.Collection)},
+		{"query", bsonx.Document(f.Query)},
+		{"remove", bsonx.Boolean(true)},
+	}
+	command = append(command, f.Opts...)
+
+	write := &Write{
+		Clock:   f.Clock,
+		DB:      f.NS.DB,
+		Command: command,
+		Session: f.Session,
+	}
+	if desc.WireVersion != nil && desc.WireVersion.Max >= 4 {
+		write.WriteConcern = f.WriteConcern
+	}
+	return write, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (f *FindOneAndDelete) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *FindOneAndDelete {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		f.err = err
+		return f
+	}
+
+	return f.decode(desc, rdr)
+}
+
+func (f *FindOneAndDelete) decode(desc description.SelectedServer, rdr bson.Raw) *FindOneAndDelete {
+	f.result, f.err = unmarshalFindAndModifyResult(rdr)
+	return f
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (f *FindOneAndDelete) Result() (result.FindAndModify, error) {
+	if f.err != nil {
+		return result.FindAndModify{}, f.err
+	}
+	return f.result, nil
+}
+
+// Err returns the error set on this command.
+func (f *FindOneAndDelete) Err() error { return f.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (f *FindOneAndDelete) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.FindAndModify, error) {
+	cmd, err := f.encode(desc)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	return f.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_replace.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_replace.go
new file mode 100644
index 0000000..b3139f8
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_replace.go
@@ -0,0 +1,112 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// FindOneAndReplace represents the findOneAndReplace operation.
+//
+// The findOneAndReplace command modifies and returns a single document.
+type FindOneAndReplace struct {
+	NS           Namespace
+	Query        bsonx.Doc
+	Replacement  bsonx.Doc
+	Opts         []bsonx.Elem
+	WriteConcern *writeconcern.WriteConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result result.FindAndModify
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (f *FindOneAndReplace) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := f.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (f *FindOneAndReplace) encode(desc description.SelectedServer) (*Write, error) {
+	if err := f.NS.Validate(); err != nil {
+		return nil, err
+	}
+
+	command := bsonx.Doc{
+		{"findAndModify", bsonx.String(f.NS.Collection)},
+		{"query", bsonx.Document(f.Query)},
+		{"update", bsonx.Document(f.Replacement)},
+	}
+	command = append(command, f.Opts...)
+
+	write := &Write{
+		Clock:   f.Clock,
+		DB:      f.NS.DB,
+		Command: command,
+		Session: f.Session,
+	}
+	if desc.WireVersion != nil && desc.WireVersion.Max >= 4 {
+		write.WriteConcern = f.WriteConcern
+	}
+	return write, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (f *FindOneAndReplace) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *FindOneAndReplace {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		f.err = err
+		return f
+	}
+
+	return f.decode(desc, rdr)
+}
+
+func (f *FindOneAndReplace) decode(desc description.SelectedServer, rdr bson.Raw) *FindOneAndReplace {
+	f.result, f.err = unmarshalFindAndModifyResult(rdr)
+	return f
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (f *FindOneAndReplace) Result() (result.FindAndModify, error) {
+	if f.err != nil {
+		return result.FindAndModify{}, f.err
+	}
+	return f.result, nil
+}
+
+// Err returns the error set on this command.
+func (f *FindOneAndReplace) Err() error { return f.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (f *FindOneAndReplace) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.FindAndModify, error) {
+	cmd, err := f.encode(desc)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	return f.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_update.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_update.go
new file mode 100644
index 0000000..b90c7d0
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/find_one_update.go
@@ -0,0 +1,112 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// FindOneAndUpdate represents the findOneAndUpdate operation.
+//
+// The findOneAndUpdate command modifies and returns a single document.
+type FindOneAndUpdate struct {
+	NS           Namespace
+	Query        bsonx.Doc
+	Update       bsonx.Doc
+	Opts         []bsonx.Elem
+	WriteConcern *writeconcern.WriteConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result result.FindAndModify
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (f *FindOneAndUpdate) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := f.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (f *FindOneAndUpdate) encode(desc description.SelectedServer) (*Write, error) {
+	if err := f.NS.Validate(); err != nil {
+		return nil, err
+	}
+
+	command := bsonx.Doc{
+		{"findAndModify", bsonx.String(f.NS.Collection)},
+		{"query", bsonx.Document(f.Query)},
+		{"update", bsonx.Document(f.Update)},
+	}
+	command = append(command, f.Opts...)
+
+	write := &Write{
+		Clock:   f.Clock,
+		DB:      f.NS.DB,
+		Command: command,
+		Session: f.Session,
+	}
+	if desc.WireVersion != nil && desc.WireVersion.Max >= 4 {
+		write.WriteConcern = f.WriteConcern
+	}
+	return write, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (f *FindOneAndUpdate) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *FindOneAndUpdate {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		f.err = err
+		return f
+	}
+
+	return f.decode(desc, rdr)
+}
+
+func (f *FindOneAndUpdate) decode(desc description.SelectedServer, rdr bson.Raw) *FindOneAndUpdate {
+	f.result, f.err = unmarshalFindAndModifyResult(rdr)
+	return f
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (f *FindOneAndUpdate) Result() (result.FindAndModify, error) {
+	if f.err != nil {
+		return result.FindAndModify{}, f.err
+	}
+	return f.result, nil
+}
+
+// Err returns the error set on this command.
+func (f *FindOneAndUpdate) Err() error { return f.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (f *FindOneAndUpdate) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.FindAndModify, error) {
+	cmd, err := f.encode(desc)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.FindAndModify{}, err
+	}
+
+	return f.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/get_more.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/get_more.go
new file mode 100644
index 0000000..ce016b1
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/get_more.go
@@ -0,0 +1,108 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// GetMore represents the getMore command.
+//
+// The getMore command retrieves additional documents from a cursor.
+type GetMore struct {
+	ID      int64
+	NS      Namespace
+	Opts    []bsonx.Elem
+	Clock   *session.ClusterClock
+	Session *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (gm *GetMore) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd, err := gm.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return cmd.Encode(desc)
+}
+
+func (gm *GetMore) encode(desc description.SelectedServer) (*Read, error) {
+	cmd := bsonx.Doc{
+		{"getMore", bsonx.Int64(gm.ID)},
+		{"collection", bsonx.String(gm.NS.Collection)},
+	}
+
+	for _, opt := range gm.Opts {
+		switch opt.Key {
+		case "maxAwaitTimeMS":
+			cmd = append(cmd, bsonx.Elem{"maxTimeMs", opt.Value})
+		default:
+			cmd = append(cmd, opt)
+		}
+	}
+
+	return &Read{
+		Clock:   gm.Clock,
+		DB:      gm.NS.DB,
+		Command: cmd,
+		Session: gm.Session,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (gm *GetMore) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *GetMore {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		gm.err = err
+		return gm
+	}
+
+	return gm.decode(desc, rdr)
+}
+
+func (gm *GetMore) decode(desc description.SelectedServer, rdr bson.Raw) *GetMore {
+	gm.result = rdr
+	return gm
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (gm *GetMore) Result() (bson.Raw, error) {
+	if gm.err != nil {
+		return nil, gm.err
+	}
+
+	return gm.result, nil
+}
+
+// Err returns the error set on this command.
+func (gm *GetMore) Err() error { return gm.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (gm *GetMore) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	cmd, err := gm.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return nil, err
+	}
+
+	return gm.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/getlasterror.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/getlasterror.go
new file mode 100644
index 0000000..4f68c3c
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/getlasterror.go
@@ -0,0 +1,111 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package command
+
+import (
+	"context"
+
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// GetLastError represents the getLastError command.
+//
+// The getLastError command is used for getting the last
+// error from the last command on a connection.
+//
+// Since GetLastError only makes sense in the context of
+// a single connection, there is no Dispatch method.
+type GetLastError struct {
+	Clock   *session.ClusterClock
+	Session *session.Client
+
+	err error
+	res result.GetLastError
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (gle *GetLastError) Encode() (wiremessage.WireMessage, error) {
+	encoded, err := gle.encode()
+	if err != nil {
+		return nil, err
+	}
+	return encoded.Encode(description.SelectedServer{})
+}
+
+func (gle *GetLastError) encode() (*Read, error) {
+	// This can probably just be a global variable that we reuse.
+	cmd := bsonx.Doc{{"getLastError", bsonx.Int32(1)}}
+
+	return &Read{
+		Clock:    gle.Clock,
+		DB:       "admin",
+		ReadPref: readpref.Secondary(),
+		Session:  gle.Session,
+		Command:  cmd,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (gle *GetLastError) Decode(wm wiremessage.WireMessage) *GetLastError {
+	reply, ok := wm.(wiremessage.Reply)
+	if !ok {
+		gle.err = fmt.Errorf("unsupported response wiremessage type %T", wm)
+		return gle
+	}
+	rdr, err := decodeCommandOpReply(reply)
+	if err != nil {
+		gle.err = err
+		return gle
+	}
+	return gle.decode(rdr)
+}
+
+func (gle *GetLastError) decode(rdr bson.Raw) *GetLastError {
+	err := bson.Unmarshal(rdr, &gle.res)
+	if err != nil {
+		gle.err = err
+		return gle
+	}
+
+	return gle
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (gle *GetLastError) Result() (result.GetLastError, error) {
+	if gle.err != nil {
+		return result.GetLastError{}, gle.err
+	}
+
+	return gle.res, nil
+}
+
+// Err returns the error set on this command.
+func (gle *GetLastError) Err() error { return gle.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (gle *GetLastError) RoundTrip(ctx context.Context, rw wiremessage.ReadWriter) (result.GetLastError, error) {
+	cmd, err := gle.encode()
+	if err != nil {
+		return result.GetLastError{}, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, description.SelectedServer{}, rw)
+	if err != nil {
+		return result.GetLastError{}, err
+	}
+
+	return gle.decode(rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/handshake.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/handshake.go
new file mode 100644
index 0000000..29eb103
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/handshake.go
@@ -0,0 +1,117 @@
+// 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 command
+
+import (
+	"context"
+	"runtime"
+
+	"github.com/mongodb/mongo-go-driver/version"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Handshake represents a generic MongoDB Handshake. It calls isMaster and
+// buildInfo.
+//
+// The isMaster and buildInfo commands are used to build a server description.
+type Handshake struct {
+	Client             bsonx.Doc
+	Compressors        []string
+	SaslSupportedMechs string
+
+	ismstr result.IsMaster
+	err    error
+}
+
+// Encode will encode the handshake commands into a wire message containing isMaster
+func (h *Handshake) Encode() (wiremessage.WireMessage, error) {
+	var wm wiremessage.WireMessage
+	ismstr, err := (&IsMaster{
+		Client:             h.Client,
+		Compressors:        h.Compressors,
+		SaslSupportedMechs: h.SaslSupportedMechs,
+	}).Encode()
+	if err != nil {
+		return wm, err
+	}
+
+	wm = ismstr
+	return wm, nil
+}
+
+// Decode will decode the wire messages.
+// Errors during decoding are deferred until either the Result or Err methods
+// are called.
+func (h *Handshake) Decode(wm wiremessage.WireMessage) *Handshake {
+	h.ismstr, h.err = (&IsMaster{}).Decode(wm).Result()
+	if h.err != nil {
+		return h
+	}
+	return h
+}
+
+// Result returns the result of decoded wire messages.
+func (h *Handshake) Result(addr address.Address) (description.Server, error) {
+	if h.err != nil {
+		return description.Server{}, h.err
+	}
+	return description.NewServer(addr, h.ismstr), nil
+}
+
+// Err returns the error set on this Handshake.
+func (h *Handshake) Err() error { return h.err }
+
+// Handshake implements the connection.Handshaker interface. It is identical
+// to the RoundTrip methods on other types in this package. It will execute
+// the isMaster command.
+func (h *Handshake) Handshake(ctx context.Context, addr address.Address, rw wiremessage.ReadWriter) (description.Server, error) {
+	wm, err := h.Encode()
+	if err != nil {
+		return description.Server{}, err
+	}
+
+	err = rw.WriteWireMessage(ctx, wm)
+	if err != nil {
+		return description.Server{}, err
+	}
+
+	wm, err = rw.ReadWireMessage(ctx)
+	if err != nil {
+		return description.Server{}, err
+	}
+	return h.Decode(wm).Result(addr)
+}
+
+// ClientDoc creates a client information document for use in an isMaster
+// command.
+func ClientDoc(app string) bsonx.Doc {
+	doc := bsonx.Doc{
+		{"driver",
+			bsonx.Document(bsonx.Doc{
+				{"name", bsonx.String("mongo-go-driver")},
+				{"version", bsonx.String(version.Driver)},
+			}),
+		},
+		{"os",
+			bsonx.Document(bsonx.Doc{
+				{"type", bsonx.String(runtime.GOOS)},
+				{"architecture", bsonx.String(runtime.GOARCH)},
+			}),
+		},
+		{"platform", bsonx.String(runtime.Version())},
+	}
+
+	if app != "" {
+		doc = append(doc, bsonx.Elem{"application", bsonx.Document(bsonx.Doc{{"name", bsonx.String(app)}})})
+	}
+
+	return doc
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/insert.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/insert.go
new file mode 100644
index 0000000..5059630
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/insert.go
@@ -0,0 +1,158 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// this is the amount of reserved buffer space in a message that the
+// driver reserves for command overhead.
+const reservedCommandBufferBytes = 16 * 10 * 10 * 10
+
+// Insert represents the insert command.
+//
+// The insert command inserts a set of documents into the database.
+//
+// Since the Insert command does not return any value other than ok or
+// an error, this type has no Err method.
+type Insert struct {
+	ContinueOnError bool
+	Clock           *session.ClusterClock
+	NS              Namespace
+	Docs            []bsonx.Doc
+	Opts            []bsonx.Elem
+	WriteConcern    *writeconcern.WriteConcern
+	Session         *session.Client
+
+	batches []*WriteBatch
+	result  result.Insert
+	err     error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (i *Insert) Encode(desc description.SelectedServer) ([]wiremessage.WireMessage, error) {
+	err := i.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return batchesToWireMessage(i.batches, desc)
+}
+
+func (i *Insert) encodeBatch(docs []bsonx.Doc, desc description.SelectedServer) (*WriteBatch, error) {
+	command, err := encodeBatch(docs, i.Opts, InsertCommand, i.NS.Collection)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, opt := range i.Opts {
+		if opt.Key == "ordered" && !opt.Value.Boolean() {
+			i.ContinueOnError = true
+			break
+		}
+	}
+
+	return &WriteBatch{
+		&Write{
+			Clock:        i.Clock,
+			DB:           i.NS.DB,
+			Command:      command,
+			WriteConcern: i.WriteConcern,
+			Session:      i.Session,
+		},
+		len(docs),
+	}, nil
+}
+
+func (i *Insert) encode(desc description.SelectedServer) error {
+	batches, err := splitBatches(i.Docs, int(desc.MaxBatchCount), int(desc.MaxDocumentSize))
+	if err != nil {
+		return err
+	}
+
+	for _, docs := range batches {
+		cmd, err := i.encodeBatch(docs, desc)
+		if err != nil {
+			return err
+		}
+
+		i.batches = append(i.batches, cmd)
+	}
+	return nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (i *Insert) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Insert {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		i.err = err
+		return i
+	}
+
+	return i.decode(desc, rdr)
+}
+
+func (i *Insert) decode(desc description.SelectedServer, rdr bson.Raw) *Insert {
+	i.err = bson.Unmarshal(rdr, &i.result)
+	return i
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (i *Insert) Result() (result.Insert, error) {
+	if i.err != nil {
+		return result.Insert{}, i.err
+	}
+	return i.result, nil
+}
+
+// Err returns the error set on this command.
+func (i *Insert) Err() error { return i.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+//func (i *Insert) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.Insert, error) {
+func (i *Insert) RoundTrip(
+	ctx context.Context,
+	desc description.SelectedServer,
+	rw wiremessage.ReadWriter,
+) (result.Insert, error) {
+	if i.batches == nil {
+		err := i.encode(desc)
+		if err != nil {
+			return result.Insert{}, err
+		}
+	}
+
+	r, batches, err := roundTripBatches(
+		ctx, desc, rw,
+		i.batches,
+		i.ContinueOnError,
+		i.Session,
+		InsertCommand,
+	)
+
+	// if there are leftover batches, save them for retry
+	if batches != nil {
+		i.batches = batches
+	}
+
+	if err != nil {
+		return result.Insert{}, err
+	}
+
+	res := r.(result.Insert)
+	return res, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/ismaster.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/ismaster.go
new file mode 100644
index 0000000..6bd8d09
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/ismaster.go
@@ -0,0 +1,121 @@
+// 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 command
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// IsMaster represents the isMaster command.
+//
+// The isMaster command is used for setting up a connection to MongoDB and
+// for monitoring a MongoDB server.
+//
+// Since IsMaster can only be run on a connection, there is no Dispatch method.
+type IsMaster struct {
+	Client             bsonx.Doc
+	Compressors        []string
+	SaslSupportedMechs string
+
+	err error
+	res result.IsMaster
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (im *IsMaster) Encode() (wiremessage.WireMessage, error) {
+	cmd := bsonx.Doc{{"isMaster", bsonx.Int32(1)}}
+	if im.Client != nil {
+		cmd = append(cmd, bsonx.Elem{"client", bsonx.Document(im.Client)})
+	}
+	if im.SaslSupportedMechs != "" {
+		cmd = append(cmd, bsonx.Elem{"saslSupportedMechs", bsonx.String(im.SaslSupportedMechs)})
+	}
+
+	// always send compressors even if empty slice
+	array := bsonx.Arr{}
+	for _, compressor := range im.Compressors {
+		array = append(array, bsonx.String(compressor))
+	}
+
+	cmd = append(cmd, bsonx.Elem{"compression", bsonx.Array(array)})
+
+	rdr, err := cmd.MarshalBSON()
+	if err != nil {
+		return nil, err
+	}
+	query := wiremessage.Query{
+		MsgHeader:          wiremessage.Header{RequestID: wiremessage.NextRequestID()},
+		FullCollectionName: "admin.$cmd",
+		Flags:              wiremessage.SlaveOK,
+		NumberToReturn:     -1,
+		Query:              rdr,
+	}
+	return query, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (im *IsMaster) Decode(wm wiremessage.WireMessage) *IsMaster {
+	reply, ok := wm.(wiremessage.Reply)
+	if !ok {
+		im.err = fmt.Errorf("unsupported response wiremessage type %T", wm)
+		return im
+	}
+	rdr, err := decodeCommandOpReply(reply)
+	if err != nil {
+		im.err = err
+		return im
+	}
+	err = bson.Unmarshal(rdr, &im.res)
+	if err != nil {
+		im.err = err
+		return im
+	}
+
+	// Reconstructs the $clusterTime doc after decode
+	if im.res.ClusterTime != nil {
+		im.res.ClusterTime = bsoncore.BuildDocument(nil, bsoncore.AppendDocumentElement(nil, "$clusterTime", im.res.ClusterTime))
+	}
+	return im
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (im *IsMaster) Result() (result.IsMaster, error) {
+	if im.err != nil {
+		return result.IsMaster{}, im.err
+	}
+
+	return im.res, nil
+}
+
+// Err returns the error set on this command.
+func (im *IsMaster) Err() error { return im.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (im *IsMaster) RoundTrip(ctx context.Context, rw wiremessage.ReadWriter) (result.IsMaster, error) {
+	wm, err := im.Encode()
+	if err != nil {
+		return result.IsMaster{}, err
+	}
+
+	err = rw.WriteWireMessage(ctx, wm)
+	if err != nil {
+		return result.IsMaster{}, err
+	}
+	wm, err = rw.ReadWireMessage(ctx)
+	if err != nil {
+		return result.IsMaster{}, err
+	}
+	return im.Decode(wm).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/kill_cursors.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/kill_cursors.go
new file mode 100644
index 0000000..37b1f89
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/kill_cursors.go
@@ -0,0 +1,103 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// KillCursors represents the killCursors command.
+//
+// The killCursors command kills a set of cursors.
+type KillCursors struct {
+	Clock *session.ClusterClock
+	NS    Namespace
+	IDs   []int64
+
+	result result.KillCursors
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (kc *KillCursors) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	encoded, err := kc.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+	return encoded.Encode(desc)
+}
+
+func (kc *KillCursors) encode(desc description.SelectedServer) (*Read, error) {
+	idVals := make([]bsonx.Val, 0, len(kc.IDs))
+	for _, id := range kc.IDs {
+		idVals = append(idVals, bsonx.Int64(id))
+	}
+	cmd := bsonx.Doc{
+		{"killCursors", bsonx.String(kc.NS.Collection)},
+		{"cursors", bsonx.Array(idVals)},
+	}
+
+	return &Read{
+		Clock:   kc.Clock,
+		DB:      kc.NS.DB,
+		Command: cmd,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (kc *KillCursors) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *KillCursors {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		kc.err = err
+		return kc
+	}
+	return kc.decode(desc, rdr)
+}
+
+func (kc *KillCursors) decode(desc description.SelectedServer, rdr bson.Raw) *KillCursors {
+	err := bson.Unmarshal(rdr, &kc.result)
+	if err != nil {
+		kc.err = err
+		return kc
+	}
+	return kc
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (kc *KillCursors) Result() (result.KillCursors, error) {
+	if kc.err != nil {
+		return result.KillCursors{}, kc.err
+	}
+
+	return kc.result, nil
+}
+
+// Err returns the error set on this command.
+func (kc *KillCursors) Err() error { return kc.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (kc *KillCursors) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.KillCursors, error) {
+	cmd, err := kc.encode(desc)
+	if err != nil {
+		return result.KillCursors{}, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.KillCursors{}, err
+	}
+
+	return kc.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_collections.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_collections.go
new file mode 100644
index 0000000..0c3e76e
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_collections.go
@@ -0,0 +1,102 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// ListCollections represents the listCollections command.
+//
+// The listCollections command lists the collections in a database.
+type ListCollections struct {
+	Clock      *session.ClusterClock
+	DB         string
+	Filter     bsonx.Doc
+	CursorOpts []bsonx.Elem
+	Opts       []bsonx.Elem
+	ReadPref   *readpref.ReadPref
+	Session    *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (lc *ListCollections) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	encoded, err := lc.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+	return encoded.Encode(desc)
+}
+
+func (lc *ListCollections) encode(desc description.SelectedServer) (*Read, error) {
+	cmd := bsonx.Doc{{"listCollections", bsonx.Int32(1)}}
+
+	if lc.Filter != nil {
+		cmd = append(cmd, bsonx.Elem{"filter", bsonx.Document(lc.Filter)})
+	}
+	cmd = append(cmd, lc.Opts...)
+
+	return &Read{
+		Clock:    lc.Clock,
+		DB:       lc.DB,
+		Command:  cmd,
+		ReadPref: lc.ReadPref,
+		Session:  lc.Session,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decolcng
+// are deferred until either the Result or Err methods are called.
+func (lc *ListCollections) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *ListCollections {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		lc.err = err
+		return lc
+	}
+	return lc.decode(desc, rdr)
+}
+
+func (lc *ListCollections) decode(desc description.SelectedServer, rdr bson.Raw) *ListCollections {
+	lc.result = rdr
+	return lc
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (lc *ListCollections) Result() (bson.Raw, error) {
+	if lc.err != nil {
+		return nil, lc.err
+	}
+	return lc.result, nil
+}
+
+// Err returns the error set on this command.
+func (lc *ListCollections) Err() error { return lc.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (lc *ListCollections) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	cmd, err := lc.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return nil, err
+	}
+
+	return lc.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_databases.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_databases.go
new file mode 100644
index 0000000..d4fd843
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_databases.go
@@ -0,0 +1,98 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// ListDatabases represents the listDatabases command.
+//
+// The listDatabases command lists the databases in a MongoDB deployment.
+type ListDatabases struct {
+	Clock   *session.ClusterClock
+	Filter  bsonx.Doc
+	Opts    []bsonx.Elem
+	Session *session.Client
+
+	result result.ListDatabases
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (ld *ListDatabases) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	encoded, err := ld.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+	return encoded.Encode(desc)
+}
+
+func (ld *ListDatabases) encode(desc description.SelectedServer) (*Read, error) {
+	cmd := bsonx.Doc{{"listDatabases", bsonx.Int32(1)}}
+
+	if ld.Filter != nil {
+		cmd = append(cmd, bsonx.Elem{"filter", bsonx.Document(ld.Filter)})
+	}
+	cmd = append(cmd, ld.Opts...)
+
+	return &Read{
+		Clock:   ld.Clock,
+		DB:      "admin",
+		Command: cmd,
+		Session: ld.Session,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (ld *ListDatabases) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *ListDatabases {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		ld.err = err
+		return ld
+	}
+	return ld.decode(desc, rdr)
+}
+
+func (ld *ListDatabases) decode(desc description.SelectedServer, rdr bson.Raw) *ListDatabases {
+	ld.err = bson.Unmarshal(rdr, &ld.result)
+	return ld
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (ld *ListDatabases) Result() (result.ListDatabases, error) {
+	if ld.err != nil {
+		return result.ListDatabases{}, ld.err
+	}
+	return ld.result, nil
+}
+
+// Err returns the error set on this command.
+func (ld *ListDatabases) Err() error { return ld.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (ld *ListDatabases) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.ListDatabases, error) {
+	cmd, err := ld.encode(desc)
+	if err != nil {
+		return result.ListDatabases{}, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.ListDatabases{}, err
+	}
+
+	return ld.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_indexes.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_indexes.go
new file mode 100644
index 0000000..48730ed
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/list_indexes.go
@@ -0,0 +1,106 @@
+// 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 command
+
+import (
+	"context"
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// ErrEmptyCursor is a signaling error when a cursor for list indexes is empty.
+var ErrEmptyCursor = errors.New("empty cursor")
+
+// ListIndexes represents the listIndexes command.
+//
+// The listIndexes command lists the indexes for a namespace.
+type ListIndexes struct {
+	Clock      *session.ClusterClock
+	NS         Namespace
+	CursorOpts []bsonx.Elem
+	Opts       []bsonx.Elem
+	Session    *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (li *ListIndexes) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	encoded, err := li.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+	return encoded.Encode(desc)
+}
+
+func (li *ListIndexes) encode(desc description.SelectedServer) (*Read, error) {
+	cmd := bsonx.Doc{{"listIndexes", bsonx.String(li.NS.Collection)}}
+	cmd = append(cmd, li.Opts...)
+
+	return &Read{
+		Clock:   li.Clock,
+		DB:      li.NS.DB,
+		Command: cmd,
+		Session: li.Session,
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoling
+// are deferred until either the Result or Err methods are called.
+func (li *ListIndexes) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *ListIndexes {
+	rdr, err := (&Read{}).Decode(desc, wm).Result()
+	if err != nil {
+		if IsNotFound(err) {
+			li.err = ErrEmptyCursor
+			return li
+		}
+		li.err = err
+		return li
+	}
+
+	return li.decode(desc, rdr)
+}
+
+func (li *ListIndexes) decode(desc description.SelectedServer, rdr bson.Raw) *ListIndexes {
+	li.result = rdr
+	return li
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (li *ListIndexes) Result() (bson.Raw, error) {
+	if li.err != nil {
+		return nil, li.err
+	}
+	return li.result, nil
+}
+
+// Err returns the error set on this command.
+func (li *ListIndexes) Err() error { return li.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (li *ListIndexes) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	cmd, err := li.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		if IsNotFound(err) {
+			return nil, ErrEmptyCursor
+		}
+		return nil, err
+	}
+
+	return li.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/namespace.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/namespace.go
new file mode 100644
index 0000000..2a4f413
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/namespace.go
@@ -0,0 +1,79 @@
+// 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 command
+
+import (
+	"errors"
+	"strings"
+)
+
+// Namespace encapsulates a database and collection name, which together
+// uniquely identifies a collection within a MongoDB cluster.
+type Namespace struct {
+	DB         string
+	Collection string
+}
+
+// NewNamespace returns a new Namespace for the
+// given database and collection.
+func NewNamespace(db, collection string) Namespace { return Namespace{DB: db, Collection: collection} }
+
+// ParseNamespace parses a namespace string into a Namespace.
+//
+// The namespace string must contain at least one ".", the first of which is the separator
+// between the database and collection names.  If not, the default (invalid) Namespace is returned.
+func ParseNamespace(name string) Namespace {
+	index := strings.Index(name, ".")
+	if index == -1 {
+		return Namespace{}
+	}
+
+	return Namespace{
+		DB:         name[:index],
+		Collection: name[index+1:],
+	}
+}
+
+// FullName returns the full namespace string, which is the result of joining the database
+// name and the collection name with a "." character.
+func (ns *Namespace) FullName() string {
+	return strings.Join([]string{ns.DB, ns.Collection}, ".")
+}
+
+// Validate validates the namespace.
+func (ns *Namespace) Validate() error {
+	if err := ns.validateDB(); err != nil {
+		return err
+	}
+
+	return ns.validateCollection()
+}
+
+// validateDB ensures the database name is not an empty string, contain a ".",
+// or contain a " ".
+func (ns *Namespace) validateDB() error {
+	if ns.DB == "" {
+		return errors.New("database name cannot be empty")
+	}
+	if strings.Contains(ns.DB, " ") {
+		return errors.New("database name cannot contain ' '")
+	}
+	if strings.Contains(ns.DB, ".") {
+		return errors.New("database name cannot contain '.'")
+	}
+
+	return nil
+}
+
+// validateCollection ensures the collection name is not an empty string.
+func (ns *Namespace) validateCollection() error {
+	if ns.Collection == "" {
+		return errors.New("collection name cannot be empty")
+	}
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/opmsg.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/opmsg.go
new file mode 100644
index 0000000..c2d5952
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/opmsg.go
@@ -0,0 +1,57 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package command
+
+import (
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+func decodeCommandOpMsg(msg wiremessage.Msg) (bson.Raw, error) {
+	var mainDoc bsonx.Doc
+
+	for _, section := range msg.Sections {
+		switch converted := section.(type) {
+		case wiremessage.SectionBody:
+			err := mainDoc.UnmarshalBSON(converted.Document)
+			if err != nil {
+				return nil, err
+			}
+		case wiremessage.SectionDocumentSequence:
+			arr := bsonx.Arr{}
+			for _, doc := range converted.Documents {
+				newDoc := bsonx.Doc{}
+				err := newDoc.UnmarshalBSON(doc)
+				if err != nil {
+					return nil, err
+				}
+
+				arr = append(arr, bsonx.Document(newDoc))
+			}
+
+			mainDoc = append(mainDoc, bsonx.Elem{converted.Identifier, bsonx.Array(arr)})
+		}
+	}
+
+	byteArray, err := mainDoc.MarshalBSON()
+	if err != nil {
+		return nil, err
+	}
+
+	rdr := bson.Raw(byteArray)
+	err = rdr.Validate()
+	if err != nil {
+		return nil, NewCommandResponseError("malformed OP_MSG: invalid document", err)
+	}
+
+	err = extractError(rdr)
+	if err != nil {
+		return nil, err
+	}
+	return rdr, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/opreply.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/opreply.go
new file mode 100644
index 0000000..68c15ed
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/opreply.go
@@ -0,0 +1,43 @@
+// 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 command
+
+import (
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// decodeCommandOpReply handles decoding the OP_REPLY response to an OP_QUERY
+// command.
+func decodeCommandOpReply(reply wiremessage.Reply) (bson.Raw, error) {
+	if reply.NumberReturned == 0 {
+		return nil, ErrNoDocCommandResponse
+	}
+	if reply.NumberReturned > 1 {
+		return nil, ErrMultiDocCommandResponse
+	}
+	if len(reply.Documents) != 1 {
+		return nil, NewCommandResponseError("malformed OP_REPLY: NumberReturned does not match number of documents returned", nil)
+	}
+	rdr := reply.Documents[0]
+	err := rdr.Validate()
+	if err != nil {
+		return nil, NewCommandResponseError("malformed OP_REPLY: invalid document", err)
+	}
+	if reply.ResponseFlags&wiremessage.QueryFailure == wiremessage.QueryFailure {
+		return nil, QueryFailureError{
+			Message:  "command failure",
+			Response: reply.Documents[0],
+		}
+	}
+
+	err = extractError(rdr)
+	if err != nil {
+		return nil, err
+	}
+	return rdr, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/read.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/read.go
new file mode 100644
index 0000000..d7b6547
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/read.go
@@ -0,0 +1,287 @@
+// 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 command
+
+import (
+	"context"
+
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Read represents a generic database read command.
+type Read struct {
+	DB          string
+	Command     bsonx.Doc
+	ReadPref    *readpref.ReadPref
+	ReadConcern *readconcern.ReadConcern
+	Clock       *session.ClusterClock
+	Session     *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+func (r *Read) createReadPref(serverKind description.ServerKind, topologyKind description.TopologyKind, isOpQuery bool) bsonx.Doc {
+	doc := bsonx.Doc{}
+	rp := r.ReadPref
+
+	if rp == nil {
+		if topologyKind == description.Single && serverKind != description.Mongos {
+			return append(doc, bsonx.Elem{"mode", bsonx.String("primaryPreferred")})
+		}
+		return nil
+	}
+
+	switch rp.Mode() {
+	case readpref.PrimaryMode:
+		if serverKind == description.Mongos {
+			return nil
+		}
+		if topologyKind == description.Single {
+			return append(doc, bsonx.Elem{"mode", bsonx.String("primaryPreferred")})
+		}
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("primary")})
+	case readpref.PrimaryPreferredMode:
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("primaryPreferred")})
+	case readpref.SecondaryPreferredMode:
+		_, ok := r.ReadPref.MaxStaleness()
+		if serverKind == description.Mongos && isOpQuery && !ok && len(r.ReadPref.TagSets()) == 0 {
+			return nil
+		}
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("secondaryPreferred")})
+	case readpref.SecondaryMode:
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("secondary")})
+	case readpref.NearestMode:
+		doc = append(doc, bsonx.Elem{"mode", bsonx.String("nearest")})
+	}
+
+	sets := make([]bsonx.Val, 0, len(r.ReadPref.TagSets()))
+	for _, ts := range r.ReadPref.TagSets() {
+		if len(ts) == 0 {
+			continue
+		}
+		set := bsonx.Doc{}
+		for _, t := range ts {
+			set = append(set, bsonx.Elem{t.Name, bsonx.String(t.Value)})
+		}
+		sets = append(sets, bsonx.Document(set))
+	}
+	if len(sets) > 0 {
+		doc = append(doc, bsonx.Elem{"tags", bsonx.Array(sets)})
+	}
+
+	if d, ok := r.ReadPref.MaxStaleness(); ok {
+		doc = append(doc, bsonx.Elem{"maxStalenessSeconds", bsonx.Int32(int32(d.Seconds()))})
+	}
+
+	return doc
+}
+
+// addReadPref will add a read preference to the query document.
+//
+// NOTE: This method must always return either a valid bson.Reader or an error.
+func (r *Read) addReadPref(rp *readpref.ReadPref, serverKind description.ServerKind, topologyKind description.TopologyKind, query bson.Raw) (bson.Raw, error) {
+	doc := r.createReadPref(serverKind, topologyKind, true)
+	if doc == nil {
+		return query, nil
+	}
+
+	qdoc := bsonx.Doc{}
+	err := bson.Unmarshal(query, &qdoc)
+	if err != nil {
+		return query, err
+	}
+	return bsonx.Doc{
+		{"$query", bsonx.Document(qdoc)},
+		{"$readPreference", bsonx.Document(doc)},
+	}.MarshalBSON()
+}
+
+// Encode r as OP_MSG
+func (r *Read) encodeOpMsg(desc description.SelectedServer, cmd bsonx.Doc) (wiremessage.WireMessage, error) {
+	msg := wiremessage.Msg{
+		MsgHeader: wiremessage.Header{RequestID: wiremessage.NextRequestID()},
+		Sections:  make([]wiremessage.Section, 0),
+	}
+
+	readPrefDoc := r.createReadPref(desc.Server.Kind, desc.Kind, false)
+	fullDocRdr, err := opmsgAddGlobals(cmd, r.DB, readPrefDoc)
+	if err != nil {
+		return nil, err
+	}
+
+	// type 0 doc
+	msg.Sections = append(msg.Sections, wiremessage.SectionBody{
+		PayloadType: wiremessage.SingleDocument,
+		Document:    fullDocRdr,
+	})
+
+	// no flags to add
+
+	return msg, nil
+}
+
+func (r *Read) slaveOK(desc description.SelectedServer) wiremessage.QueryFlag {
+	if desc.Kind == description.Single && desc.Server.Kind != description.Mongos {
+		return wiremessage.SlaveOK
+	}
+
+	if r.ReadPref == nil {
+		// assume primary
+		return 0
+	}
+
+	if r.ReadPref.Mode() != readpref.PrimaryMode {
+		return wiremessage.SlaveOK
+	}
+
+	return 0
+}
+
+// Encode c as OP_QUERY
+func (r *Read) encodeOpQuery(desc description.SelectedServer, cmd bsonx.Doc) (wiremessage.WireMessage, error) {
+	rdr, err := marshalCommand(cmd)
+	if err != nil {
+		return nil, err
+	}
+
+	if desc.Server.Kind == description.Mongos {
+		rdr, err = r.addReadPref(r.ReadPref, desc.Server.Kind, desc.Kind, rdr)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	query := wiremessage.Query{
+		MsgHeader:          wiremessage.Header{RequestID: wiremessage.NextRequestID()},
+		FullCollectionName: r.DB + ".$cmd",
+		Flags:              r.slaveOK(desc),
+		NumberToReturn:     -1,
+		Query:              rdr,
+	}
+
+	return query, nil
+}
+
+func (r *Read) decodeOpMsg(wm wiremessage.WireMessage) {
+	msg, ok := wm.(wiremessage.Msg)
+	if !ok {
+		r.err = fmt.Errorf("unsupported response wiremessage type %T", wm)
+		return
+	}
+
+	r.result, r.err = decodeCommandOpMsg(msg)
+}
+
+func (r *Read) decodeOpReply(wm wiremessage.WireMessage) {
+	reply, ok := wm.(wiremessage.Reply)
+	if !ok {
+		r.err = fmt.Errorf("unsupported response wiremessage type %T", wm)
+		return
+	}
+	r.result, r.err = decodeCommandOpReply(reply)
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (r *Read) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd := r.Command.Copy()
+	cmd, err := addReadConcern(cmd, desc, r.ReadConcern, r.Session)
+	if err != nil {
+		return nil, err
+	}
+
+	cmd, err = addSessionFields(cmd, desc, r.Session)
+	if err != nil {
+		return nil, err
+	}
+
+	cmd = addClusterTime(cmd, desc, r.Session, r.Clock)
+
+	if desc.WireVersion == nil || desc.WireVersion.Max < wiremessage.OpmsgWireVersion {
+		return r.encodeOpQuery(desc, cmd)
+	}
+
+	return r.encodeOpMsg(desc, cmd)
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (r *Read) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Read {
+	switch wm.(type) {
+	case wiremessage.Reply:
+		r.decodeOpReply(wm)
+	default:
+		r.decodeOpMsg(wm)
+	}
+
+	if r.err != nil {
+		// decode functions set error if an invalid response document was returned or if the OK flag in the response was 0
+		// if the OK flag was 0, a type Error is returned. otherwise, a special type is returned
+		if _, ok := r.err.(Error); !ok {
+			return r // for missing/invalid response docs, don't update cluster times
+		}
+	}
+
+	_ = updateClusterTimes(r.Session, r.Clock, r.result)
+	_ = updateOperationTime(r.Session, r.result)
+	return r
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (r *Read) Result() (bson.Raw, error) {
+	if r.err != nil {
+		return nil, r.err
+	}
+
+	return r.result, nil
+}
+
+// Err returns the error set on this command.
+func (r *Read) Err() error {
+	return r.err
+}
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (r *Read) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	wm, err := r.Encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	err = rw.WriteWireMessage(ctx, wm)
+	if err != nil {
+		if _, ok := err.(Error); ok {
+			return nil, err
+		}
+		// Connection errors are transient
+		return nil, Error{Message: err.Error(), Labels: []string{TransientTransactionError, NetworkError}}
+	}
+	wm, err = rw.ReadWireMessage(ctx)
+	if err != nil {
+		if _, ok := err.(Error); ok {
+			return nil, err
+		}
+		// Connection errors are transient
+		return nil, Error{Message: err.Error(), Labels: []string{TransientTransactionError, NetworkError}}
+	}
+
+	if r.Session != nil {
+		err = r.Session.UpdateUseTime()
+		if err != nil {
+			return nil, err
+		}
+	}
+	return r.Decode(desc, wm).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/start_session.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/start_session.go
new file mode 100644
index 0000000..69758b8
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/start_session.go
@@ -0,0 +1,82 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// StartSession represents a startSession command
+type StartSession struct {
+	Clock  *session.ClusterClock
+	result result.StartSession
+	err    error
+}
+
+// Encode will encode this command into a wiremessage for the given server description.
+func (ss *StartSession) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd := ss.encode(desc)
+	return cmd.Encode(desc)
+}
+
+func (ss *StartSession) encode(desc description.SelectedServer) *Write {
+	cmd := bsonx.Doc{{"startSession", bsonx.Int32(1)}}
+	return &Write{
+		Clock:   ss.Clock,
+		DB:      "admin",
+		Command: cmd,
+	}
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding are deferred until
+// either the Result or Err methods are called.
+func (ss *StartSession) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *StartSession {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		ss.err = err
+		return ss
+	}
+
+	return ss.decode(desc, rdr)
+}
+
+func (ss *StartSession) decode(desc description.SelectedServer, rdr bson.Raw) *StartSession {
+	ss.err = bson.Unmarshal(rdr, &ss.result)
+	return ss
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (ss *StartSession) Result() (result.StartSession, error) {
+	if ss.err != nil {
+		return result.StartSession{}, ss.err
+	}
+
+	return ss.result, nil
+}
+
+// Err returns the error set on this command
+func (ss *StartSession) Err() error {
+	return ss.err
+}
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter
+func (ss *StartSession) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (result.StartSession, error) {
+	cmd := ss.encode(desc)
+	rdr, err := cmd.RoundTrip(ctx, desc, rw)
+	if err != nil {
+		return result.StartSession{}, err
+	}
+
+	return ss.decode(desc, rdr).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/update.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/update.go
new file mode 100644
index 0000000..29470ae
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/update.go
@@ -0,0 +1,161 @@
+// 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 command
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Update represents the update command.
+//
+// The update command updates a set of documents with the database.
+type Update struct {
+	ContinueOnError bool
+	Clock           *session.ClusterClock
+	NS              Namespace
+	Docs            []bsonx.Doc
+	Opts            []bsonx.Elem
+	WriteConcern    *writeconcern.WriteConcern
+	Session         *session.Client
+
+	batches []*WriteBatch
+	result  result.Update
+	err     error
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (u *Update) Encode(desc description.SelectedServer) ([]wiremessage.WireMessage, error) {
+	err := u.encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	return batchesToWireMessage(u.batches, desc)
+}
+
+func (u *Update) encode(desc description.SelectedServer) error {
+	batches, err := splitBatches(u.Docs, int(desc.MaxBatchCount), int(desc.MaxDocumentSize))
+	if err != nil {
+		return err
+	}
+
+	for _, docs := range batches {
+		cmd, err := u.encodeBatch(docs, desc)
+		if err != nil {
+			return err
+		}
+
+		u.batches = append(u.batches, cmd)
+	}
+
+	return nil
+}
+
+func (u *Update) encodeBatch(docs []bsonx.Doc, desc description.SelectedServer) (*WriteBatch, error) {
+	copyDocs := make([]bsonx.Doc, 0, len(docs)) // copy of all the documents
+	for _, doc := range docs {
+		newDoc := doc.Copy()
+		copyDocs = append(copyDocs, newDoc)
+	}
+
+	var options []bsonx.Elem
+	for _, opt := range u.Opts {
+		switch opt.Key {
+		case "upsert", "collation", "arrayFilters":
+			// options that are encoded on each individual document
+			for idx := range copyDocs {
+				copyDocs[idx] = append(copyDocs[idx], opt)
+			}
+		default:
+			options = append(options, opt)
+		}
+	}
+
+	command, err := encodeBatch(copyDocs, options, UpdateCommand, u.NS.Collection)
+	if err != nil {
+		return nil, err
+	}
+
+	return &WriteBatch{
+		&Write{
+			Clock:        u.Clock,
+			DB:           u.NS.DB,
+			Command:      command,
+			WriteConcern: u.WriteConcern,
+			Session:      u.Session,
+		},
+		len(docs),
+	}, nil
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (u *Update) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Update {
+	rdr, err := (&Write{}).Decode(desc, wm).Result()
+	if err != nil {
+		u.err = err
+		return u
+	}
+	return u.decode(desc, rdr)
+}
+
+func (u *Update) decode(desc description.SelectedServer, rdr bson.Raw) *Update {
+	u.err = bson.Unmarshal(rdr, &u.result)
+	return u
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (u *Update) Result() (result.Update, error) {
+	if u.err != nil {
+		return result.Update{}, u.err
+	}
+	return u.result, nil
+}
+
+// Err returns the error set on this command.
+func (u *Update) Err() error { return u.err }
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriter.
+func (u *Update) RoundTrip(
+	ctx context.Context,
+	desc description.SelectedServer,
+	rw wiremessage.ReadWriter,
+) (result.Update, error) {
+	if u.batches == nil {
+		err := u.encode(desc)
+		if err != nil {
+			return result.Update{}, err
+		}
+	}
+
+	r, batches, err := roundTripBatches(
+		ctx, desc, rw,
+		u.batches,
+		u.ContinueOnError,
+		u.Session,
+		UpdateCommand,
+	)
+
+	// if there are leftover batches, save them for retry
+	if batches != nil {
+		u.batches = batches
+	}
+
+	if err != nil {
+		return result.Update{}, err
+	}
+
+	return r.(result.Update), nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/command/write.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/write.go
new file mode 100644
index 0000000..3787fae
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/command/write.go
@@ -0,0 +1,245 @@
+// 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 command
+
+import (
+	"context"
+	"fmt"
+
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Write represents a generic write database command.
+// This can be used to send arbitrary write commands to the database.
+type Write struct {
+	DB           string
+	Command      bsonx.Doc
+	WriteConcern *writeconcern.WriteConcern
+	Clock        *session.ClusterClock
+	Session      *session.Client
+
+	result bson.Raw
+	err    error
+}
+
+// Encode c as OP_MSG
+func (w *Write) encodeOpMsg(desc description.SelectedServer, cmd bsonx.Doc) (wiremessage.WireMessage, error) {
+	var arr bsonx.Arr
+	var identifier string
+
+	cmd, arr, identifier = opmsgRemoveArray(cmd)
+
+	msg := wiremessage.Msg{
+		MsgHeader: wiremessage.Header{RequestID: wiremessage.NextRequestID()},
+		Sections:  make([]wiremessage.Section, 0),
+	}
+
+	fullDocRdr, err := opmsgAddGlobals(cmd, w.DB, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	// type 0 doc
+	msg.Sections = append(msg.Sections, wiremessage.SectionBody{
+		PayloadType: wiremessage.SingleDocument,
+		Document:    fullDocRdr,
+	})
+
+	// type 1 doc
+	if identifier != "" {
+		docSequence, err := opmsgCreateDocSequence(arr, identifier)
+		if err != nil {
+			return nil, err
+		}
+
+		msg.Sections = append(msg.Sections, docSequence)
+	}
+
+	// flags
+	if !writeconcern.AckWrite(w.WriteConcern) {
+		msg.FlagBits |= wiremessage.MoreToCome
+	}
+
+	return msg, nil
+}
+
+// Encode w as OP_QUERY
+func (w *Write) encodeOpQuery(desc description.SelectedServer, cmd bsonx.Doc) (wiremessage.WireMessage, error) {
+	rdr, err := marshalCommand(cmd)
+	if err != nil {
+		return nil, err
+	}
+
+	query := wiremessage.Query{
+		MsgHeader:          wiremessage.Header{RequestID: wiremessage.NextRequestID()},
+		FullCollectionName: w.DB + ".$cmd",
+		Flags:              w.slaveOK(desc),
+		NumberToReturn:     -1,
+		Query:              rdr,
+	}
+
+	return query, nil
+}
+
+func (w *Write) slaveOK(desc description.SelectedServer) wiremessage.QueryFlag {
+	if desc.Kind == description.Single && desc.Server.Kind != description.Mongos {
+		return wiremessage.SlaveOK
+	}
+
+	return 0
+}
+
+func (w *Write) decodeOpReply(wm wiremessage.WireMessage) {
+	reply, ok := wm.(wiremessage.Reply)
+	if !ok {
+		w.err = fmt.Errorf("unsupported response wiremessage type %T", wm)
+		return
+	}
+	w.result, w.err = decodeCommandOpReply(reply)
+}
+
+func (w *Write) decodeOpMsg(wm wiremessage.WireMessage) {
+	msg, ok := wm.(wiremessage.Msg)
+	if !ok {
+		w.err = fmt.Errorf("unsupported response wiremessage type %T", wm)
+		return
+	}
+
+	w.result, w.err = decodeCommandOpMsg(msg)
+}
+
+// Encode will encode this command into a wire message for the given server description.
+func (w *Write) Encode(desc description.SelectedServer) (wiremessage.WireMessage, error) {
+	cmd := w.Command.Copy()
+	var err error
+	if w.Session != nil && w.Session.TransactionStarting() {
+		// Starting transactions have a read concern, even in writes.
+		cmd, err = addReadConcern(cmd, desc, nil, w.Session)
+		if err != nil {
+			return nil, err
+		}
+	}
+	cmd, err = addWriteConcern(cmd, w.WriteConcern)
+	if err != nil {
+		return nil, err
+	}
+
+	if !writeconcern.AckWrite(w.WriteConcern) {
+		// unack write with explicit session --> raise an error
+		// unack write with implicit session --> do not send session ID (implicit session shouldn't have been created
+		// in the first place)
+
+		if w.Session != nil && w.Session.SessionType == session.Explicit {
+			return nil, errors.New("explicit sessions cannot be used with unacknowledged writes")
+		}
+	} else {
+		// only encode session ID for acknowledged writes
+		cmd, err = addSessionFields(cmd, desc, w.Session)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if w.Session != nil && w.Session.RetryWrite {
+		cmd = append(cmd, bsonx.Elem{"txnNumber", bsonx.Int64(w.Session.TxnNumber)})
+	}
+
+	cmd = addClusterTime(cmd, desc, w.Session, w.Clock)
+
+	if desc.WireVersion == nil || desc.WireVersion.Max < wiremessage.OpmsgWireVersion {
+		return w.encodeOpQuery(desc, cmd)
+	}
+
+	return w.encodeOpMsg(desc, cmd)
+}
+
+// Decode will decode the wire message using the provided server description. Errors during decoding
+// are deferred until either the Result or Err methods are called.
+func (w *Write) Decode(desc description.SelectedServer, wm wiremessage.WireMessage) *Write {
+	switch wm.(type) {
+	case wiremessage.Reply:
+		w.decodeOpReply(wm)
+	default:
+		w.decodeOpMsg(wm)
+	}
+
+	if w.err != nil {
+		if _, ok := w.err.(Error); !ok {
+			return w
+		}
+	}
+
+	_ = updateClusterTimes(w.Session, w.Clock, w.result)
+
+	if writeconcern.AckWrite(w.WriteConcern) {
+		// don't update session operation time for unacknowledged write
+		_ = updateOperationTime(w.Session, w.result)
+	}
+	return w
+}
+
+// Result returns the result of a decoded wire message and server description.
+func (w *Write) Result() (bson.Raw, error) {
+	if w.err != nil {
+		return nil, w.err
+	}
+
+	return w.result, nil
+}
+
+// Err returns the error set on this command.
+func (w *Write) Err() error {
+	return w.err
+}
+
+// RoundTrip handles the execution of this command using the provided wiremessage.ReadWriteCloser.
+func (w *Write) RoundTrip(ctx context.Context, desc description.SelectedServer, rw wiremessage.ReadWriter) (bson.Raw, error) {
+	wm, err := w.Encode(desc)
+	if err != nil {
+		return nil, err
+	}
+
+	err = rw.WriteWireMessage(ctx, wm)
+	if err != nil {
+		if _, ok := err.(Error); ok {
+			return nil, err
+		}
+		// Connection errors are transient
+		return nil, Error{Message: err.Error(), Labels: []string{TransientTransactionError, NetworkError}}
+	}
+
+	if msg, ok := wm.(wiremessage.Msg); ok {
+		// don't expect response if using OP_MSG for an unacknowledged write
+		if msg.FlagBits&wiremessage.MoreToCome > 0 {
+			return nil, ErrUnacknowledgedWrite
+		}
+	}
+
+	wm, err = rw.ReadWireMessage(ctx)
+	if err != nil {
+		if _, ok := err.(Error); ok {
+			return nil, err
+		}
+		// Connection errors are transient
+		return nil, Error{Message: err.Error(), Labels: []string{TransientTransactionError, NetworkError}}
+	}
+
+	if w.Session != nil {
+		err = w.Session.UpdateUseTime()
+		if err != nil {
+			return nil, err
+		}
+	}
+	return w.Decode(desc, wm).Result()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/compressor/compression.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/compressor/compression.go
new file mode 100644
index 0000000..5ec2ea0
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/compressor/compression.go
@@ -0,0 +1,157 @@
+// 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 compressor
+
+import (
+	"bytes"
+	"compress/zlib"
+
+	"io"
+
+	"github.com/golang/snappy"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Compressor is the interface implemented by types that can compress and decompress wire messages. This is used
+// when sending and receiving messages to and from the server.
+type Compressor interface {
+	CompressBytes(src, dest []byte) ([]byte, error)
+	UncompressBytes(src, dest []byte) ([]byte, error)
+	CompressorID() wiremessage.CompressorID
+	Name() string
+}
+
+type writer struct {
+	buf []byte
+}
+
+// Write appends bytes to the writer
+func (w *writer) Write(p []byte) (n int, err error) {
+	index := len(w.buf)
+	if len(p) > cap(w.buf)-index {
+		buf := make([]byte, 2*cap(w.buf)+len(p))
+		copy(buf, w.buf)
+		w.buf = buf
+	}
+
+	w.buf = w.buf[:index+len(p)]
+	copy(w.buf[index:], p)
+	return len(p), nil
+}
+
+// SnappyCompressor uses the snappy method to compress data
+type SnappyCompressor struct {
+}
+
+// ZlibCompressor uses the zlib method to compress data
+type ZlibCompressor struct {
+	level      int
+	zlibWriter *zlib.Writer
+}
+
+// CompressBytes uses snappy to compress a slice of bytes.
+func (s *SnappyCompressor) CompressBytes(src, dest []byte) ([]byte, error) {
+	dest = dest[:0]
+	dest = snappy.Encode(dest, src)
+	return dest, nil
+}
+
+// UncompressBytes uses snappy to uncompress a slice of bytes.
+func (s *SnappyCompressor) UncompressBytes(src, dest []byte) ([]byte, error) {
+	var err error
+	dest, err = snappy.Decode(dest, src)
+	if err != nil {
+		return dest, err
+	}
+
+	return dest, nil
+}
+
+// CompressorID returns the ID for the snappy compressor.
+func (s *SnappyCompressor) CompressorID() wiremessage.CompressorID {
+	return wiremessage.CompressorSnappy
+}
+
+// Name returns the string name for the snappy compressor.
+func (s *SnappyCompressor) Name() string {
+	return "snappy"
+}
+
+// CompressBytes uses zlib to compress a slice of bytes.
+func (z *ZlibCompressor) CompressBytes(src, dest []byte) ([]byte, error) {
+	dest = dest[:0]
+	z.zlibWriter.Reset(&writer{
+		buf: dest,
+	})
+
+	_, err := z.zlibWriter.Write(src)
+	if err != nil {
+		_ = z.zlibWriter.Close()
+		return dest, err
+	}
+
+	err = z.zlibWriter.Close()
+	if err != nil {
+		return dest, err
+	}
+	return dest, nil
+}
+
+// UncompressBytes uses zlib to uncompress a slice of bytes. It assumes dest is empty and is the exact size that it
+// needs to be.
+func (z *ZlibCompressor) UncompressBytes(src, dest []byte) ([]byte, error) {
+	reader := bytes.NewReader(src)
+	zlibReader, err := zlib.NewReader(reader)
+
+	if err != nil {
+		return dest, err
+	}
+	defer func() {
+		_ = zlibReader.Close()
+	}()
+
+	_, err = io.ReadFull(zlibReader, dest)
+	if err != nil {
+		return dest, err
+	}
+
+	return dest, nil
+}
+
+// CompressorID returns the ID for the zlib compressor.
+func (z *ZlibCompressor) CompressorID() wiremessage.CompressorID {
+	return wiremessage.CompressorZLib
+}
+
+// Name returns the name for the zlib compressor.
+func (z *ZlibCompressor) Name() string {
+	return "zlib"
+}
+
+// CreateSnappy creates a snappy compressor
+func CreateSnappy() Compressor {
+	return &SnappyCompressor{}
+}
+
+// CreateZlib creates a zlib compressor
+func CreateZlib(level int) (Compressor, error) {
+	if level < 0 {
+		level = wiremessage.DefaultZlibLevel
+	}
+
+	var compressBuf bytes.Buffer
+	zlibWriter, err := zlib.NewWriterLevel(&compressBuf, level)
+
+	if err != nil {
+		return &ZlibCompressor{}, err
+	}
+
+	return &ZlibCompressor{
+		level:      level,
+		zlibWriter: zlibWriter,
+	}, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/addr.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/addr.go
new file mode 100644
index 0000000..4d8976d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/addr.go
@@ -0,0 +1,21 @@
+// 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 connection
+
+const defaultPort = "27017"
+
+// Addr is a network address. It can be either an IP address or a DNS name.
+type Addr string
+
+// Network is the network protcol for this address. In most cases this will be "tcp" or "unix".
+func (Addr) Network() string { return "" }
+
+// String is the canonical version of this address, e.g. localhost:27017, 1.2.3.4:27017, example.com:27017
+func (Addr) String() string { return "" }
+
+// Canonicalize creates a canonicalized address.
+func (Addr) Canonicalize() Addr { return Addr("") }
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/command_metadata.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/command_metadata.go
new file mode 100644
index 0000000..222f6f7
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/command_metadata.go
@@ -0,0 +1,28 @@
+package connection
+
+import "time"
+
+// commandMetadata contains metadata about a command sent to the server.
+type commandMetadata struct {
+	Name               string
+	Time               time.Time
+	Legacy             bool
+	FullCollectionName string
+}
+
+// createMetadata creates metadata for a command.
+func createMetadata(name string, legacy bool, fullCollName string) *commandMetadata {
+	return &commandMetadata{
+		Name:               name,
+		Time:               time.Now(),
+		Legacy:             legacy,
+		FullCollectionName: fullCollName,
+	}
+}
+
+// TimeDifference returns the difference between now and the time a command was sent in nanoseconds.
+func (cm *commandMetadata) TimeDifference() int64 {
+	t := time.Now()
+	duration := t.Sub(cm.Time)
+	return duration.Nanoseconds()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/connection.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/connection.go
new file mode 100644
index 0000000..5e64037
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/connection.go
@@ -0,0 +1,851 @@
+// 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 connection contains the types for building and pooling connections that can speak the
+// MongoDB Wire Protocol. Since this low level library is meant to be used in the context of either
+// a driver or a server there are some extra identifiers on a connection so one can keep track of
+// what a connection is. This package purposefully hides the underlying network and abstracts the
+// writing to and reading from a connection to wireops.Op's. This package also provides types for
+// listening for and accepting Connections, as well as some types for handling connections and
+// proxying connections to another server.
+package connection
+
+import (
+	"context"
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"io"
+	"net"
+	"strings"
+	"sync/atomic"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/event"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+	"github.com/mongodb/mongo-go-driver/x/network/compressor"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+var globalClientConnectionID uint64
+var emptyDoc bson.Raw
+
+func nextClientConnectionID() uint64 {
+	return atomic.AddUint64(&globalClientConnectionID, 1)
+}
+
+// Connection is used to read and write wire protocol messages to a network.
+type Connection interface {
+	WriteWireMessage(context.Context, wiremessage.WireMessage) error
+	ReadWireMessage(context.Context) (wiremessage.WireMessage, error)
+	Close() error
+	Expired() bool
+	Alive() bool
+	ID() string
+}
+
+// Dialer is used to make network connections.
+type Dialer interface {
+	DialContext(ctx context.Context, network, address string) (net.Conn, error)
+}
+
+// DialerFunc is a type implemented by functions that can be used as a Dialer.
+type DialerFunc func(ctx context.Context, network, address string) (net.Conn, error)
+
+// DialContext implements the Dialer interface.
+func (df DialerFunc) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
+	return df(ctx, network, address)
+}
+
+// DefaultDialer is the Dialer implementation that is used by this package. Changing this
+// will also change the Dialer used for this package. This should only be changed why all
+// of the connections being made need to use a different Dialer. Most of the time, using a
+// WithDialer option is more appropriate than changing this variable.
+var DefaultDialer Dialer = &net.Dialer{}
+
+// Handshaker is the interface implemented by types that can perform a MongoDB
+// handshake over a provided ReadWriter. This is used during connection
+// initialization.
+type Handshaker interface {
+	Handshake(context.Context, address.Address, wiremessage.ReadWriter) (description.Server, error)
+}
+
+// HandshakerFunc is an adapter to allow the use of ordinary functions as
+// connection handshakers.
+type HandshakerFunc func(context.Context, address.Address, wiremessage.ReadWriter) (description.Server, error)
+
+// Handshake implements the Handshaker interface.
+func (hf HandshakerFunc) Handshake(ctx context.Context, addr address.Address, rw wiremessage.ReadWriter) (description.Server, error) {
+	return hf(ctx, addr, rw)
+}
+
+type connection struct {
+	addr        address.Address
+	id          string
+	conn        net.Conn
+	compressBuf []byte                // buffer to compress messages
+	compressor  compressor.Compressor // use for compressing messages
+	// server can compress response with any compressor supported by driver
+	compressorMap    map[wiremessage.CompressorID]compressor.Compressor
+	commandMap       map[int64]*commandMetadata // map for monitoring commands sent to server
+	dead             bool
+	idleTimeout      time.Duration
+	idleDeadline     time.Time
+	lifetimeDeadline time.Time
+	cmdMonitor       *event.CommandMonitor
+	readTimeout      time.Duration
+	uncompressBuf    []byte // buffer to uncompress messages
+	writeTimeout     time.Duration
+	readBuf          []byte
+	writeBuf         []byte
+	wireMessageBuf   []byte // buffer to store uncompressed wire message before compressing
+}
+
+// New opens a connection to a given Addr
+//
+// The server description returned is nil if there was no handshaker provided.
+func New(ctx context.Context, addr address.Address, opts ...Option) (Connection, *description.Server, error) {
+	cfg, err := newConfig(opts...)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	nc, err := cfg.dialer.DialContext(ctx, addr.Network(), addr.String())
+	if err != nil {
+		return nil, nil, err
+	}
+
+	if cfg.tlsConfig != nil {
+		tlsConfig := cfg.tlsConfig.Clone()
+		nc, err = configureTLS(ctx, nc, addr, tlsConfig)
+		if err != nil {
+			return nil, nil, err
+		}
+	}
+
+	var lifetimeDeadline time.Time
+	if cfg.lifeTimeout > 0 {
+		lifetimeDeadline = time.Now().Add(cfg.lifeTimeout)
+	}
+
+	id := fmt.Sprintf("%s[-%d]", addr, nextClientConnectionID())
+	compressorMap := make(map[wiremessage.CompressorID]compressor.Compressor)
+
+	for _, comp := range cfg.compressors {
+		compressorMap[comp.CompressorID()] = comp
+	}
+
+	c := &connection{
+		id:               id,
+		conn:             nc,
+		compressBuf:      make([]byte, 256),
+		compressorMap:    compressorMap,
+		commandMap:       make(map[int64]*commandMetadata),
+		addr:             addr,
+		idleTimeout:      cfg.idleTimeout,
+		lifetimeDeadline: lifetimeDeadline,
+		readTimeout:      cfg.readTimeout,
+		writeTimeout:     cfg.writeTimeout,
+		readBuf:          make([]byte, 256),
+		uncompressBuf:    make([]byte, 256),
+		writeBuf:         make([]byte, 0, 256),
+		wireMessageBuf:   make([]byte, 256),
+	}
+
+	c.bumpIdleDeadline()
+
+	var desc *description.Server
+	if cfg.handshaker != nil {
+		d, err := cfg.handshaker.Handshake(ctx, c.addr, c)
+		if err != nil {
+			return nil, nil, err
+		}
+
+		if len(d.Compression) > 0 {
+		clientMethodLoop:
+			for _, comp := range cfg.compressors {
+				method := comp.Name()
+
+				for _, serverMethod := range d.Compression {
+					if method != serverMethod {
+						continue
+					}
+
+					c.compressor = comp // found matching compressor
+					break clientMethodLoop
+				}
+			}
+
+		}
+
+		desc = &d
+	}
+
+	c.cmdMonitor = cfg.cmdMonitor // attach the command monitor later to avoid monitoring auth
+	return c, desc, nil
+}
+
+func configureTLS(ctx context.Context, nc net.Conn, addr address.Address, config *TLSConfig) (net.Conn, error) {
+	if !config.InsecureSkipVerify {
+		hostname := addr.String()
+		colonPos := strings.LastIndex(hostname, ":")
+		if colonPos == -1 {
+			colonPos = len(hostname)
+		}
+
+		hostname = hostname[:colonPos]
+		config.ServerName = hostname
+	}
+
+	client := tls.Client(nc, config.Config)
+
+	errChan := make(chan error, 1)
+	go func() {
+		errChan <- client.Handshake()
+	}()
+
+	select {
+	case err := <-errChan:
+		if err != nil {
+			return nil, err
+		}
+	case <-ctx.Done():
+		return nil, errors.New("server connection cancelled/timeout during TLS handshake")
+	}
+	return client, nil
+}
+
+func (c *connection) Alive() bool {
+	return !c.dead
+}
+
+func (c *connection) Expired() bool {
+	now := time.Now()
+	if !c.idleDeadline.IsZero() && now.After(c.idleDeadline) {
+		return true
+	}
+
+	if !c.lifetimeDeadline.IsZero() && now.After(c.lifetimeDeadline) {
+		return true
+	}
+
+	return c.dead
+}
+
+func canCompress(cmd string) bool {
+	if cmd == "isMaster" || cmd == "saslStart" || cmd == "saslContinue" || cmd == "getnonce" || cmd == "authenticate" ||
+		cmd == "createUser" || cmd == "updateUser" || cmd == "copydbSaslStart" || cmd == "copydbgetnonce" || cmd == "copydb" {
+		return false
+	}
+	return true
+}
+
+func (c *connection) compressMessage(wm wiremessage.WireMessage) (wiremessage.WireMessage, error) {
+	var requestID int32
+	var responseTo int32
+	var origOpcode wiremessage.OpCode
+
+	switch converted := wm.(type) {
+	case wiremessage.Query:
+		firstElem, err := converted.Query.IndexErr(0)
+		if err != nil {
+			return wiremessage.Compressed{}, err
+		}
+
+		key := firstElem.Key()
+		if !canCompress(key) {
+			return wm, nil // return original message because this command can't be compressed
+		}
+		requestID = converted.MsgHeader.RequestID
+		origOpcode = wiremessage.OpQuery
+		responseTo = converted.MsgHeader.ResponseTo
+	case wiremessage.Msg:
+		firstElem, err := converted.Sections[0].(wiremessage.SectionBody).Document.IndexErr(0)
+		if err != nil {
+			return wiremessage.Compressed{}, err
+		}
+
+		key := firstElem.Key()
+		if !canCompress(key) {
+			return wm, nil
+		}
+
+		requestID = converted.MsgHeader.RequestID
+		origOpcode = wiremessage.OpMsg
+		responseTo = converted.MsgHeader.ResponseTo
+	}
+
+	// can compress
+	c.wireMessageBuf = c.wireMessageBuf[:0] // truncate
+	var err error
+	c.wireMessageBuf, err = wm.AppendWireMessage(c.wireMessageBuf)
+	if err != nil {
+		return wiremessage.Compressed{}, err
+	}
+
+	c.wireMessageBuf = c.wireMessageBuf[16:] // strip header
+	c.compressBuf = c.compressBuf[:0]
+	compressedBytes, err := c.compressor.CompressBytes(c.wireMessageBuf, c.compressBuf)
+	if err != nil {
+		return wiremessage.Compressed{}, err
+	}
+
+	compressedMessage := wiremessage.Compressed{
+		MsgHeader: wiremessage.Header{
+			// MessageLength and OpCode will be set when marshalling wire message by SetDefaults()
+			RequestID:  requestID,
+			ResponseTo: responseTo,
+		},
+		OriginalOpCode:    origOpcode,
+		UncompressedSize:  int32(len(c.wireMessageBuf)), // length of uncompressed message excluding MsgHeader
+		CompressorID:      wiremessage.CompressorID(c.compressor.CompressorID()),
+		CompressedMessage: compressedBytes,
+	}
+
+	return compressedMessage, nil
+}
+
+// returns []byte of uncompressed message with reconstructed header, original opcode, error
+func (c *connection) uncompressMessage(compressed wiremessage.Compressed) ([]byte, wiremessage.OpCode, error) {
+	// server doesn't guarantee the same compression method will be used each time so the CompressorID field must be
+	// used to find the correct method for uncompressing data
+	uncompressor := c.compressorMap[compressed.CompressorID]
+
+	// reset uncompressBuf
+	c.uncompressBuf = c.uncompressBuf[:0]
+	if int(compressed.UncompressedSize) > cap(c.uncompressBuf) {
+		c.uncompressBuf = make([]byte, 0, compressed.UncompressedSize)
+	}
+
+	uncompressedMessage, err := uncompressor.UncompressBytes(compressed.CompressedMessage, c.uncompressBuf)
+
+	if err != nil {
+		return nil, 0, err
+	}
+
+	origHeader := wiremessage.Header{
+		MessageLength: int32(len(uncompressedMessage)) + 16, // add 16 for original header
+		RequestID:     compressed.MsgHeader.RequestID,
+		ResponseTo:    compressed.MsgHeader.ResponseTo,
+	}
+
+	switch compressed.OriginalOpCode {
+	case wiremessage.OpReply:
+		origHeader.OpCode = wiremessage.OpReply
+	case wiremessage.OpMsg:
+		origHeader.OpCode = wiremessage.OpMsg
+	default:
+		return nil, 0, fmt.Errorf("opcode %s not implemented", compressed.OriginalOpCode)
+	}
+
+	var fullMessage []byte
+	fullMessage = origHeader.AppendHeader(fullMessage)
+	fullMessage = append(fullMessage, uncompressedMessage...)
+	return fullMessage, origHeader.OpCode, nil
+}
+
+func canMonitor(cmd string) bool {
+	if cmd == "authenticate" || cmd == "saslStart" || cmd == "saslContinue" || cmd == "getnonce" || cmd == "createUser" ||
+		cmd == "updateUser" || cmd == "copydbgetnonce" || cmd == "copydbsaslstart" || cmd == "copydb" {
+		return false
+	}
+
+	return true
+}
+
+func (c *connection) commandStartedEvent(ctx context.Context, wm wiremessage.WireMessage) error {
+	if c.cmdMonitor == nil || c.cmdMonitor.Started == nil {
+		return nil
+	}
+
+	startedEvent := &event.CommandStartedEvent{
+		ConnectionID: c.id,
+	}
+
+	var cmd bsonx.Doc
+	var err error
+	var legacy bool
+	var fullCollName string
+
+	var acknowledged bool
+	switch converted := wm.(type) {
+	case wiremessage.Query:
+		cmd, err = converted.CommandDocument()
+		if err != nil {
+			return err
+		}
+
+		acknowledged = converted.AcknowledgedWrite()
+		startedEvent.DatabaseName = converted.DatabaseName()
+		startedEvent.RequestID = int64(converted.MsgHeader.RequestID)
+		legacy = converted.Legacy()
+		fullCollName = converted.FullCollectionName
+	case wiremessage.Msg:
+		cmd, err = converted.GetMainDocument()
+		if err != nil {
+			return err
+		}
+
+		acknowledged = converted.AcknowledgedWrite()
+		arr, identifier, err := converted.GetSequenceArray()
+		if err != nil {
+			return err
+		}
+		if arr != nil {
+			cmd = cmd.Copy() // make copy to avoid changing original command
+			cmd = append(cmd, bsonx.Elem{identifier, bsonx.Array(arr)})
+		}
+
+		dbVal, err := cmd.LookupErr("$db")
+		if err != nil {
+			return err
+		}
+
+		startedEvent.DatabaseName = dbVal.StringValue()
+		startedEvent.RequestID = int64(converted.MsgHeader.RequestID)
+	case wiremessage.GetMore:
+		cmd = converted.CommandDocument()
+		startedEvent.DatabaseName = converted.DatabaseName()
+		startedEvent.RequestID = int64(converted.MsgHeader.RequestID)
+		acknowledged = true
+		legacy = true
+		fullCollName = converted.FullCollectionName
+	case wiremessage.KillCursors:
+		cmd = converted.CommandDocument()
+		startedEvent.DatabaseName = converted.DatabaseName
+		startedEvent.RequestID = int64(converted.MsgHeader.RequestID)
+		legacy = true
+	}
+
+	rawcmd, _ := cmd.MarshalBSON()
+	startedEvent.Command = rawcmd
+	startedEvent.CommandName = cmd[0].Key
+	if !canMonitor(startedEvent.CommandName) {
+		startedEvent.Command = emptyDoc
+	}
+
+	c.cmdMonitor.Started(ctx, startedEvent)
+
+	if !acknowledged {
+		if c.cmdMonitor.Succeeded == nil {
+			return nil
+		}
+
+		// unack writes must provide a CommandSucceededEvent with an { ok: 1 } reply
+		finishedEvent := event.CommandFinishedEvent{
+			DurationNanos: 0,
+			CommandName:   startedEvent.CommandName,
+			RequestID:     startedEvent.RequestID,
+			ConnectionID:  c.id,
+		}
+
+		c.cmdMonitor.Succeeded(ctx, &event.CommandSucceededEvent{
+			CommandFinishedEvent: finishedEvent,
+			Reply:                bsoncore.BuildDocument(nil, bsoncore.AppendInt32Element(nil, "ok", 1)),
+		})
+
+		return nil
+	}
+
+	c.commandMap[startedEvent.RequestID] = createMetadata(startedEvent.CommandName, legacy, fullCollName)
+	return nil
+}
+
+func processReply(reply bsonx.Doc) (bool, string) {
+	var success bool
+	var errmsg string
+	var errCode int32
+
+	for _, elem := range reply {
+		switch elem.Key {
+		case "ok":
+			switch elem.Value.Type() {
+			case bsontype.Int32:
+				if elem.Value.Int32() == 1 {
+					success = true
+				}
+			case bsontype.Int64:
+				if elem.Value.Int64() == 1 {
+					success = true
+				}
+			case bsontype.Double:
+				if elem.Value.Double() == 1 {
+					success = true
+				}
+			}
+		case "errmsg":
+			if str, ok := elem.Value.StringValueOK(); ok {
+				errmsg = str
+			}
+		case "code":
+			if c, ok := elem.Value.Int32OK(); ok {
+				errCode = c
+			}
+		}
+	}
+
+	if success {
+		return true, ""
+	}
+
+	fullErrMsg := fmt.Sprintf("Error code %d: %s", errCode, errmsg)
+	return false, fullErrMsg
+}
+
+func (c *connection) commandFinishedEvent(ctx context.Context, wm wiremessage.WireMessage) error {
+	if c.cmdMonitor == nil {
+		return nil
+	}
+
+	var reply bsonx.Doc
+	var requestID int64
+	var err error
+
+	switch converted := wm.(type) {
+	case wiremessage.Reply:
+		requestID = int64(converted.MsgHeader.ResponseTo)
+	case wiremessage.Msg:
+		requestID = int64(converted.MsgHeader.ResponseTo)
+	}
+	cmdMetadata := c.commandMap[requestID]
+	delete(c.commandMap, requestID)
+
+	switch converted := wm.(type) {
+	case wiremessage.Reply:
+		if cmdMetadata.Legacy {
+			reply, err = converted.GetMainLegacyDocument(cmdMetadata.FullCollectionName)
+		} else {
+			reply, err = converted.GetMainDocument()
+		}
+	case wiremessage.Msg:
+		reply, err = converted.GetMainDocument()
+	}
+	if err != nil {
+		return err
+	}
+
+	success, errmsg := processReply(reply)
+
+	if (success && c.cmdMonitor.Succeeded == nil) || (!success && c.cmdMonitor.Failed == nil) {
+		return nil
+	}
+
+	finishedEvent := event.CommandFinishedEvent{
+		DurationNanos: cmdMetadata.TimeDifference(),
+		CommandName:   cmdMetadata.Name,
+		RequestID:     requestID,
+		ConnectionID:  c.id,
+	}
+
+	if success {
+		if !canMonitor(finishedEvent.CommandName) {
+			successEvent := &event.CommandSucceededEvent{
+				Reply:                emptyDoc,
+				CommandFinishedEvent: finishedEvent,
+			}
+			c.cmdMonitor.Succeeded(ctx, successEvent)
+			return nil
+		}
+
+		// if response has type 1 document sequence, the sequence must be included as a BSON array in the event's reply.
+		if opmsg, ok := wm.(wiremessage.Msg); ok {
+			arr, identifier, err := opmsg.GetSequenceArray()
+			if err != nil {
+				return err
+			}
+			if arr != nil {
+				reply = reply.Copy() // make copy to avoid changing original command
+				reply = append(reply, bsonx.Elem{identifier, bsonx.Array(arr)})
+			}
+		}
+
+		replyraw, _ := reply.MarshalBSON()
+		successEvent := &event.CommandSucceededEvent{
+			Reply:                replyraw,
+			CommandFinishedEvent: finishedEvent,
+		}
+
+		c.cmdMonitor.Succeeded(ctx, successEvent)
+		return nil
+	}
+
+	failureEvent := &event.CommandFailedEvent{
+		Failure:              errmsg,
+		CommandFinishedEvent: finishedEvent,
+	}
+
+	c.cmdMonitor.Failed(ctx, failureEvent)
+	return nil
+}
+
+func (c *connection) WriteWireMessage(ctx context.Context, wm wiremessage.WireMessage) error {
+	var err error
+	if c.dead {
+		return Error{
+			ConnectionID: c.id,
+			message:      "connection is dead",
+		}
+	}
+
+	select {
+	case <-ctx.Done():
+		return Error{
+			ConnectionID: c.id,
+			Wrapped:      ctx.Err(),
+			message:      "failed to write",
+		}
+	default:
+	}
+
+	deadline := time.Time{}
+	if c.writeTimeout != 0 {
+		deadline = time.Now().Add(c.writeTimeout)
+	}
+
+	if dl, ok := ctx.Deadline(); ok && (deadline.IsZero() || dl.Before(deadline)) {
+		deadline = dl
+	}
+
+	if err := c.conn.SetWriteDeadline(deadline); err != nil {
+		return Error{
+			ConnectionID: c.id,
+			Wrapped:      err,
+			message:      "failed to set write deadline",
+		}
+	}
+
+	// Truncate the write buffer
+	c.writeBuf = c.writeBuf[:0]
+
+	messageToWrite := wm
+	// Compress if possible
+	if c.compressor != nil {
+		compressed, err := c.compressMessage(wm)
+		if err != nil {
+			return Error{
+				ConnectionID: c.id,
+				Wrapped:      err,
+				message:      "unable to compress wire message",
+			}
+		}
+		messageToWrite = compressed
+	}
+
+	c.writeBuf, err = messageToWrite.AppendWireMessage(c.writeBuf)
+	if err != nil {
+		return Error{
+			ConnectionID: c.id,
+			Wrapped:      err,
+			message:      "unable to encode wire message",
+		}
+	}
+
+	_, err = c.conn.Write(c.writeBuf)
+	if err != nil {
+		c.Close()
+		return Error{
+			ConnectionID: c.id,
+			Wrapped:      err,
+			message:      "unable to write wire message to network",
+		}
+	}
+
+	c.bumpIdleDeadline()
+	err = c.commandStartedEvent(ctx, wm)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (c *connection) ReadWireMessage(ctx context.Context) (wiremessage.WireMessage, error) {
+	if c.dead {
+		return nil, Error{
+			ConnectionID: c.id,
+			message:      "connection is dead",
+		}
+	}
+
+	select {
+	case <-ctx.Done():
+		// We close the connection because we don't know if there
+		// is an unread message on the wire.
+		c.Close()
+		return nil, Error{
+			ConnectionID: c.id,
+			Wrapped:      ctx.Err(),
+			message:      "failed to read",
+		}
+	default:
+	}
+
+	deadline := time.Time{}
+	if c.readTimeout != 0 {
+		deadline = time.Now().Add(c.readTimeout)
+	}
+
+	if ctxDL, ok := ctx.Deadline(); ok && (deadline.IsZero() || ctxDL.Before(deadline)) {
+		deadline = ctxDL
+	}
+
+	if err := c.conn.SetReadDeadline(deadline); err != nil {
+		return nil, Error{
+			ConnectionID: c.id,
+			Wrapped:      ctx.Err(),
+			message:      "failed to set read deadline",
+		}
+	}
+
+	var sizeBuf [4]byte
+	_, err := io.ReadFull(c.conn, sizeBuf[:])
+	if err != nil {
+		c.Close()
+		return nil, Error{
+			ConnectionID: c.id,
+			Wrapped:      err,
+			message:      "unable to decode message length",
+		}
+	}
+
+	size := readInt32(sizeBuf[:], 0)
+
+	// Isn't the best reuse, but resizing a []byte to be larger
+	// is difficult.
+	if cap(c.readBuf) > int(size) {
+		c.readBuf = c.readBuf[:size]
+	} else {
+		c.readBuf = make([]byte, size)
+	}
+
+	c.readBuf[0], c.readBuf[1], c.readBuf[2], c.readBuf[3] = sizeBuf[0], sizeBuf[1], sizeBuf[2], sizeBuf[3]
+
+	_, err = io.ReadFull(c.conn, c.readBuf[4:])
+	if err != nil {
+		c.Close()
+		return nil, Error{
+			ConnectionID: c.id,
+			Wrapped:      err,
+			message:      "unable to read full message",
+		}
+	}
+
+	hdr, err := wiremessage.ReadHeader(c.readBuf, 0)
+	if err != nil {
+		c.Close()
+		return nil, Error{
+			ConnectionID: c.id,
+			Wrapped:      err,
+			message:      "unable to decode header",
+		}
+	}
+
+	messageToDecode := c.readBuf
+	opcodeToCheck := hdr.OpCode
+
+	if hdr.OpCode == wiremessage.OpCompressed {
+		var compressed wiremessage.Compressed
+		err := compressed.UnmarshalWireMessage(c.readBuf)
+		if err != nil {
+			defer c.Close()
+			return nil, Error{
+				ConnectionID: c.id,
+				Wrapped:      err,
+				message:      "unable to decode OP_COMPRESSED",
+			}
+		}
+
+		uncompressed, origOpcode, err := c.uncompressMessage(compressed)
+		if err != nil {
+			defer c.Close()
+			return nil, Error{
+				ConnectionID: c.id,
+				Wrapped:      err,
+				message:      "unable to uncompress message",
+			}
+		}
+		messageToDecode = uncompressed
+		opcodeToCheck = origOpcode
+	}
+
+	var wm wiremessage.WireMessage
+	switch opcodeToCheck {
+	case wiremessage.OpReply:
+		var r wiremessage.Reply
+		err := r.UnmarshalWireMessage(messageToDecode)
+		if err != nil {
+			c.Close()
+			return nil, Error{
+				ConnectionID: c.id,
+				Wrapped:      err,
+				message:      "unable to decode OP_REPLY",
+			}
+		}
+		wm = r
+	case wiremessage.OpMsg:
+		var reply wiremessage.Msg
+		err := reply.UnmarshalWireMessage(messageToDecode)
+		if err != nil {
+			c.Close()
+			return nil, Error{
+				ConnectionID: c.id,
+				Wrapped:      err,
+				message:      "unable to decode OP_MSG",
+			}
+		}
+		wm = reply
+	default:
+		c.Close()
+		return nil, Error{
+			ConnectionID: c.id,
+			message:      fmt.Sprintf("opcode %s not implemented", hdr.OpCode),
+		}
+	}
+
+	c.bumpIdleDeadline()
+	err = c.commandFinishedEvent(ctx, wm)
+	if err != nil {
+		return nil, err // TODO: do we care if monitoring fails?
+	}
+
+	return wm, nil
+}
+
+func (c *connection) bumpIdleDeadline() {
+	if c.idleTimeout > 0 {
+		c.idleDeadline = time.Now().Add(c.idleTimeout)
+	}
+}
+
+func (c *connection) Close() error {
+	c.dead = true
+	err := c.conn.Close()
+	if err != nil {
+		return Error{
+			ConnectionID: c.id,
+			Wrapped:      err,
+			message:      "failed to close net.Conn",
+		}
+	}
+
+	return nil
+}
+
+func (c *connection) ID() string {
+	return c.id
+}
+
+func (c *connection) initialize(ctx context.Context, appName string) error {
+	return nil
+}
+
+func readInt32(b []byte, pos int32) int32 {
+	return (int32(b[pos+0])) | (int32(b[pos+1]) << 8) | (int32(b[pos+2]) << 16) | (int32(b[pos+3]) << 24)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/error.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/error.go
new file mode 100644
index 0000000..eebca94
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/error.go
@@ -0,0 +1,41 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package connection
+
+import "fmt"
+
+// Error represents a connection error.
+type Error struct {
+	ConnectionID string
+	Wrapped      error
+
+	message string
+}
+
+// Error implements the error interface.
+func (e Error) Error() string {
+	if e.Wrapped != nil {
+		return fmt.Sprintf("connection(%s) %s: %s", e.ConnectionID, e.message, e.Wrapped.Error())
+	}
+	return fmt.Sprintf("connection(%s) %s", e.ConnectionID, e.message)
+}
+
+// NetworkError represents an error that occurred while reading from or writing
+// to a network socket.
+type NetworkError struct {
+	ConnectionID string
+	Wrapped      error
+}
+
+func (ne NetworkError) Error() string {
+	return fmt.Sprintf("connection(%s): %s", ne.ConnectionID, ne.Wrapped.Error())
+}
+
+// PoolError is an error returned from a Pool method.
+type PoolError string
+
+func (pe PoolError) Error() string { return string(pe) }
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/keepalive_300.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/keepalive_300.go
new file mode 100644
index 0000000..554e38d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/keepalive_300.go
@@ -0,0 +1,13 @@
+// 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
+
+//+build !go1.12
+
+package connection
+
+import "time"
+
+const tcpKeepalive = 300 * time.Second
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/keepalive_default.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/keepalive_default.go
new file mode 100644
index 0000000..9eeeb69
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/keepalive_default.go
@@ -0,0 +1,11 @@
+// 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
+
+//+build go1.12
+
+package connection
+
+const tcpKeepalive = 0 // will be set by default on Go 1.12 and higher
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/listener.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/listener.go
new file mode 100644
index 0000000..76f4f7d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/listener.go
@@ -0,0 +1,27 @@
+// 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 connection
+
+// Listener is a generic mongodb network protocol listener. It can return connections
+// that speak the mongodb wire protocol.
+//
+// Multiple goroutines may invoke methods on a Listener simultaneously.
+//
+// TODO(GODRIVER-270): Implement this.
+type Listener interface {
+	// Accept waits for and returns the next Connection to the listener.
+	Accept() (Connection, error)
+
+	// Close closes the listener.
+	Close() error
+
+	// Addr returns the listener's network address.
+	Addr() Addr
+}
+
+// Listen creates a new listener on the provided network and address.
+func Listen(network, address string) (Listener, error) { return nil, nil }
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/options.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/options.go
new file mode 100644
index 0000000..cd19931
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/options.go
@@ -0,0 +1,148 @@
+// 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 connection
+
+import (
+	"net"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/event"
+	"github.com/mongodb/mongo-go-driver/x/network/compressor"
+)
+
+type config struct {
+	appName        string
+	connectTimeout time.Duration
+	dialer         Dialer
+	handshaker     Handshaker
+	idleTimeout    time.Duration
+	lifeTimeout    time.Duration
+	cmdMonitor     *event.CommandMonitor
+	readTimeout    time.Duration
+	writeTimeout   time.Duration
+	tlsConfig      *TLSConfig
+	compressors    []compressor.Compressor
+}
+
+func newConfig(opts ...Option) (*config, error) {
+	cfg := &config{
+		connectTimeout: 30 * time.Second,
+		dialer:         nil,
+		idleTimeout:    10 * time.Minute,
+		lifeTimeout:    30 * time.Minute,
+	}
+
+	for _, opt := range opts {
+		err := opt(cfg)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if cfg.dialer == nil {
+		cfg.dialer = &net.Dialer{
+			KeepAlive: tcpKeepalive,
+			Timeout:   cfg.connectTimeout,
+		}
+	}
+
+	return cfg, nil
+}
+
+// Option is used to configure a connection.
+type Option func(*config) error
+
+// WithAppName sets the application name which gets sent to MongoDB when it
+// first connects.
+func WithAppName(fn func(string) string) Option {
+	return func(c *config) error {
+		c.appName = fn(c.appName)
+		return nil
+	}
+}
+
+// WithCompressors sets the compressors that can be used for communication.
+func WithCompressors(fn func([]compressor.Compressor) []compressor.Compressor) Option {
+	return func(c *config) error {
+		c.compressors = fn(c.compressors)
+		return nil
+	}
+}
+
+// WithConnectTimeout configures the maximum amount of time a dial will wait for a
+// connect to complete. The default is 30 seconds.
+func WithConnectTimeout(fn func(time.Duration) time.Duration) Option {
+	return func(c *config) error {
+		c.connectTimeout = fn(c.connectTimeout)
+		return nil
+	}
+}
+
+// WithDialer configures the Dialer to use when making a new connection to MongoDB.
+func WithDialer(fn func(Dialer) Dialer) Option {
+	return func(c *config) error {
+		c.dialer = fn(c.dialer)
+		return nil
+	}
+}
+
+// WithHandshaker configures the Handshaker that wll be used to initialize newly
+// dialed connections.
+func WithHandshaker(fn func(Handshaker) Handshaker) Option {
+	return func(c *config) error {
+		c.handshaker = fn(c.handshaker)
+		return nil
+	}
+}
+
+// WithIdleTimeout configures the maximum idle time to allow for a connection.
+func WithIdleTimeout(fn func(time.Duration) time.Duration) Option {
+	return func(c *config) error {
+		c.idleTimeout = fn(c.idleTimeout)
+		return nil
+	}
+}
+
+// WithLifeTimeout configures the maximum life of a connection.
+func WithLifeTimeout(fn func(time.Duration) time.Duration) Option {
+	return func(c *config) error {
+		c.lifeTimeout = fn(c.lifeTimeout)
+		return nil
+	}
+}
+
+// WithReadTimeout configures the maximum read time for a connection.
+func WithReadTimeout(fn func(time.Duration) time.Duration) Option {
+	return func(c *config) error {
+		c.readTimeout = fn(c.readTimeout)
+		return nil
+	}
+}
+
+// WithWriteTimeout configures the maximum write time for a connection.
+func WithWriteTimeout(fn func(time.Duration) time.Duration) Option {
+	return func(c *config) error {
+		c.writeTimeout = fn(c.writeTimeout)
+		return nil
+	}
+}
+
+// WithTLSConfig configures the TLS options for a connection.
+func WithTLSConfig(fn func(*TLSConfig) *TLSConfig) Option {
+	return func(c *config) error {
+		c.tlsConfig = fn(c.tlsConfig)
+		return nil
+	}
+}
+
+// WithMonitor configures a event for command monitoring.
+func WithMonitor(fn func(*event.CommandMonitor) *event.CommandMonitor) Option {
+	return func(c *config) error {
+		c.cmdMonitor = fn(c.cmdMonitor)
+		return nil
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/pool.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/pool.go
new file mode 100644
index 0000000..3a25ad3
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/pool.go
@@ -0,0 +1,310 @@
+// 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 connection
+
+import (
+	"context"
+	"sync"
+	"sync/atomic"
+
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+	"golang.org/x/sync/semaphore"
+)
+
+// ErrPoolClosed is returned from an attempt to use a closed pool.
+var ErrPoolClosed = PoolError("pool is closed")
+
+// ErrSizeLargerThanCapacity is returned from an attempt to create a pool with a size
+// larger than the capacity.
+var ErrSizeLargerThanCapacity = PoolError("size is larger than capacity")
+
+// ErrPoolConnected is returned from an attempt to connect an already connected pool
+var ErrPoolConnected = PoolError("pool is connected")
+
+// ErrPoolDisconnected is returned from an attempt to disconnect an already disconnected
+// or disconnecting pool.
+var ErrPoolDisconnected = PoolError("pool is disconnected or disconnecting")
+
+// ErrConnectionClosed is returned from an attempt to use an already closed connection.
+var ErrConnectionClosed = Error{ConnectionID: "<closed>", message: "connection is closed"}
+
+// These constants represent the connection states of a pool.
+const (
+	disconnected int32 = iota
+	disconnecting
+	connected
+)
+
+// Pool is used to pool Connections to a server.
+type Pool interface {
+	// Get must return a nil *description.Server if the returned connection is
+	// not a newly dialed connection.
+	Get(context.Context) (Connection, *description.Server, error)
+	// Connect handles the initialization of a Pool and allow Connections to be
+	// retrieved and pooled. Implementations must return an error if Connect is
+	// called more than once before calling Disconnect.
+	Connect(context.Context) error
+	// Disconnect closest connections managed by this Pool. Implementations must
+	// either wait until all of the connections in use have been returned and
+	// closed or the context expires before returning. If the context expires
+	// via cancellation, deadline, timeout, or some other manner, implementations
+	// must close the in use connections. If this method returns with no errors,
+	// all connections managed by this pool must be closed. Calling Disconnect
+	// multiple times after a single Connect call must result in an error.
+	Disconnect(context.Context) error
+	Drain() error
+}
+
+type pool struct {
+	address    address.Address
+	opts       []Option
+	conns      chan *pooledConnection
+	generation uint64
+	sem        *semaphore.Weighted
+	connected  int32
+	nextid     uint64
+	capacity   uint64
+	inflight   map[uint64]*pooledConnection
+
+	sync.Mutex
+}
+
+// NewPool creates a new pool that will hold size number of idle connections
+// and will create a max of capacity connections. It will use the provided
+// options.
+func NewPool(addr address.Address, size, capacity uint64, opts ...Option) (Pool, error) {
+	if size > capacity {
+		return nil, ErrSizeLargerThanCapacity
+	}
+	p := &pool{
+		address:    addr,
+		conns:      make(chan *pooledConnection, size),
+		generation: 0,
+		sem:        semaphore.NewWeighted(int64(capacity)),
+		connected:  disconnected,
+		capacity:   capacity,
+		inflight:   make(map[uint64]*pooledConnection),
+		opts:       opts,
+	}
+	return p, nil
+}
+
+func (p *pool) Drain() error {
+	atomic.AddUint64(&p.generation, 1)
+	return nil
+}
+
+func (p *pool) Connect(ctx context.Context) error {
+	if !atomic.CompareAndSwapInt32(&p.connected, disconnected, connected) {
+		return ErrPoolConnected
+	}
+	atomic.AddUint64(&p.generation, 1)
+	return nil
+}
+
+func (p *pool) Disconnect(ctx context.Context) error {
+	if !atomic.CompareAndSwapInt32(&p.connected, connected, disconnecting) {
+		return ErrPoolDisconnected
+	}
+
+	// We first clear out the idle connections, then we attempt to acquire the entire capacity
+	// semaphore. If the context is either cancelled, the deadline expires, or there is a timeout
+	// the semaphore acquire method will return an error. If that happens, we will aggressively
+	// close the remaining open connections. If we were able to successfully acquire the semaphore,
+	// then all of the in flight connections have been closed and we release the semaphore.
+loop:
+	for {
+		select {
+		case pc := <-p.conns:
+			// This error would be overwritten by the semaphore
+			_ = p.closeConnection(pc)
+		default:
+			break loop
+		}
+	}
+	err := p.sem.Acquire(ctx, int64(p.capacity))
+	if err != nil {
+		p.Lock()
+		// We copy the remaining connections to close into a slice, then
+		// iterate the slice to do the closing. This allows us to use a single
+		// function to actually clean up and close connections at the expense of
+		// a double iteration in the worst case.
+		toClose := make([]*pooledConnection, 0, len(p.inflight))
+		for _, pc := range p.inflight {
+			toClose = append(toClose, pc)
+		}
+		p.Unlock()
+		for _, pc := range toClose {
+			_ = pc.Close()
+		}
+	} else {
+		p.sem.Release(int64(p.capacity))
+	}
+	atomic.StoreInt32(&p.connected, disconnected)
+	return nil
+}
+
+func (p *pool) Get(ctx context.Context) (Connection, *description.Server, error) {
+	if atomic.LoadInt32(&p.connected) != connected {
+		return nil, nil, ErrPoolClosed
+	}
+
+	err := p.sem.Acquire(ctx, 1)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return p.get(ctx)
+}
+
+func (p *pool) get(ctx context.Context) (Connection, *description.Server, error) {
+	g := atomic.LoadUint64(&p.generation)
+	select {
+	case c := <-p.conns:
+		if c.Expired() {
+			go p.closeConnection(c)
+			return p.get(ctx)
+		}
+
+		return &acquired{Connection: c, sem: p.sem}, nil, nil
+	case <-ctx.Done():
+		p.sem.Release(1)
+		return nil, nil, ctx.Err()
+	default:
+		c, desc, err := New(ctx, p.address, p.opts...)
+		if err != nil {
+			p.sem.Release(1)
+			return nil, nil, err
+		}
+
+		pc := &pooledConnection{
+			Connection: c,
+			p:          p,
+			generation: g,
+			id:         atomic.AddUint64(&p.nextid, 1),
+		}
+		p.Lock()
+		if atomic.LoadInt32(&p.connected) != connected {
+			p.Unlock()
+			p.sem.Release(1)
+			p.closeConnection(pc)
+			return nil, nil, ErrPoolClosed
+		}
+		defer p.Unlock()
+		p.inflight[pc.id] = pc
+		return &acquired{Connection: pc, sem: p.sem}, desc, nil
+	}
+}
+
+func (p *pool) closeConnection(pc *pooledConnection) error {
+	if !atomic.CompareAndSwapInt32(&pc.closed, 0, 1) {
+		return nil
+	}
+	p.Lock()
+	delete(p.inflight, pc.id)
+	p.Unlock()
+	return pc.Connection.Close()
+}
+
+func (p *pool) returnConnection(pc *pooledConnection) error {
+	if atomic.LoadInt32(&p.connected) != connected || pc.Expired() {
+		return p.closeConnection(pc)
+	}
+
+	select {
+	case p.conns <- pc:
+		return nil
+	default:
+		return p.closeConnection(pc)
+	}
+}
+
+func (p *pool) isExpired(generation uint64) bool {
+	return generation < atomic.LoadUint64(&p.generation)
+}
+
+type pooledConnection struct {
+	Connection
+	p          *pool
+	generation uint64
+	id         uint64
+	closed     int32
+}
+
+func (pc *pooledConnection) Close() error {
+	return pc.p.returnConnection(pc)
+}
+
+func (pc *pooledConnection) Expired() bool {
+	return pc.Connection.Expired() || pc.p.isExpired(pc.generation)
+}
+
+type acquired struct {
+	Connection
+
+	sem *semaphore.Weighted
+	sync.Mutex
+}
+
+func (a *acquired) WriteWireMessage(ctx context.Context, wm wiremessage.WireMessage) error {
+	a.Lock()
+	defer a.Unlock()
+	if a.Connection == nil {
+		return ErrConnectionClosed
+	}
+	return a.Connection.WriteWireMessage(ctx, wm)
+}
+
+func (a *acquired) ReadWireMessage(ctx context.Context) (wiremessage.WireMessage, error) {
+	a.Lock()
+	defer a.Unlock()
+	if a.Connection == nil {
+		return nil, ErrConnectionClosed
+	}
+	return a.Connection.ReadWireMessage(ctx)
+}
+
+func (a *acquired) Close() error {
+	a.Lock()
+	defer a.Unlock()
+	if a.Connection == nil {
+		return nil
+	}
+	err := a.Connection.Close()
+	a.sem.Release(1)
+	a.Connection = nil
+	return err
+}
+
+func (a *acquired) Expired() bool {
+	a.Lock()
+	defer a.Unlock()
+	if a.Connection == nil {
+		return true
+	}
+	return a.Connection.Expired()
+}
+
+func (a *acquired) Alive() bool {
+	a.Lock()
+	defer a.Unlock()
+	if a.Connection == nil {
+		return false
+	}
+	return a.Connection.Alive()
+}
+
+func (a *acquired) ID() string {
+	a.Lock()
+	defer a.Unlock()
+	if a.Connection == nil {
+		return "<closed>"
+	}
+	return a.Connection.ID()
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/proxy.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/proxy.go
new file mode 100644
index 0000000..62e18d2
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/proxy.go
@@ -0,0 +1,26 @@
+// 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 connection
+
+import "github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+
+// Proxy implements a MongoDB proxy. It will use the given pool to connect to a
+// MongoDB server and proxy the traffic between connections it is given and the
+// server. It will pass each of the wireops it reads from the handled connection
+// to a Processor. If an error is returned from the processor, the wireop will
+// not be forwarded onto the server. If there is not an error the returned message
+// will be passed onto the server. If both the return message and the error are nil,
+// the original wiremessage will be passed onto the server.
+//
+// TODO(GODRIVER-268): Implement this.
+type Proxy struct {
+	Processor wiremessage.Transformer
+	Pool      Pool
+}
+
+// HandleConnection implements the Handler interface.
+func (*Proxy) HandleConnection(Connection) { return }
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/server.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/server.go
new file mode 100644
index 0000000..033d0d7
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/server.go
@@ -0,0 +1,40 @@
+// 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 connection
+
+import "context"
+
+// Server is used to handle incoming Connections. It handles the boilerplate of accepting a
+// Connection and cleaning it up after running a Handler. This also makes it easier to build
+// higher level processors, like proxies, by handling the life cycle of the underlying
+// connection.
+//
+// TODO(GODRIVER-269): Implement this.
+type Server struct {
+	Addr    Addr
+	Handler Handler
+}
+
+// ListenAndServe listens on the network address srv.Addr and calls Serve to
+// handle requests on incoming connections. If srv.Addr is blank, "localhost:27017"
+// is used.
+func (*Server) ListenAndServe() error { return nil }
+
+// Serve accepts incoming connections on the Listener l, creating a new service
+// goroutine for each. The service goroutines call srv.Handler and do not processing
+// beforehand. When srv.Handler returns, the connection is closed.
+func (*Server) Serve(Listener) error { return nil }
+
+// Shutdown gracefully shuts down the server by closing the active listeners. Shutdown
+// does not handle or wait for all open connections to close and return before returning.
+func (*Server) Shutdown(context.Context) error { return nil }
+
+// Handler handles an individual Connection. Returning signals that the Connection
+// is no longer needed and can be closed.
+type Handler interface {
+	HandleConnection(Connection)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/tlsconfig.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/tlsconfig.go
new file mode 100644
index 0000000..0536418
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/tlsconfig.go
@@ -0,0 +1,237 @@
+// 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 connection
+
+import (
+	"bytes"
+	"crypto/tls"
+	"crypto/x509"
+	"encoding/asn1"
+	"encoding/hex"
+	"encoding/pem"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"strings"
+)
+
+// TLSConfig contains options for configuring a TLS connection to the server.
+type TLSConfig struct {
+	*tls.Config
+	clientCertPass func() string
+}
+
+// NewTLSConfig creates a new TLSConfig.
+func NewTLSConfig() *TLSConfig {
+	cfg := &TLSConfig{}
+	cfg.Config = new(tls.Config)
+
+	return cfg
+}
+
+// SetClientCertDecryptPassword sets a function to retrieve the decryption password
+// necessary to read a certificate. This is a function instead of a string to
+// provide greater flexibility when deciding how to retrieve and store the password.
+func (c *TLSConfig) SetClientCertDecryptPassword(f func() string) {
+	c.clientCertPass = f
+}
+
+// SetInsecure sets whether the client should verify the server's certificate
+// chain and hostnames.
+func (c *TLSConfig) SetInsecure(allow bool) {
+	c.InsecureSkipVerify = allow
+}
+
+// AddCACertFromFile adds a root CA certificate to the configuration given a path
+// to the containing file.
+func (c *TLSConfig) AddCACertFromFile(file string) error {
+	data, err := ioutil.ReadFile(file)
+	if err != nil {
+		return err
+	}
+
+	certBytes, err := loadCert(data)
+	if err != nil {
+		return err
+	}
+
+	cert, err := x509.ParseCertificate(certBytes)
+	if err != nil {
+		return err
+	}
+
+	if c.RootCAs == nil {
+		c.RootCAs = x509.NewCertPool()
+	}
+
+	c.RootCAs.AddCert(cert)
+
+	return nil
+}
+
+// AddClientCertFromFile adds a client certificate to the configuration given a path to the
+// containing file and returns the certificate's subject name.
+func (c *TLSConfig) AddClientCertFromFile(clientFile string) (string, error) {
+	data, err := ioutil.ReadFile(clientFile)
+	if err != nil {
+		return "", err
+	}
+
+	var currentBlock *pem.Block
+	var certBlock, certDecodedBlock, keyBlock []byte
+
+	remaining := data
+	start := 0
+	for {
+		currentBlock, remaining = pem.Decode(remaining)
+		if currentBlock == nil {
+			break
+		}
+
+		if currentBlock.Type == "CERTIFICATE" {
+			certBlock = data[start : len(data)-len(remaining)]
+			certDecodedBlock = currentBlock.Bytes
+			start += len(certBlock)
+		} else if strings.HasSuffix(currentBlock.Type, "PRIVATE KEY") {
+			if c.clientCertPass != nil && x509.IsEncryptedPEMBlock(currentBlock) {
+				var encoded bytes.Buffer
+				buf, err := x509.DecryptPEMBlock(currentBlock, []byte(c.clientCertPass()))
+				if err != nil {
+					return "", err
+				}
+
+				pem.Encode(&encoded, &pem.Block{Type: currentBlock.Type, Bytes: buf})
+				keyBlock = encoded.Bytes()
+				start = len(data) - len(remaining)
+			} else {
+				keyBlock = data[start : len(data)-len(remaining)]
+				start += len(keyBlock)
+			}
+		}
+	}
+	if len(certBlock) == 0 {
+		return "", fmt.Errorf("failed to find CERTIFICATE")
+	}
+	if len(keyBlock) == 0 {
+		return "", fmt.Errorf("failed to find PRIVATE KEY")
+	}
+
+	cert, err := tls.X509KeyPair(certBlock, keyBlock)
+	if err != nil {
+		return "", err
+	}
+
+	c.Certificates = append(c.Certificates, cert)
+
+	// The documentation for the tls.X509KeyPair indicates that the Leaf certificate is not
+	// retained.
+	crt, err := x509.ParseCertificate(certDecodedBlock)
+	if err != nil {
+		return "", err
+	}
+
+	return x509CertSubject(crt), nil
+}
+
+func loadCert(data []byte) ([]byte, error) {
+	var certBlock *pem.Block
+
+	for certBlock == nil {
+		if data == nil || len(data) == 0 {
+			return nil, errors.New(".pem file must have both a CERTIFICATE and an RSA PRIVATE KEY section")
+		}
+
+		block, rest := pem.Decode(data)
+		if block == nil {
+			return nil, errors.New("invalid .pem file")
+		}
+
+		switch block.Type {
+		case "CERTIFICATE":
+			if certBlock != nil {
+				return nil, errors.New("multiple CERTIFICATE sections in .pem file")
+			}
+
+			certBlock = block
+		}
+
+		data = rest
+	}
+
+	return certBlock.Bytes, nil
+}
+
+// Because the functionality to convert a pkix.Name to a string wasn't added until Go 1.10, we
+// need to copy the implementation (along with the attributeTypeNames map below).
+func x509CertSubject(cert *x509.Certificate) string {
+	r := cert.Subject.ToRDNSequence()
+
+	s := ""
+	for i := 0; i < len(r); i++ {
+		rdn := r[len(r)-1-i]
+		if i > 0 {
+			s += ","
+		}
+		for j, tv := range rdn {
+			if j > 0 {
+				s += "+"
+			}
+
+			oidString := tv.Type.String()
+			typeName, ok := attributeTypeNames[oidString]
+			if !ok {
+				derBytes, err := asn1.Marshal(tv.Value)
+				if err == nil {
+					s += oidString + "=#" + hex.EncodeToString(derBytes)
+					continue // No value escaping necessary.
+				}
+
+				typeName = oidString
+			}
+
+			valueString := fmt.Sprint(tv.Value)
+			escaped := make([]rune, 0, len(valueString))
+
+			for k, c := range valueString {
+				escape := false
+
+				switch c {
+				case ',', '+', '"', '\\', '<', '>', ';':
+					escape = true
+
+				case ' ':
+					escape = k == 0 || k == len(valueString)-1
+
+				case '#':
+					escape = k == 0
+				}
+
+				if escape {
+					escaped = append(escaped, '\\', c)
+				} else {
+					escaped = append(escaped, c)
+				}
+			}
+
+			s += typeName + "=" + string(escaped)
+		}
+	}
+
+	return s
+}
+
+var attributeTypeNames = map[string]string{
+	"2.5.4.6":  "C",
+	"2.5.4.10": "O",
+	"2.5.4.11": "OU",
+	"2.5.4.3":  "CN",
+	"2.5.4.5":  "SERIALNUMBER",
+	"2.5.4.7":  "L",
+	"2.5.4.8":  "ST",
+	"2.5.4.9":  "STREET",
+	"2.5.4.17": "POSTALCODE",
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/tlsconfig_clone_17.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/tlsconfig_clone_17.go
new file mode 100644
index 0000000..a753dfd
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connection/tlsconfig_clone_17.go
@@ -0,0 +1,42 @@
+// 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 connection
+
+import "crypto/tls"
+
+// Clone returns a shallow clone of c. It is safe to clone a Config that is being
+// used concurrently by a TLS client or server.
+func (c *TLSConfig) Clone() *TLSConfig {
+	cfg := cloneconfig(c.Config)
+	return &TLSConfig{cfg, c.clientCertPass}
+}
+
+func cloneconfig(c *tls.Config) *tls.Config {
+	return &tls.Config{
+		Rand:                        c.Rand,
+		Time:                        c.Time,
+		Certificates:                c.Certificates,
+		NameToCertificate:           c.NameToCertificate,
+		GetCertificate:              c.GetCertificate,
+		RootCAs:                     c.RootCAs,
+		NextProtos:                  c.NextProtos,
+		ServerName:                  c.ServerName,
+		ClientAuth:                  c.ClientAuth,
+		ClientCAs:                   c.ClientCAs,
+		InsecureSkipVerify:          c.InsecureSkipVerify,
+		CipherSuites:                c.CipherSuites,
+		PreferServerCipherSuites:    c.PreferServerCipherSuites,
+		SessionTicketsDisabled:      c.SessionTicketsDisabled,
+		SessionTicketKey:            c.SessionTicketKey,
+		ClientSessionCache:          c.ClientSessionCache,
+		MinVersion:                  c.MinVersion,
+		MaxVersion:                  c.MaxVersion,
+		CurvePreferences:            c.CurvePreferences,
+		DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
+		Renegotiation:               c.Renegotiation,
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/connstring/connstring.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/connstring/connstring.go
new file mode 100644
index 0000000..263a84c
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/connstring/connstring.go
@@ -0,0 +1,773 @@
+// 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 connstring
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/url"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/internal"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
+)
+
+// Parse parses the provided uri and returns a URI object.
+func Parse(s string) (ConnString, error) {
+	var p parser
+	err := p.parse(s)
+	if err != nil {
+		err = internal.WrapErrorf(err, "error parsing uri (%s)", s)
+	}
+	return p.ConnString, err
+}
+
+// ConnString represents a connection string to mongodb.
+type ConnString struct {
+	Original                           string
+	AppName                            string
+	AuthMechanism                      string
+	AuthMechanismProperties            map[string]string
+	AuthSource                         string
+	Compressors                        []string
+	Connect                            ConnectMode
+	ConnectSet                         bool
+	ConnectTimeout                     time.Duration
+	ConnectTimeoutSet                  bool
+	Database                           string
+	HeartbeatInterval                  time.Duration
+	HeartbeatIntervalSet               bool
+	Hosts                              []string
+	J                                  bool
+	JSet                               bool
+	LocalThreshold                     time.Duration
+	LocalThresholdSet                  bool
+	MaxConnIdleTime                    time.Duration
+	MaxConnIdleTimeSet                 bool
+	MaxPoolSize                        uint16
+	MaxPoolSizeSet                     bool
+	Password                           string
+	PasswordSet                        bool
+	ReadConcernLevel                   string
+	ReadPreference                     string
+	ReadPreferenceTagSets              []map[string]string
+	RetryWrites                        bool
+	RetryWritesSet                     bool
+	MaxStaleness                       time.Duration
+	MaxStalenessSet                    bool
+	ReplicaSet                         string
+	ServerSelectionTimeout             time.Duration
+	ServerSelectionTimeoutSet          bool
+	SocketTimeout                      time.Duration
+	SocketTimeoutSet                   bool
+	SSL                                bool
+	SSLSet                             bool
+	SSLClientCertificateKeyFile        string
+	SSLClientCertificateKeyFileSet     bool
+	SSLClientCertificateKeyPassword    func() string
+	SSLClientCertificateKeyPasswordSet bool
+	SSLInsecure                        bool
+	SSLInsecureSet                     bool
+	SSLCaFile                          string
+	SSLCaFileSet                       bool
+	WString                            string
+	WNumber                            int
+	WNumberSet                         bool
+	Username                           string
+	ZlibLevel                          int
+
+	WTimeout              time.Duration
+	WTimeoutSet           bool
+	WTimeoutSetFromOption bool
+
+	Options        map[string][]string
+	UnknownOptions map[string][]string
+}
+
+func (u *ConnString) String() string {
+	return u.Original
+}
+
+// ConnectMode informs the driver on how to connect
+// to the server.
+type ConnectMode uint8
+
+// ConnectMode constants.
+const (
+	AutoConnect ConnectMode = iota
+	SingleConnect
+)
+
+type parser struct {
+	ConnString
+}
+
+func (p *parser) parse(original string) error {
+	p.Original = original
+	uri := original
+
+	var err error
+	var isSRV bool
+	if strings.HasPrefix(uri, "mongodb+srv://") {
+		isSRV = true
+		// remove the scheme
+		uri = uri[14:]
+	} else if strings.HasPrefix(uri, "mongodb://") {
+		// remove the scheme
+		uri = uri[10:]
+	} else {
+		return fmt.Errorf("scheme must be \"mongodb\" or \"mongodb+srv\"")
+	}
+
+	if idx := strings.Index(uri, "@"); idx != -1 {
+		userInfo := uri[:idx]
+		uri = uri[idx+1:]
+
+		username := userInfo
+		var password string
+
+		if idx := strings.Index(userInfo, ":"); idx != -1 {
+			username = userInfo[:idx]
+			password = userInfo[idx+1:]
+			p.PasswordSet = true
+		}
+
+		if len(username) > 1 {
+			if strings.Contains(username, "/") {
+				return fmt.Errorf("unescaped slash in username")
+			}
+		}
+
+		p.Username, err = url.QueryUnescape(username)
+		if err != nil {
+			return internal.WrapErrorf(err, "invalid username")
+		}
+		if len(password) > 1 {
+			if strings.Contains(password, ":") {
+				return fmt.Errorf("unescaped colon in password")
+			}
+			if strings.Contains(password, "/") {
+				return fmt.Errorf("unescaped slash in password")
+			}
+			p.Password, err = url.QueryUnescape(password)
+			if err != nil {
+				return internal.WrapErrorf(err, "invalid password")
+			}
+		}
+	}
+
+	// fetch the hosts field
+	hosts := uri
+	if idx := strings.IndexAny(uri, "/?@"); idx != -1 {
+		if uri[idx] == '@' {
+			return fmt.Errorf("unescaped @ sign in user info")
+		}
+		if uri[idx] == '?' {
+			return fmt.Errorf("must have a / before the query ?")
+		}
+		hosts = uri[:idx]
+	}
+
+	var connectionArgsFromTXT []string
+	parsedHosts := strings.Split(hosts, ",")
+
+	if isSRV {
+		parsedHosts = strings.Split(hosts, ",")
+		if len(parsedHosts) != 1 {
+			return fmt.Errorf("URI with SRV must include one and only one hostname")
+		}
+		parsedHosts, err = fetchSeedlistFromSRV(parsedHosts[0])
+		if err != nil {
+			return err
+		}
+
+		// error ignored because finding a TXT record should not be
+		// considered an error.
+		recordsFromTXT, _ := net.LookupTXT(hosts)
+
+		// This is a temporary fix to get around bug https://github.com/golang/go/issues/21472.
+		// It will currently incorrectly concatenate multiple TXT records to one
+		// on windows.
+		if runtime.GOOS == "windows" {
+			recordsFromTXT = []string{strings.Join(recordsFromTXT, "")}
+		}
+
+		if len(recordsFromTXT) > 1 {
+			return errors.New("multiple records from TXT not supported")
+		}
+		if len(recordsFromTXT) > 0 {
+			connectionArgsFromTXT = strings.FieldsFunc(recordsFromTXT[0], func(r rune) bool { return r == ';' || r == '&' })
+
+			err := validateTXTResult(connectionArgsFromTXT)
+			if err != nil {
+				return err
+			}
+
+		}
+
+		// SSL is enabled by default for SRV, but can be manually disabled with "ssl=false".
+		p.SSL = true
+		p.SSLSet = true
+	}
+
+	for _, host := range parsedHosts {
+		err = p.addHost(host)
+		if err != nil {
+			return internal.WrapErrorf(err, "invalid host \"%s\"", host)
+		}
+	}
+	if len(p.Hosts) == 0 {
+		return fmt.Errorf("must have at least 1 host")
+	}
+
+	uri = uri[len(hosts):]
+
+	extractedDatabase, err := extractDatabaseFromURI(uri)
+	if err != nil {
+		return err
+	}
+
+	uri = extractedDatabase.uri
+	p.Database = extractedDatabase.db
+
+	connectionArgsFromQueryString, err := extractQueryArgsFromURI(uri)
+	connectionArgPairs := append(connectionArgsFromTXT, connectionArgsFromQueryString...)
+
+	for _, pair := range connectionArgPairs {
+		err = p.addOption(pair)
+		if err != nil {
+			return err
+		}
+	}
+
+	err = p.setDefaultAuthParams(extractedDatabase.db)
+	if err != nil {
+		return err
+	}
+
+	err = p.validateAuth()
+	if err != nil {
+		return err
+	}
+
+	// Check for invalid write concern (i.e. w=0 and j=true)
+	if p.WNumberSet && p.WNumber == 0 && p.JSet && p.J {
+		return writeconcern.ErrInconsistent
+	}
+
+	// If WTimeout was set from manual options passed in, set WTImeoutSet to true.
+	if p.WTimeoutSetFromOption {
+		p.WTimeoutSet = true
+	}
+
+	return nil
+}
+
+func (p *parser) setDefaultAuthParams(dbName string) error {
+	switch strings.ToLower(p.AuthMechanism) {
+	case "plain":
+		if p.AuthSource == "" {
+			p.AuthSource = dbName
+			if p.AuthSource == "" {
+				p.AuthSource = "$external"
+			}
+		}
+	case "gssapi":
+		if p.AuthMechanismProperties == nil {
+			p.AuthMechanismProperties = map[string]string{
+				"SERVICE_NAME": "mongodb",
+			}
+		} else if v, ok := p.AuthMechanismProperties["SERVICE_NAME"]; !ok || v == "" {
+			p.AuthMechanismProperties["SERVICE_NAME"] = "mongodb"
+		}
+		fallthrough
+	case "mongodb-x509":
+		if p.AuthSource == "" {
+			p.AuthSource = "$external"
+		} else if p.AuthSource != "$external" {
+			return fmt.Errorf("auth source must be $external")
+		}
+	case "mongodb-cr":
+		fallthrough
+	case "scram-sha-1":
+		fallthrough
+	case "scram-sha-256":
+		if p.AuthSource == "" {
+			p.AuthSource = dbName
+			if p.AuthSource == "" {
+				p.AuthSource = "admin"
+			}
+		}
+	case "":
+		if p.AuthSource == "" {
+			p.AuthSource = dbName
+			if p.AuthSource == "" {
+				p.AuthSource = "admin"
+			}
+		}
+	default:
+		return fmt.Errorf("invalid auth mechanism")
+	}
+	return nil
+}
+
+func (p *parser) validateAuth() error {
+	switch strings.ToLower(p.AuthMechanism) {
+	case "mongodb-cr":
+		if p.Username == "" {
+			return fmt.Errorf("username required for MONGO-CR")
+		}
+		if p.Password == "" {
+			return fmt.Errorf("password required for MONGO-CR")
+		}
+		if p.AuthMechanismProperties != nil {
+			return fmt.Errorf("MONGO-CR cannot have mechanism properties")
+		}
+	case "mongodb-x509":
+		if p.Password != "" {
+			return fmt.Errorf("password cannot be specified for MONGO-X509")
+		}
+		if p.AuthMechanismProperties != nil {
+			return fmt.Errorf("MONGO-X509 cannot have mechanism properties")
+		}
+	case "gssapi":
+		if p.Username == "" {
+			return fmt.Errorf("username required for GSSAPI")
+		}
+		for k := range p.AuthMechanismProperties {
+			if k != "SERVICE_NAME" && k != "CANONICALIZE_HOST_NAME" && k != "SERVICE_REALM" {
+				return fmt.Errorf("invalid auth property for GSSAPI")
+			}
+		}
+	case "plain":
+		if p.Username == "" {
+			return fmt.Errorf("username required for PLAIN")
+		}
+		if p.Password == "" {
+			return fmt.Errorf("password required for PLAIN")
+		}
+		if p.AuthMechanismProperties != nil {
+			return fmt.Errorf("PLAIN cannot have mechanism properties")
+		}
+	case "scram-sha-1":
+		if p.Username == "" {
+			return fmt.Errorf("username required for SCRAM-SHA-1")
+		}
+		if p.Password == "" {
+			return fmt.Errorf("password required for SCRAM-SHA-1")
+		}
+		if p.AuthMechanismProperties != nil {
+			return fmt.Errorf("SCRAM-SHA-1 cannot have mechanism properties")
+		}
+	case "scram-sha-256":
+		if p.Username == "" {
+			return fmt.Errorf("username required for SCRAM-SHA-256")
+		}
+		if p.Password == "" {
+			return fmt.Errorf("password required for SCRAM-SHA-256")
+		}
+		if p.AuthMechanismProperties != nil {
+			return fmt.Errorf("SCRAM-SHA-256 cannot have mechanism properties")
+		}
+	case "":
+	default:
+		return fmt.Errorf("invalid auth mechanism")
+	}
+	return nil
+}
+
+func fetchSeedlistFromSRV(host string) ([]string, error) {
+	var err error
+
+	_, _, err = net.SplitHostPort(host)
+
+	if err == nil {
+		// we were able to successfully extract a port from the host,
+		// but should not be able to when using SRV
+		return nil, fmt.Errorf("URI with srv must not include a port number")
+	}
+
+	_, addresses, err := net.LookupSRV("mongodb", "tcp", host)
+	if err != nil {
+		return nil, err
+	}
+	parsedHosts := make([]string, len(addresses))
+	for i, address := range addresses {
+		trimmedAddressTarget := strings.TrimSuffix(address.Target, ".")
+		err := validateSRVResult(trimmedAddressTarget, host)
+		if err != nil {
+			return nil, err
+		}
+		parsedHosts[i] = fmt.Sprintf("%s:%d", trimmedAddressTarget, address.Port)
+	}
+
+	return parsedHosts, nil
+}
+
+func (p *parser) addHost(host string) error {
+	if host == "" {
+		return nil
+	}
+	host, err := url.QueryUnescape(host)
+	if err != nil {
+		return internal.WrapErrorf(err, "invalid host \"%s\"", host)
+	}
+
+	_, port, err := net.SplitHostPort(host)
+	// this is unfortunate that SplitHostPort actually requires
+	// a port to exist.
+	if err != nil {
+		if addrError, ok := err.(*net.AddrError); !ok || addrError.Err != "missing port in address" {
+			return err
+		}
+	}
+
+	if port != "" {
+		d, err := strconv.Atoi(port)
+		if err != nil {
+			return internal.WrapErrorf(err, "port must be an integer")
+		}
+		if d <= 0 || d >= 65536 {
+			return fmt.Errorf("port must be in the range [1, 65535]")
+		}
+	}
+	p.Hosts = append(p.Hosts, host)
+	return nil
+}
+
+func (p *parser) addOption(pair string) error {
+	kv := strings.SplitN(pair, "=", 2)
+	if len(kv) != 2 || kv[0] == "" {
+		return fmt.Errorf("invalid option")
+	}
+
+	key, err := url.QueryUnescape(kv[0])
+	if err != nil {
+		return internal.WrapErrorf(err, "invalid option key \"%s\"", kv[0])
+	}
+
+	value, err := url.QueryUnescape(kv[1])
+	if err != nil {
+		return internal.WrapErrorf(err, "invalid option value \"%s\"", kv[1])
+	}
+
+	lowerKey := strings.ToLower(key)
+	switch lowerKey {
+	case "appname":
+		p.AppName = value
+	case "authmechanism":
+		p.AuthMechanism = value
+	case "authmechanismproperties":
+		p.AuthMechanismProperties = make(map[string]string)
+		pairs := strings.Split(value, ",")
+		for _, pair := range pairs {
+			kv := strings.SplitN(pair, ":", 2)
+			if len(kv) != 2 || kv[0] == "" {
+				return fmt.Errorf("invalid authMechanism property")
+			}
+			p.AuthMechanismProperties[kv[0]] = kv[1]
+		}
+	case "authsource":
+		p.AuthSource = value
+	case "compressors":
+		compressors := strings.Split(value, ",")
+		if len(compressors) < 1 {
+			return fmt.Errorf("must have at least 1 compressor")
+		}
+		p.Compressors = compressors
+	case "connect":
+		switch strings.ToLower(value) {
+		case "automatic":
+		case "direct":
+			p.Connect = SingleConnect
+		default:
+			return fmt.Errorf("invalid 'connect' value: %s", value)
+		}
+
+		p.ConnectSet = true
+	case "connecttimeoutms":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.ConnectTimeout = time.Duration(n) * time.Millisecond
+		p.ConnectTimeoutSet = true
+	case "heartbeatintervalms", "heartbeatfrequencyms":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.HeartbeatInterval = time.Duration(n) * time.Millisecond
+		p.HeartbeatIntervalSet = true
+	case "journal":
+		switch value {
+		case "true":
+			p.J = true
+		case "false":
+			p.J = false
+		default:
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+
+		p.JSet = true
+	case "localthresholdms":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.LocalThreshold = time.Duration(n) * time.Millisecond
+		p.LocalThresholdSet = true
+	case "maxidletimems":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.MaxConnIdleTime = time.Duration(n) * time.Millisecond
+		p.MaxConnIdleTimeSet = true
+	case "maxpoolsize":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.MaxPoolSize = uint16(n)
+		p.MaxPoolSizeSet = true
+	case "readconcernlevel":
+		p.ReadConcernLevel = value
+	case "readpreference":
+		p.ReadPreference = value
+	case "readpreferencetags":
+		tags := make(map[string]string)
+		items := strings.Split(value, ",")
+		for _, item := range items {
+			parts := strings.Split(item, ":")
+			if len(parts) != 2 {
+				return fmt.Errorf("invalid value for %s: %s", key, value)
+			}
+			tags[parts[0]] = parts[1]
+		}
+		p.ReadPreferenceTagSets = append(p.ReadPreferenceTagSets, tags)
+	case "maxstaleness":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.MaxStaleness = time.Duration(n) * time.Second
+		p.MaxStalenessSet = true
+	case "replicaset":
+		p.ReplicaSet = value
+	case "retrywrites":
+		p.RetryWrites = value == "true"
+		p.RetryWritesSet = true
+	case "serverselectiontimeoutms":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.ServerSelectionTimeout = time.Duration(n) * time.Millisecond
+		p.ServerSelectionTimeoutSet = true
+	case "sockettimeoutms":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.SocketTimeout = time.Duration(n) * time.Millisecond
+		p.SocketTimeoutSet = true
+	case "ssl":
+		switch value {
+		case "true":
+			p.SSL = true
+		case "false":
+			p.SSL = false
+		default:
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+
+		p.SSLSet = true
+	case "sslclientcertificatekeyfile":
+		p.SSL = true
+		p.SSLSet = true
+		p.SSLClientCertificateKeyFile = value
+		p.SSLClientCertificateKeyFileSet = true
+	case "sslclientcertificatekeypassword":
+		p.SSLClientCertificateKeyPassword = func() string { return value }
+		p.SSLClientCertificateKeyPasswordSet = true
+	case "sslinsecure":
+		switch value {
+		case "true":
+			p.SSLInsecure = true
+		case "false":
+			p.SSLInsecure = false
+		default:
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+
+		p.SSLInsecureSet = true
+	case "sslcertificateauthorityfile":
+		p.SSL = true
+		p.SSLSet = true
+		p.SSLCaFile = value
+		p.SSLCaFileSet = true
+	case "w":
+		if w, err := strconv.Atoi(value); err == nil {
+			if w < 0 {
+				return fmt.Errorf("invalid value for %s: %s", key, value)
+			}
+
+			p.WNumber = w
+			p.WNumberSet = true
+			p.WString = ""
+			break
+		}
+
+		p.WString = value
+		p.WNumberSet = false
+
+	case "wtimeoutms":
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.WTimeout = time.Duration(n) * time.Millisecond
+		p.WTimeoutSet = true
+	case "wtimeout":
+		// Defer to wtimeoutms, but not to a manually-set option.
+		if p.WTimeoutSet {
+			break
+		}
+		n, err := strconv.Atoi(value)
+		if err != nil || n < 0 {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+		p.WTimeout = time.Duration(n) * time.Millisecond
+	case "zlibcompressionlevel":
+		level, err := strconv.Atoi(value)
+		if err != nil || (level < -1 || level > 9) {
+			return fmt.Errorf("invalid value for %s: %s", key, value)
+		}
+
+		if level == -1 {
+			level = wiremessage.DefaultZlibLevel
+		}
+		p.ZlibLevel = level
+	default:
+		if p.UnknownOptions == nil {
+			p.UnknownOptions = make(map[string][]string)
+		}
+		p.UnknownOptions[lowerKey] = append(p.UnknownOptions[lowerKey], value)
+	}
+
+	if p.Options == nil {
+		p.Options = make(map[string][]string)
+	}
+	p.Options[lowerKey] = append(p.Options[lowerKey], value)
+
+	return nil
+}
+
+func validateSRVResult(recordFromSRV, inputHostName string) error {
+	separatedInputDomain := strings.Split(inputHostName, ".")
+	separatedRecord := strings.Split(recordFromSRV, ".")
+	if len(separatedRecord) < 2 {
+		return errors.New("DNS name must contain at least 2 labels")
+	}
+	if len(separatedRecord) < len(separatedInputDomain) {
+		return errors.New("Domain suffix from SRV record not matched input domain")
+	}
+
+	inputDomainSuffix := separatedInputDomain[1:]
+	domainSuffixOffset := len(separatedRecord) - (len(separatedInputDomain) - 1)
+
+	recordDomainSuffix := separatedRecord[domainSuffixOffset:]
+	for ix, label := range inputDomainSuffix {
+		if label != recordDomainSuffix[ix] {
+			return errors.New("Domain suffix from SRV record not matched input domain")
+		}
+	}
+	return nil
+}
+
+var allowedTXTOptions = map[string]struct{}{
+	"authsource": {},
+	"replicaset": {},
+}
+
+func validateTXTResult(paramsFromTXT []string) error {
+	for _, param := range paramsFromTXT {
+		kv := strings.SplitN(param, "=", 2)
+		if len(kv) != 2 {
+			return errors.New("Invalid TXT record")
+		}
+		key := strings.ToLower(kv[0])
+		if _, ok := allowedTXTOptions[key]; !ok {
+			return fmt.Errorf("Cannot specify option '%s' in TXT record", kv[0])
+		}
+	}
+	return nil
+}
+
+func extractQueryArgsFromURI(uri string) ([]string, error) {
+	if len(uri) == 0 {
+		return nil, nil
+	}
+
+	if uri[0] != '?' {
+		return nil, errors.New("must have a ? separator between path and query")
+	}
+
+	uri = uri[1:]
+	if len(uri) == 0 {
+		return nil, nil
+	}
+	return strings.FieldsFunc(uri, func(r rune) bool { return r == ';' || r == '&' }), nil
+
+}
+
+type extractedDatabase struct {
+	uri string
+	db  string
+}
+
+// extractDatabaseFromURI is a helper function to retrieve information about
+// the database from the passed in URI. It accepts as an argument the currently
+// parsed URI and returns the remainder of the uri, the database it found,
+// and any error it encounters while parsing.
+func extractDatabaseFromURI(uri string) (extractedDatabase, error) {
+	if len(uri) == 0 {
+		return extractedDatabase{}, nil
+	}
+
+	if uri[0] != '/' {
+		return extractedDatabase{}, errors.New("must have a / separator between hosts and path")
+	}
+
+	uri = uri[1:]
+	if len(uri) == 0 {
+		return extractedDatabase{}, nil
+	}
+
+	database := uri
+	if idx := strings.IndexRune(uri, '?'); idx != -1 {
+		database = uri[:idx]
+	}
+
+	escapedDatabase, err := url.QueryUnescape(database)
+	if err != nil {
+		return extractedDatabase{}, internal.WrapErrorf(err, "invalid database \"%s\"", database)
+	}
+
+	uri = uri[len(database):]
+
+	return extractedDatabase{
+		uri: uri,
+		db:  escapedDatabase,
+	}, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/description.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/description.go
new file mode 100644
index 0000000..758b112
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/description.go
@@ -0,0 +1,10 @@
+// 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 description
+
+// Unknown is an unknown server or topology kind.
+const Unknown = 0
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/feature.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/feature.go
new file mode 100644
index 0000000..f0236c0
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/feature.go
@@ -0,0 +1,36 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package description
+
+import (
+	"fmt"
+)
+
+// MaxStalenessSupported returns an error if the given server version
+// does not support max staleness.
+func MaxStalenessSupported(wireVersion *VersionRange) error {
+	if wireVersion != nil && wireVersion.Max < 5 {
+		return fmt.Errorf("max staleness is only supported for servers 3.4 or newer")
+	}
+
+	return nil
+}
+
+// ScramSHA1Supported returns an error if the given server version
+// does not support scram-sha-1.
+func ScramSHA1Supported(wireVersion *VersionRange) error {
+	if wireVersion != nil && wireVersion.Max < 3 {
+		return fmt.Errorf("SCRAM-SHA-1 is only supported for servers 3.0 or newer")
+	}
+
+	return nil
+}
+
+// SessionsSupported returns true of the given server version indicates that it supports sessions.
+func SessionsSupported(wireVersion *VersionRange) bool {
+	return wireVersion != nil && wireVersion.Max >= 6
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server.go
new file mode 100644
index 0000000..d6857ce
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server.go
@@ -0,0 +1,144 @@
+// 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 description
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson/primitive"
+	"github.com/mongodb/mongo-go-driver/tag"
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// UnsetRTT is the unset value for a round trip time.
+const UnsetRTT = -1 * time.Millisecond
+
+// SelectedServer represents a selected server that is a member of a topology.
+type SelectedServer struct {
+	Server
+	Kind TopologyKind
+}
+
+// Server represents a description of a server. This is created from an isMaster
+// command.
+type Server struct {
+	Addr address.Address
+
+	AverageRTT            time.Duration
+	AverageRTTSet         bool
+	Compression           []string // compression methods returned by server
+	CanonicalAddr         address.Address
+	ElectionID            primitive.ObjectID
+	HeartbeatInterval     time.Duration
+	LastError             error
+	LastUpdateTime        time.Time
+	LastWriteTime         time.Time
+	MaxBatchCount         uint32
+	MaxDocumentSize       uint32
+	MaxMessageSize        uint32
+	Members               []address.Address
+	ReadOnly              bool
+	SessionTimeoutMinutes uint32
+	SetName               string
+	SetVersion            uint32
+	Tags                  tag.Set
+	Kind                  ServerKind
+	WireVersion           *VersionRange
+
+	SaslSupportedMechs []string // user-specific from server handshake
+}
+
+// NewServer creates a new server description from the given parameters.
+func NewServer(addr address.Address, isMaster result.IsMaster) Server {
+	i := Server{
+		Addr: addr,
+
+		CanonicalAddr:         address.Address(isMaster.Me).Canonicalize(),
+		Compression:           isMaster.Compression,
+		ElectionID:            isMaster.ElectionID,
+		LastUpdateTime:        time.Now().UTC(),
+		LastWriteTime:         isMaster.LastWriteTimestamp,
+		MaxBatchCount:         isMaster.MaxWriteBatchSize,
+		MaxDocumentSize:       isMaster.MaxBSONObjectSize,
+		MaxMessageSize:        isMaster.MaxMessageSizeBytes,
+		SaslSupportedMechs:    isMaster.SaslSupportedMechs,
+		SessionTimeoutMinutes: isMaster.LogicalSessionTimeoutMinutes,
+		SetName:               isMaster.SetName,
+		SetVersion:            isMaster.SetVersion,
+		Tags:                  tag.NewTagSetFromMap(isMaster.Tags),
+	}
+
+	if i.CanonicalAddr == "" {
+		i.CanonicalAddr = addr
+	}
+
+	if isMaster.OK != 1 {
+		i.LastError = fmt.Errorf("not ok")
+		return i
+	}
+
+	for _, host := range isMaster.Hosts {
+		i.Members = append(i.Members, address.Address(host).Canonicalize())
+	}
+
+	for _, passive := range isMaster.Passives {
+		i.Members = append(i.Members, address.Address(passive).Canonicalize())
+	}
+
+	for _, arbiter := range isMaster.Arbiters {
+		i.Members = append(i.Members, address.Address(arbiter).Canonicalize())
+	}
+
+	i.Kind = Standalone
+
+	if isMaster.IsReplicaSet {
+		i.Kind = RSGhost
+	} else if isMaster.SetName != "" {
+		if isMaster.IsMaster {
+			i.Kind = RSPrimary
+		} else if isMaster.Hidden {
+			i.Kind = RSMember
+		} else if isMaster.Secondary {
+			i.Kind = RSSecondary
+		} else if isMaster.ArbiterOnly {
+			i.Kind = RSArbiter
+		} else {
+			i.Kind = RSMember
+		}
+	} else if isMaster.Msg == "isdbgrid" {
+		i.Kind = Mongos
+	}
+
+	i.WireVersion = &VersionRange{
+		Min: isMaster.MinWireVersion,
+		Max: isMaster.MaxWireVersion,
+	}
+
+	return i
+}
+
+// SetAverageRTT sets the average round trip time for this server description.
+func (s Server) SetAverageRTT(rtt time.Duration) Server {
+	s.AverageRTT = rtt
+	if rtt == UnsetRTT {
+		s.AverageRTTSet = false
+	} else {
+		s.AverageRTTSet = true
+	}
+
+	return s
+}
+
+// DataBearing returns true if the server is a data bearing server.
+func (s Server) DataBearing() bool {
+	return s.Kind == RSPrimary ||
+		s.Kind == RSSecondary ||
+		s.Kind == Mongos ||
+		s.Kind == Standalone
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server_kind.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server_kind.go
new file mode 100644
index 0000000..657791b
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server_kind.go
@@ -0,0 +1,43 @@
+// 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 description
+
+// ServerKind represents the type of a server.
+type ServerKind uint32
+
+// These constants are the possible types of servers.
+const (
+	Standalone  ServerKind = 1
+	RSMember    ServerKind = 2
+	RSPrimary   ServerKind = 4 + RSMember
+	RSSecondary ServerKind = 8 + RSMember
+	RSArbiter   ServerKind = 16 + RSMember
+	RSGhost     ServerKind = 32 + RSMember
+	Mongos      ServerKind = 256
+)
+
+// String implements the fmt.Stringer interface.
+func (kind ServerKind) String() string {
+	switch kind {
+	case Standalone:
+		return "Standalone"
+	case RSMember:
+		return "RSOther"
+	case RSPrimary:
+		return "RSPrimary"
+	case RSSecondary:
+		return "RSSecondary"
+	case RSArbiter:
+		return "RSArbiter"
+	case RSGhost:
+		return "RSGhost"
+	case Mongos:
+		return "Mongos"
+	}
+
+	return "Unknown"
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server_selector.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server_selector.go
new file mode 100644
index 0000000..9c31b6e
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/server_selector.go
@@ -0,0 +1,279 @@
+// 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 description
+
+import (
+	"fmt"
+	"math"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/tag"
+)
+
+// ServerSelector is an interface implemented by types that can select a server given a
+// topology description.
+type ServerSelector interface {
+	SelectServer(Topology, []Server) ([]Server, error)
+}
+
+// ServerSelectorFunc is a function that can be used as a ServerSelector.
+type ServerSelectorFunc func(Topology, []Server) ([]Server, error)
+
+// SelectServer implements the ServerSelector interface.
+func (ssf ServerSelectorFunc) SelectServer(t Topology, s []Server) ([]Server, error) {
+	return ssf(t, s)
+}
+
+type compositeSelector struct {
+	selectors []ServerSelector
+}
+
+// CompositeSelector combines multiple selectors into a single selector.
+func CompositeSelector(selectors []ServerSelector) ServerSelector {
+	return &compositeSelector{selectors: selectors}
+}
+
+func (cs *compositeSelector) SelectServer(t Topology, candidates []Server) ([]Server, error) {
+	var err error
+	for _, sel := range cs.selectors {
+		candidates, err = sel.SelectServer(t, candidates)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return candidates, nil
+}
+
+type latencySelector struct {
+	latency time.Duration
+}
+
+// LatencySelector creates a ServerSelector which selects servers based on their latency.
+func LatencySelector(latency time.Duration) ServerSelector {
+	return &latencySelector{latency: latency}
+}
+
+func (ls *latencySelector) SelectServer(t Topology, candidates []Server) ([]Server, error) {
+	if ls.latency < 0 {
+		return candidates, nil
+	}
+
+	switch len(candidates) {
+	case 0, 1:
+		return candidates, nil
+	default:
+		min := time.Duration(math.MaxInt64)
+		for _, candidate := range candidates {
+			if candidate.AverageRTTSet {
+				if candidate.AverageRTT < min {
+					min = candidate.AverageRTT
+				}
+			}
+		}
+
+		if min == math.MaxInt64 {
+			return candidates, nil
+		}
+
+		max := min + ls.latency
+
+		var result []Server
+		for _, candidate := range candidates {
+			if candidate.AverageRTTSet {
+				if candidate.AverageRTT <= max {
+					result = append(result, candidate)
+				}
+			}
+		}
+
+		return result, nil
+	}
+}
+
+// WriteSelector selects all the writable servers.
+func WriteSelector() ServerSelector {
+	return ServerSelectorFunc(func(t Topology, candidates []Server) ([]Server, error) {
+		switch t.Kind {
+		case Single:
+			return candidates, nil
+		default:
+			result := []Server{}
+			for _, candidate := range candidates {
+				switch candidate.Kind {
+				case Mongos, RSPrimary, Standalone:
+					result = append(result, candidate)
+				}
+			}
+			return result, nil
+		}
+	})
+}
+
+// ReadPrefSelector selects servers based on the provided read preference.
+func ReadPrefSelector(rp *readpref.ReadPref) ServerSelector {
+	return ServerSelectorFunc(func(t Topology, candidates []Server) ([]Server, error) {
+		if _, set := rp.MaxStaleness(); set {
+			for _, s := range candidates {
+				if s.Kind != Unknown {
+					if err := MaxStalenessSupported(s.WireVersion); err != nil {
+						return nil, err
+					}
+				}
+			}
+		}
+
+		switch t.Kind {
+		case Single:
+			return candidates, nil
+		case ReplicaSetNoPrimary, ReplicaSetWithPrimary:
+			return selectForReplicaSet(rp, t, candidates)
+		case Sharded:
+			return selectByKind(candidates, Mongos), nil
+		}
+
+		return nil, nil
+	})
+}
+
+func selectForReplicaSet(rp *readpref.ReadPref, t Topology, candidates []Server) ([]Server, error) {
+	if err := verifyMaxStaleness(rp, t); err != nil {
+		return nil, err
+	}
+
+	switch rp.Mode() {
+	case readpref.PrimaryMode:
+		return selectByKind(candidates, RSPrimary), nil
+	case readpref.PrimaryPreferredMode:
+		selected := selectByKind(candidates, RSPrimary)
+
+		if len(selected) == 0 {
+			selected = selectSecondaries(rp, candidates)
+			return selectByTagSet(selected, rp.TagSets()), nil
+		}
+
+		return selected, nil
+	case readpref.SecondaryPreferredMode:
+		selected := selectSecondaries(rp, candidates)
+		selected = selectByTagSet(selected, rp.TagSets())
+		if len(selected) > 0 {
+			return selected, nil
+		}
+		return selectByKind(candidates, RSPrimary), nil
+	case readpref.SecondaryMode:
+		selected := selectSecondaries(rp, candidates)
+		return selectByTagSet(selected, rp.TagSets()), nil
+	case readpref.NearestMode:
+		selected := selectByKind(candidates, RSPrimary)
+		selected = append(selected, selectSecondaries(rp, candidates)...)
+		return selectByTagSet(selected, rp.TagSets()), nil
+	}
+
+	return nil, fmt.Errorf("unsupported mode: %d", rp.Mode())
+}
+
+func selectSecondaries(rp *readpref.ReadPref, candidates []Server) []Server {
+	secondaries := selectByKind(candidates, RSSecondary)
+	if len(secondaries) == 0 {
+		return secondaries
+	}
+	if maxStaleness, set := rp.MaxStaleness(); set {
+		primaries := selectByKind(candidates, RSPrimary)
+		if len(primaries) == 0 {
+			baseTime := secondaries[0].LastWriteTime
+			for i := 1; i < len(secondaries); i++ {
+				if secondaries[i].LastWriteTime.After(baseTime) {
+					baseTime = secondaries[i].LastWriteTime
+				}
+			}
+
+			var selected []Server
+			for _, secondary := range secondaries {
+				estimatedStaleness := baseTime.Sub(secondary.LastWriteTime) + secondary.HeartbeatInterval
+				if estimatedStaleness <= maxStaleness {
+					selected = append(selected, secondary)
+				}
+			}
+
+			return selected
+		}
+
+		primary := primaries[0]
+
+		var selected []Server
+		for _, secondary := range secondaries {
+			estimatedStaleness := secondary.LastUpdateTime.Sub(secondary.LastWriteTime) - primary.LastUpdateTime.Sub(primary.LastWriteTime) + secondary.HeartbeatInterval
+			if estimatedStaleness <= maxStaleness {
+				selected = append(selected, secondary)
+			}
+		}
+		return selected
+	}
+
+	return secondaries
+}
+
+func selectByTagSet(candidates []Server, tagSets []tag.Set) []Server {
+	if len(tagSets) == 0 {
+		return candidates
+	}
+
+	for _, ts := range tagSets {
+		var results []Server
+		for _, s := range candidates {
+			if len(s.Tags) > 0 && s.Tags.ContainsAll(ts) {
+				results = append(results, s)
+			}
+		}
+
+		if len(results) > 0 {
+			return results
+		}
+	}
+
+	return []Server{}
+}
+
+func selectByKind(candidates []Server, kind ServerKind) []Server {
+	var result []Server
+	for _, s := range candidates {
+		if s.Kind == kind {
+			result = append(result, s)
+		}
+	}
+
+	return result
+}
+
+func verifyMaxStaleness(rp *readpref.ReadPref, t Topology) error {
+	maxStaleness, set := rp.MaxStaleness()
+	if !set {
+		return nil
+	}
+
+	if maxStaleness < 90*time.Second {
+		return fmt.Errorf("max staleness (%s) must be greater than or equal to 90s", maxStaleness)
+	}
+
+	if len(t.Servers) < 1 {
+		// Maybe we should return an error here instead?
+		return nil
+	}
+
+	// we'll assume all candidates have the same heartbeat interval.
+	s := t.Servers[0]
+	idleWritePeriod := 10 * time.Second
+
+	if maxStaleness < s.HeartbeatInterval+idleWritePeriod {
+		return fmt.Errorf(
+			"max staleness (%s) must be greater than or equal to the heartbeat interval (%s) plus idle write period (%s)",
+			maxStaleness, s.HeartbeatInterval, idleWritePeriod,
+		)
+	}
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/topology.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/topology.go
new file mode 100644
index 0000000..caf447d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/topology.go
@@ -0,0 +1,89 @@
+// 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 description
+
+import (
+	"sort"
+	"strings"
+
+	"github.com/mongodb/mongo-go-driver/x/network/address"
+)
+
+// Topology represents a description of a mongodb topology
+type Topology struct {
+	Servers               []Server
+	Kind                  TopologyKind
+	SessionTimeoutMinutes uint32
+}
+
+// Server returns the server for the given address. Returns false if the server
+// could not be found.
+func (t Topology) Server(addr address.Address) (Server, bool) {
+	for _, server := range t.Servers {
+		if server.Addr.String() == addr.String() {
+			return server, true
+		}
+	}
+	return Server{}, false
+}
+
+// TopologyDiff is the difference between two different topology descriptions.
+type TopologyDiff struct {
+	Added   []Server
+	Removed []Server
+}
+
+// DiffTopology compares the two topology descriptions and returns the difference.
+func DiffTopology(old, new Topology) TopologyDiff {
+	var diff TopologyDiff
+
+	// TODO: do this without sorting...
+	oldServers := serverSorter(old.Servers)
+	newServers := serverSorter(new.Servers)
+
+	sort.Sort(oldServers)
+	sort.Sort(newServers)
+
+	i := 0
+	j := 0
+	for {
+		if i < len(oldServers) && j < len(newServers) {
+			comp := strings.Compare(oldServers[i].Addr.String(), newServers[j].Addr.String())
+			switch comp {
+			case 1:
+				//left is bigger than
+				diff.Added = append(diff.Added, newServers[j])
+				j++
+			case -1:
+				// right is bigger
+				diff.Removed = append(diff.Removed, oldServers[i])
+				i++
+			case 0:
+				i++
+				j++
+			}
+		} else if i < len(oldServers) {
+			diff.Removed = append(diff.Removed, oldServers[i])
+			i++
+		} else if j < len(newServers) {
+			diff.Added = append(diff.Added, newServers[j])
+			j++
+		} else {
+			break
+		}
+	}
+
+	return diff
+}
+
+type serverSorter []Server
+
+func (ss serverSorter) Len() int      { return len(ss) }
+func (ss serverSorter) Swap(i, j int) { ss[i], ss[j] = ss[j], ss[i] }
+func (ss serverSorter) Less(i, j int) bool {
+	return strings.Compare(ss[i].Addr.String(), ss[j].Addr.String()) < 0
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/topology_kind.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/topology_kind.go
new file mode 100644
index 0000000..69f8177
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/topology_kind.go
@@ -0,0 +1,37 @@
+// 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 description
+
+// TopologyKind represents a specific topology configuration.
+type TopologyKind uint32
+
+// These constants are the available topology configurations.
+const (
+	Single                TopologyKind = 1
+	ReplicaSet            TopologyKind = 2
+	ReplicaSetNoPrimary   TopologyKind = 4 + ReplicaSet
+	ReplicaSetWithPrimary TopologyKind = 8 + ReplicaSet
+	Sharded               TopologyKind = 256
+)
+
+// String implements the fmt.Stringer interface.
+func (kind TopologyKind) String() string {
+	switch kind {
+	case Single:
+		return "Single"
+	case ReplicaSet:
+		return "ReplicaSet"
+	case ReplicaSetNoPrimary:
+		return "ReplicaSetNoPrimary"
+	case ReplicaSetWithPrimary:
+		return "ReplicaSetWithPrimary"
+	case Sharded:
+		return "Sharded"
+	}
+
+	return "Unknown"
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/version.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/version.go
new file mode 100644
index 0000000..60cda4e
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/version.go
@@ -0,0 +1,44 @@
+// 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 description
+
+import "strconv"
+
+// Version represents a software version.
+type Version struct {
+	Desc  string
+	Parts []uint8
+}
+
+// AtLeast ensures that the version is at least as large as the "other" version.
+func (v Version) AtLeast(other ...uint8) bool {
+	for i := range other {
+		if i == len(v.Parts) {
+			return false
+		}
+		if v.Parts[i] < other[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// String provides the string represtation of the Version.
+func (v Version) String() string {
+	if v.Desc == "" {
+		var s string
+		for i, p := range v.Parts {
+			if i != 0 {
+				s += "."
+			}
+			s += strconv.Itoa(int(p))
+		}
+		return s
+	}
+
+	return v.Desc
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/description/version_range.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/version_range.go
new file mode 100644
index 0000000..984dff8
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/description/version_range.go
@@ -0,0 +1,31 @@
+// 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 description
+
+import "fmt"
+
+// VersionRange represents a range of versions.
+type VersionRange struct {
+	Min int32
+	Max int32
+}
+
+// NewVersionRange creates a new VersionRange given a min and a max.
+func NewVersionRange(min, max int32) VersionRange {
+	return VersionRange{Min: min, Max: max}
+}
+
+// Includes returns a bool indicating whether the supplied integer is included
+// in the range.
+func (vr VersionRange) Includes(v int32) bool {
+	return v >= vr.Min && v <= vr.Max
+}
+
+// String implements the fmt.Stringer interface.
+func (vr VersionRange) String() string {
+	return fmt.Sprintf("[%d, %d]", vr.Min, vr.Max)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/result/result.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/result/result.go
new file mode 100644
index 0000000..d317bb7
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/result/result.go
@@ -0,0 +1,173 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+// Package result contains the results from various operations.
+package result
+
+import (
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/primitive"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+)
+
+// Upsert contains the information for a single upsert.
+type Upsert struct {
+	Index int64       `bson:"index"`
+	ID    interface{} `bson:"_id"`
+}
+
+// Insert is a result from an Insert command.
+type Insert struct {
+	N                 int
+	WriteErrors       []WriteError       `bson:"writeErrors"`
+	WriteConcernError *WriteConcernError `bson:"writeConcernError"`
+}
+
+// StartSession is a result from a StartSession command.
+type StartSession struct {
+	ID bsonx.Doc `bson:"id"`
+}
+
+// EndSessions is a result from an EndSessions command.
+type EndSessions struct{}
+
+// Delete is a result from a Delete command.
+type Delete struct {
+	N                 int
+	WriteErrors       []WriteError       `bson:"writeErrors"`
+	WriteConcernError *WriteConcernError `bson:"writeConcernError"`
+}
+
+// Update is a result of an Update command.
+type Update struct {
+	MatchedCount      int64              `bson:"n"`
+	ModifiedCount     int64              `bson:"nModified"`
+	Upserted          []Upsert           `bson:"upserted"`
+	WriteErrors       []WriteError       `bson:"writeErrors"`
+	WriteConcernError *WriteConcernError `bson:"writeConcernError"`
+}
+
+// Distinct is a result from a Distinct command.
+type Distinct struct {
+	Values []interface{}
+}
+
+// FindAndModify is a result from a findAndModify command.
+type FindAndModify struct {
+	Value           bson.Raw
+	LastErrorObject struct {
+		UpdatedExisting bool
+		Upserted        interface{}
+	}
+}
+
+// WriteError is an error from a write operation that is not a write concern
+// error.
+type WriteError struct {
+	Index  int
+	Code   int
+	ErrMsg string
+}
+
+// WriteConcernError is an error related to a write concern.
+type WriteConcernError struct {
+	Code    int
+	ErrMsg  string
+	ErrInfo bson.Raw
+}
+
+// ListDatabases is the result from a listDatabases command.
+type ListDatabases struct {
+	Databases []struct {
+		Name       string
+		SizeOnDisk int64 `bson:"sizeOnDisk"`
+		Empty      bool
+	}
+	TotalSize int64 `bson:"totalSize"`
+}
+
+// IsMaster is a result of an IsMaster command.
+type IsMaster struct {
+	Arbiters                     []string           `bson:"arbiters,omitempty"`
+	ArbiterOnly                  bool               `bson:"arbiterOnly,omitempty"`
+	ClusterTime                  bson.Raw           `bson:"$clusterTime,omitempty"`
+	Compression                  []string           `bson:"compression,omitempty"`
+	ElectionID                   primitive.ObjectID `bson:"electionId,omitempty"`
+	Hidden                       bool               `bson:"hidden,omitempty"`
+	Hosts                        []string           `bson:"hosts,omitempty"`
+	IsMaster                     bool               `bson:"ismaster,omitempty"`
+	IsReplicaSet                 bool               `bson:"isreplicaset,omitempty"`
+	LastWriteTimestamp           time.Time          `bson:"lastWriteDate,omitempty"`
+	LogicalSessionTimeoutMinutes uint32             `bson:"logicalSessionTimeoutMinutes,omitempty"`
+	MaxBSONObjectSize            uint32             `bson:"maxBsonObjectSize,omitempty"`
+	MaxMessageSizeBytes          uint32             `bson:"maxMessageSizeBytes,omitempty"`
+	MaxWriteBatchSize            uint32             `bson:"maxWriteBatchSize,omitempty"`
+	Me                           string             `bson:"me,omitempty"`
+	MaxWireVersion               int32              `bson:"maxWireVersion,omitempty"`
+	MinWireVersion               int32              `bson:"minWireVersion,omitempty"`
+	Msg                          string             `bson:"msg,omitempty"`
+	OK                           int32              `bson:"ok"`
+	Passives                     []string           `bson:"passives,omitempty"`
+	ReadOnly                     bool               `bson:"readOnly,omitempty"`
+	SaslSupportedMechs           []string           `bson:"saslSupportedMechs,omitempty"`
+	Secondary                    bool               `bson:"secondary,omitempty"`
+	SetName                      string             `bson:"setName,omitempty"`
+	SetVersion                   uint32             `bson:"setVersion,omitempty"`
+	Tags                         map[string]string  `bson:"tags,omitempty"`
+}
+
+// BuildInfo is a result of a BuildInfo command.
+type BuildInfo struct {
+	OK           bool    `bson:"ok"`
+	GitVersion   string  `bson:"gitVersion,omitempty"`
+	Version      string  `bson:"version,omitempty"`
+	VersionArray []uint8 `bson:"versionArray,omitempty"`
+}
+
+// IsZero returns true if the BuildInfo is the zero value.
+func (bi BuildInfo) IsZero() bool {
+	if !bi.OK && bi.GitVersion == "" && bi.Version == "" && bi.VersionArray == nil {
+		return true
+	}
+
+	return false
+}
+
+// GetLastError is a result of a GetLastError command.
+type GetLastError struct {
+	ConnectionID uint32 `bson:"connectionId"`
+}
+
+// KillCursors is a result of a KillCursors command.
+type KillCursors struct {
+	CursorsKilled   []int64 `bson:"cursorsKilled"`
+	CursorsNotFound []int64 `bson:"cursorsNotFound"`
+	CursorsAlive    []int64 `bson:"cursorsAlive"`
+}
+
+// CreateIndexes is a result of a CreateIndexes command.
+type CreateIndexes struct {
+	CreatedCollectionAutomatically bool `bson:"createdCollectionAutomatically"`
+	IndexesBefore                  int  `bson:"numIndexesBefore"`
+	IndexesAfter                   int  `bson:"numIndexesAfter"`
+}
+
+// TransactionResult holds the result of committing or aborting a transaction.
+type TransactionResult struct {
+	WriteConcernError *WriteConcernError `bson:"writeConcernError"`
+}
+
+// BulkWrite holds the result of a bulk write operation.
+type BulkWrite struct {
+	InsertedCount int64
+	MatchedCount  int64
+	ModifiedCount int64
+	DeletedCount  int64
+	UpsertedCount int64
+	UpsertedIDs   map[int64]interface{}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/appenders.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/appenders.go
new file mode 100644
index 0000000..3d9f784
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/appenders.go
@@ -0,0 +1,20 @@
+// 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 wiremessage
+
+func appendInt32(b []byte, i int32) []byte {
+	return append(b, byte(i), byte(i>>8), byte(i>>16), byte(i>>24))
+}
+
+func appendCString(b []byte, str string) []byte {
+	b = append(b, str...)
+	return append(b, 0x00)
+}
+
+func appendInt64(b []byte, i int64) []byte {
+	return append(b, byte(i), byte(i>>8), byte(i>>16), byte(i>>24), byte(i>>32), byte(i>>40), byte(i>>48), byte(i>>56))
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/command.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/command.go
new file mode 100644
index 0000000..8c339a5
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/command.go
@@ -0,0 +1,49 @@
+// 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 wiremessage
+
+import "github.com/mongodb/mongo-go-driver/bson"
+
+// Command represents the OP_COMMAND message of the MongoDB wire protocol.
+type Command struct {
+	MsgHeader   Header
+	Database    string
+	CommandName string
+	Metadata    string
+	CommandArgs string
+	InputDocs   []bson.Raw
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (c Command) MarshalWireMessage() ([]byte, error) {
+	panic("not implemented")
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (c Command) ValidateWireMessage() error {
+	panic("not implemented")
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+func (c Command) AppendWireMessage([]byte) ([]byte, error) {
+	panic("not implemented")
+}
+
+// String implements the fmt.Stringer interface.
+func (c Command) String() string {
+	panic("not implemented")
+}
+
+// Len implements the WireMessage interface.
+func (c Command) Len() int {
+	panic("not implemented")
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (c *Command) UnmarshalWireMessage([]byte) error {
+	panic("not implemented")
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/command_reply.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/command_reply.go
new file mode 100644
index 0000000..d5773d6
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/command_reply.go
@@ -0,0 +1,47 @@
+// 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 wiremessage
+
+import "github.com/mongodb/mongo-go-driver/bson"
+
+// CommandReply represents the OP_COMMANDREPLY message of the MongoDB wire protocol.
+type CommandReply struct {
+	MsgHeader    Header
+	Metadata     bson.Raw
+	CommandReply bson.Raw
+	OutputDocs   []bson.Raw
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (cr CommandReply) MarshalWireMessage() ([]byte, error) {
+	panic("not implemented")
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (cr CommandReply) ValidateWireMessage() error {
+	panic("not implemented")
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+func (cr CommandReply) AppendWireMessage([]byte) ([]byte, error) {
+	panic("not implemented")
+}
+
+// String implements the fmt.Stringer interface.
+func (cr CommandReply) String() string {
+	panic("not implemented")
+}
+
+// Len implements the WireMessage interface.
+func (cr CommandReply) Len() int {
+	panic("not implemented")
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (cr *CommandReply) UnmarshalWireMessage([]byte) error {
+	panic("not implemented")
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/compressed.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/compressed.go
new file mode 100644
index 0000000..f8f3884
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/compressed.go
@@ -0,0 +1,110 @@
+// 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 wiremessage
+
+import (
+	"errors"
+	"fmt"
+)
+
+// Compressed represents the OP_COMPRESSED message of the MongoDB wire protocol.
+type Compressed struct {
+	MsgHeader         Header
+	OriginalOpCode    OpCode
+	UncompressedSize  int32
+	CompressorID      CompressorID
+	CompressedMessage []byte
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (c Compressed) MarshalWireMessage() ([]byte, error) {
+	b := make([]byte, 0, c.Len())
+	return c.AppendWireMessage(b)
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (c Compressed) ValidateWireMessage() error {
+	if int(c.MsgHeader.MessageLength) != c.Len() {
+		return errors.New("incorrect header: message length is not correct")
+	}
+
+	if c.MsgHeader.OpCode != OpCompressed {
+		return errors.New("incorrect header: opcode is not OpCompressed")
+	}
+
+	if c.OriginalOpCode != c.MsgHeader.OpCode {
+		return errors.New("incorrect header: original opcode does not match opcode in message header")
+	}
+	return nil
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+//
+// AppendWireMessage will set the MessageLength property of MsgHeader if it is 0. It will also set the OpCode to
+// OpCompressed if the OpCode is 0. If either of these properties are non-zero and not correct, this method will return
+// both the []byte with the wire message appended to it and an invalid header error.
+func (c Compressed) AppendWireMessage(b []byte) ([]byte, error) {
+	err := c.MsgHeader.SetDefaults(c.Len(), OpCompressed)
+
+	b = c.MsgHeader.AppendHeader(b)
+	b = appendInt32(b, int32(c.OriginalOpCode))
+	b = appendInt32(b, c.UncompressedSize)
+	b = append(b, byte(c.CompressorID))
+	b = append(b, c.CompressedMessage...)
+
+	return b, err
+}
+
+// String implements the fmt.Stringer interface.
+func (c Compressed) String() string {
+	return fmt.Sprintf(
+		`OP_COMPRESSED{MsgHeader: %s, Uncompressed Size: %d, CompressorId: %d, Compressed message: %s}`,
+		c.MsgHeader, c.UncompressedSize, c.CompressorID, c.CompressedMessage,
+	)
+}
+
+// Len implements the WireMessage interface.
+func (c Compressed) Len() int {
+	// Header + OpCode + UncompressedSize + CompressorId + CompressedMessage
+	return 16 + 4 + 4 + 1 + len(c.CompressedMessage)
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (c *Compressed) UnmarshalWireMessage(b []byte) error {
+	var err error
+	c.MsgHeader, err = ReadHeader(b, 0)
+	if err != nil {
+		return err
+	}
+
+	if len(b) < int(c.MsgHeader.MessageLength) {
+		return Error{Type: ErrOpCompressed, Message: "[]byte too small"}
+	}
+
+	c.OriginalOpCode = OpCode(readInt32(b, 16)) // skip first 16 for header
+	c.UncompressedSize = readInt32(b, 20)
+	c.CompressorID = CompressorID(b[24])
+
+	// messageLength - Header - OpCode - UncompressedSize - CompressorId
+	msgLen := c.MsgHeader.MessageLength - 16 - 4 - 4 - 1
+	c.CompressedMessage = b[25 : 25+msgLen]
+
+	return nil
+}
+
+// CompressorID is the ID for each type of Compressor.
+type CompressorID uint8
+
+// These constants represent the individual compressor IDs for an OP_COMPRESSED.
+const (
+	CompressorNoOp CompressorID = iota
+	CompressorSnappy
+	CompressorZLib
+)
+
+// DefaultZlibLevel is the default level for zlib compression
+const DefaultZlibLevel = 6
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/delete.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/delete.go
new file mode 100644
index 0000000..0a502da
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/delete.go
@@ -0,0 +1,55 @@
+// 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 wiremessage
+
+import "github.com/mongodb/mongo-go-driver/bson"
+
+// Delete represents the OP_DELETE message of the MongoDB wire protocol.
+type Delete struct {
+	MsgHeader          Header
+	FullCollectionName string
+	Flags              DeleteFlag
+	Selector           bson.Raw
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (d Delete) MarshalWireMessage() ([]byte, error) {
+	panic("not implemented")
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (d Delete) ValidateWireMessage() error {
+	panic("not implemented")
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+func (d Delete) AppendWireMessage([]byte) ([]byte, error) {
+	panic("not implemented")
+}
+
+// String implements the fmt.Stringer interface.
+func (d Delete) String() string {
+	panic("not implemented")
+}
+
+// Len implements the WireMessage interface.
+func (d Delete) Len() int {
+	panic("not implemented")
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (d *Delete) UnmarshalWireMessage([]byte) error {
+	panic("not implemented")
+}
+
+// DeleteFlag represents the flags on an OP_DELETE message.
+type DeleteFlag int32
+
+// These constants represent the individual flags on an OP_DELETE message.
+const (
+	SingleRemove DeleteFlag = 1 << iota
+)
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/get_more.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/get_more.go
new file mode 100644
index 0000000..f197113
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/get_more.go
@@ -0,0 +1,103 @@
+// 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 wiremessage
+
+import (
+	"errors"
+	"fmt"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"strings"
+)
+
+// GetMore represents the OP_GET_MORE message of the MongoDB wire protocol.
+type GetMore struct {
+	MsgHeader          Header
+	Zero               int32
+	FullCollectionName string
+	NumberToReturn     int32
+	CursorID           int64
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (gm GetMore) MarshalWireMessage() ([]byte, error) {
+	b := make([]byte, 0, gm.Len())
+	return gm.AppendWireMessage(b)
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (gm GetMore) ValidateWireMessage() error {
+	if int(gm.MsgHeader.MessageLength) != gm.Len() {
+		return errors.New("incorrect header: message length is not correct")
+	}
+	if gm.MsgHeader.OpCode != OpGetMore {
+		return errors.New("incorrect header: op code is not OpGetMore")
+	}
+	if strings.Index(gm.FullCollectionName, ".") == -1 {
+		return errors.New("incorrect header: collection name does not contain a dot")
+	}
+
+	return nil
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+//
+// AppendWireMessage will set the MessageLength property of the MsgHeader
+// if it is zero. It will also set the OpCode to OpGetMore if the OpCode is
+// zero. If either of these properties are non-zero and not correct, this
+// method will return both the []byte with the wire message appended to it
+// and an invalid header error.
+func (gm GetMore) AppendWireMessage(b []byte) ([]byte, error) {
+	var err error
+	err = gm.MsgHeader.SetDefaults(gm.Len(), OpGetMore)
+
+	b = gm.MsgHeader.AppendHeader(b)
+	b = appendInt32(b, gm.Zero)
+	b = appendCString(b, gm.FullCollectionName)
+	b = appendInt32(b, gm.NumberToReturn)
+	b = appendInt64(b, gm.CursorID)
+	return b, err
+}
+
+// String implements the fmt.Stringer interface.
+func (gm GetMore) String() string {
+	return fmt.Sprintf(
+		`OP_GET_MORE{MsgHeader: %s, Zero: %d, FullCollectionName: %s, NumberToReturn: %d, CursorID: %d}`,
+		gm.MsgHeader, gm.Zero, gm.FullCollectionName, gm.NumberToReturn, gm.CursorID,
+	)
+}
+
+// Len implements the WireMessage interface.
+func (gm GetMore) Len() int {
+	// Header + Zero + CollectionName + Null Terminator + Return + CursorID
+	return 16 + 4 + len(gm.FullCollectionName) + 1 + 4 + 8
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (gm *GetMore) UnmarshalWireMessage([]byte) error {
+	panic("not implemented")
+}
+
+// CommandDocument creates a BSON document representing this command.
+func (gm GetMore) CommandDocument() bsonx.Doc {
+	parts := strings.Split(gm.FullCollectionName, ".")
+	collName := parts[len(parts)-1]
+
+	doc := bsonx.Doc{
+		{"getMore", bsonx.Int64(gm.CursorID)},
+		{"collection", bsonx.String(collName)},
+	}
+	if gm.NumberToReturn != 0 {
+		doc = doc.Append("batchSize", bsonx.Int32(gm.NumberToReturn))
+	}
+
+	return doc
+}
+
+// DatabaseName returns the name of the database for this command.
+func (gm GetMore) DatabaseName() string {
+	return strings.Split(gm.FullCollectionName, ".")[0]
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/header.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/header.go
new file mode 100644
index 0000000..ad1c291
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/header.go
@@ -0,0 +1,87 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package wiremessage
+
+import (
+	"fmt"
+)
+
+// ErrInvalidHeader is returned when methods are called on a malformed Header.
+var ErrInvalidHeader error = Error{Type: ErrHeader, Message: "invalid header"}
+
+// ErrHeaderTooSmall is returned when the size of the header is too small to be valid.
+var ErrHeaderTooSmall error = Error{Type: ErrHeader, Message: "the header is too small to be valid"}
+
+// ErrHeaderTooFewBytes is returned when a call to ReadHeader does not contain enough
+// bytes to be a valid header.
+var ErrHeaderTooFewBytes error = Error{Type: ErrHeader, Message: "invalid header because []byte too small"}
+
+// ErrHeaderInvalidLength is returned when the MessageLength of a header is
+// set but is not set to the correct size.
+var ErrHeaderInvalidLength error = Error{Type: ErrHeader, Message: "invalid header because MessageLength is imporperly set"}
+
+// ErrHeaderIncorrectOpCode is returned when the OpCode on a header is set but
+// is not set to the correct OpCode.
+var ErrHeaderIncorrectOpCode error = Error{Type: ErrHeader, Message: "invalid header because OpCode is improperly set"}
+
+// Header represents the header of a MongoDB wire protocol message.
+type Header struct {
+	MessageLength int32
+	RequestID     int32
+	ResponseTo    int32
+	OpCode        OpCode
+}
+
+// ReadHeader reads a header from the given slice of bytes starting at offset
+// pos.
+func ReadHeader(b []byte, pos int32) (Header, error) {
+	if len(b) < 16 {
+		return Header{}, ErrHeaderTooFewBytes
+	}
+	return Header{
+		MessageLength: readInt32(b, 0),
+		RequestID:     readInt32(b, 4),
+		ResponseTo:    readInt32(b, 8),
+		OpCode:        OpCode(readInt32(b, 12)),
+	}, nil
+}
+
+func (h Header) String() string {
+	return fmt.Sprintf(
+		`Header{MessageLength: %d, RequestID: %d, ResponseTo: %d, OpCode: %v}`,
+		h.MessageLength, h.RequestID, h.ResponseTo, h.OpCode,
+	)
+}
+
+// AppendHeader will append this header to the given slice of bytes.
+func (h Header) AppendHeader(b []byte) []byte {
+	b = appendInt32(b, h.MessageLength)
+	b = appendInt32(b, h.RequestID)
+	b = appendInt32(b, h.ResponseTo)
+	b = appendInt32(b, int32(h.OpCode))
+
+	return b
+}
+
+// SetDefaults sets the length and opcode of this header.
+func (h *Header) SetDefaults(length int, opcode OpCode) error {
+	switch h.MessageLength {
+	case int32(length):
+	case 0:
+		h.MessageLength = int32(length)
+	default:
+		return ErrHeaderInvalidLength
+	}
+	switch h.OpCode {
+	case opcode:
+	case OpCode(0):
+		h.OpCode = opcode
+	default:
+		return ErrHeaderIncorrectOpCode
+	}
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/insert.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/insert.go
new file mode 100644
index 0000000..498228d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/insert.go
@@ -0,0 +1,55 @@
+// 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 wiremessage
+
+import "github.com/mongodb/mongo-go-driver/bson"
+
+// Insert represents the OP_INSERT message of the MongoDB wire protocol.
+type Insert struct {
+	MsgHeader          Header
+	Flags              InsertFlag
+	FullCollectionName string
+	Documents          []bson.Raw
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (i Insert) MarshalWireMessage() ([]byte, error) {
+	panic("not implemented")
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (i Insert) ValidateWireMessage() error {
+	panic("not implemented")
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+func (i Insert) AppendWireMessage([]byte) ([]byte, error) {
+	panic("not implemented")
+}
+
+// String implements the fmt.Stringer interface.
+func (i Insert) String() string {
+	panic("not implemented")
+}
+
+// Len implements the WireMessage interface.
+func (i Insert) Len() int {
+	panic("not implemented")
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (i *Insert) UnmarshalWireMessage([]byte) error {
+	panic("not implemented")
+}
+
+// InsertFlag represents the flags on an OP_INSERT message.
+type InsertFlag int32
+
+// These constants represent the individual flags on an OP_INSERT message.
+const (
+	ContinueOnError InsertFlag = 1 << iota
+)
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/kill_cursors.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/kill_cursors.go
new file mode 100644
index 0000000..228a6ae
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/kill_cursors.go
@@ -0,0 +1,92 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package wiremessage
+
+import (
+	"errors"
+	"fmt"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+)
+
+// KillCursors represents the OP_KILL_CURSORS message of the MongoDB wire protocol.
+type KillCursors struct {
+	MsgHeader         Header
+	Zero              int32
+	NumberOfCursorIDs int32
+	CursorIDs         []int64
+
+	DatabaseName   string
+	CollectionName string
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (kc KillCursors) MarshalWireMessage() ([]byte, error) {
+	b := make([]byte, 0, kc.Len())
+	return kc.AppendWireMessage(b)
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (kc KillCursors) ValidateWireMessage() error {
+	if int(kc.MsgHeader.MessageLength) != kc.Len() {
+		return errors.New("incorrect header: message length is not correct")
+	}
+	if kc.MsgHeader.OpCode != OpKillCursors {
+		return errors.New("incorrect header: op code is not OpGetMore")
+	}
+	if kc.NumberOfCursorIDs != int32(len(kc.CursorIDs)) {
+		return errors.New("incorrect number of cursor IDs")
+	}
+
+	return nil
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+func (kc KillCursors) AppendWireMessage(b []byte) ([]byte, error) {
+	var err error
+	err = kc.MsgHeader.SetDefaults(kc.Len(), OpKillCursors)
+
+	b = kc.MsgHeader.AppendHeader(b)
+	b = appendInt32(b, kc.Zero)
+	b = appendInt32(b, kc.NumberOfCursorIDs)
+	for _, id := range kc.CursorIDs {
+		b = appendInt64(b, id)
+	}
+
+	return b, err
+}
+
+// String implements the fmt.Stringer interface.
+func (kc KillCursors) String() string {
+	return fmt.Sprintf(
+		`OP_KILL_CURSORS{MsgHeader: %s, Zero: %d, Number of Cursor IDS: %d, Cursor IDs: %v}`,
+		kc.MsgHeader, kc.Zero, kc.NumberOfCursorIDs, kc.CursorIDs,
+	)
+}
+
+// Len implements the WireMessage interface.
+func (kc KillCursors) Len() int {
+	// Header + Zero + Number IDs + 8 * Number IDs
+	return 16 + 4 + 4 + int(kc.NumberOfCursorIDs*8)
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (kc *KillCursors) UnmarshalWireMessage([]byte) error {
+	panic("not implemented")
+}
+
+// CommandDocument creates a BSON document representing this command.
+func (kc KillCursors) CommandDocument() bsonx.Doc {
+	cursors := make([]bsonx.Val, len(kc.CursorIDs))
+	for i, id := range kc.CursorIDs {
+		cursors[i] = bsonx.Int64(id)
+	}
+
+	return bsonx.Doc{
+		{"killCursors", bsonx.String(kc.CollectionName)},
+		{"cursors", bsonx.Array(cursors)},
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/msg.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/msg.go
new file mode 100644
index 0000000..07f35ab
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/msg.go
@@ -0,0 +1,298 @@
+// 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 wiremessage
+
+import (
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+)
+
+// Msg represents the OP_MSG message of the MongoDB wire protocol.
+type Msg struct {
+	MsgHeader Header
+	FlagBits  MsgFlag
+	Sections  []Section
+	Checksum  uint32
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (m Msg) MarshalWireMessage() ([]byte, error) {
+	b := make([]byte, 0, m.Len())
+	return m.AppendWireMessage(b)
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (m Msg) ValidateWireMessage() error {
+	if int(m.MsgHeader.MessageLength) != m.Len() {
+		return errors.New("incorrect header: message length is not correct")
+	}
+	if m.MsgHeader.OpCode != OpMsg {
+		return errors.New("incorrect header: opcode is not OpMsg")
+	}
+
+	return nil
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+//
+// AppendWireMesssage will set the MessageLength property of the MsgHeader if it is zero. It will also set the Opcode
+// to OP_MSG if it is zero. If either of these properties are non-zero and not correct, this method will return both the
+// []byte with the wire message appended to it and an invalid header error.
+func (m Msg) AppendWireMessage(b []byte) ([]byte, error) {
+	var err error
+	err = m.MsgHeader.SetDefaults(m.Len(), OpMsg)
+
+	b = m.MsgHeader.AppendHeader(b)
+	b = appendInt32(b, int32(m.FlagBits))
+
+	for _, section := range m.Sections {
+		newB := make([]byte, 0)
+		newB = section.AppendSection(newB)
+
+		b = section.AppendSection(b)
+	}
+
+	return b, err
+}
+
+// String implements the fmt.Stringer interface.
+func (m Msg) String() string {
+	panic("not implemented")
+}
+
+// Len implements the WireMessage interface.
+func (m Msg) Len() int {
+	// Header + Flags + len of each section + optional checksum
+	totalLen := 16 + 4 // header and flag
+
+	for _, section := range m.Sections {
+		totalLen += section.Len()
+	}
+
+	if m.FlagBits&ChecksumPresent > 0 {
+		totalLen += 4
+	}
+
+	return totalLen
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (m *Msg) UnmarshalWireMessage(b []byte) error {
+	var err error
+
+	m.MsgHeader, err = ReadHeader(b, 0)
+	if err != nil {
+		return err
+	}
+	if len(b) < int(m.MsgHeader.MessageLength) {
+		return Error{
+			Type:    ErrOpMsg,
+			Message: "[]byte too small",
+		}
+	}
+
+	m.FlagBits = MsgFlag(readInt32(b, 16))
+
+	// read each section
+	sectionBytes := m.MsgHeader.MessageLength - 16 - 4 // number of bytes taken up by sections
+	hasChecksum := m.FlagBits&ChecksumPresent > 0
+	if hasChecksum {
+		sectionBytes -= 4 // 4 bytes at end for checksum
+	}
+
+	m.Sections = make([]Section, 0)
+	position := 20 // position to read from
+	for sectionBytes > 0 {
+		sectionType := SectionType(b[position])
+		position++
+
+		switch sectionType {
+		case SingleDocument:
+			rdr, size, err := readDocument(b, int32(position))
+			if err.Message != "" {
+				err.Type = ErrOpMsg
+				return err
+			}
+
+			position += size
+			sb := SectionBody{
+				Document: rdr,
+			}
+			sb.PayloadType = sb.Kind()
+
+			sectionBytes -= int32(sb.Len())
+			m.Sections = append(m.Sections, sb)
+		case DocumentSequence:
+			sds := SectionDocumentSequence{}
+			sds.Size = readInt32(b, int32(position))
+			position += 4
+
+			identifier, err := readCString(b, int32(position))
+			if err != nil {
+				return err
+			}
+
+			sds.Identifier = identifier
+			position += len(identifier) + 1 // +1 for \0
+			sds.PayloadType = sds.Kind()
+
+			// length of documents to read
+			// sequenceLen - 4 bytes for size field - identifierLength (including \0)
+			docsLen := int(sds.Size) - 4 - len(identifier) - 1
+			for docsLen > 0 {
+				rdr, size, err := readDocument(b, int32(position))
+				if err.Message != "" {
+					err.Type = ErrOpMsg
+					return err
+				}
+
+				position += size
+				sds.Documents = append(sds.Documents, rdr)
+				docsLen -= size
+			}
+
+			sectionBytes -= int32(sds.Len())
+			m.Sections = append(m.Sections, sds)
+		}
+	}
+
+	if hasChecksum {
+		m.Checksum = uint32(readInt32(b, int32(position)))
+	}
+
+	return nil
+}
+
+// GetMainDocument returns the document containing the message to send.
+func (m *Msg) GetMainDocument() (bsonx.Doc, error) {
+	return bsonx.ReadDoc(m.Sections[0].(SectionBody).Document)
+}
+
+// GetSequenceArray returns this message's document sequence as a BSON array along with the array identifier.
+// If this message has no associated document sequence, a nil array is returned.
+func (m *Msg) GetSequenceArray() (bsonx.Arr, string, error) {
+	if len(m.Sections) == 1 {
+		return nil, "", nil
+	}
+
+	arr := bsonx.Arr{}
+	sds := m.Sections[1].(SectionDocumentSequence)
+
+	for _, rdr := range sds.Documents {
+		doc, err := bsonx.ReadDoc([]byte(rdr))
+		if err != nil {
+			return nil, "", err
+		}
+
+		arr = append(arr, bsonx.Document(doc))
+	}
+
+	return arr, sds.Identifier, nil
+}
+
+// AcknowledgedWrite returns true if this msg represents an acknowledged write command.
+func (m *Msg) AcknowledgedWrite() bool {
+	return m.FlagBits&MoreToCome == 0
+}
+
+// MsgFlag represents the flags on an OP_MSG message.
+type MsgFlag uint32
+
+// These constants represent the individual flags on an OP_MSG message.
+const (
+	ChecksumPresent MsgFlag = 1 << iota
+	MoreToCome
+
+	ExhaustAllowed MsgFlag = 1 << 16
+)
+
+// Section represents a section on an OP_MSG message.
+type Section interface {
+	Kind() SectionType
+	Len() int
+	AppendSection([]byte) []byte
+}
+
+// SectionBody represents the kind body of an OP_MSG message.
+type SectionBody struct {
+	PayloadType SectionType
+	Document    bson.Raw
+}
+
+// Kind implements the Section interface.
+func (sb SectionBody) Kind() SectionType {
+	return SingleDocument
+}
+
+// Len implements the Section interface
+func (sb SectionBody) Len() int {
+	return 1 + len(sb.Document) // 1 for PayloadType
+}
+
+// AppendSection implements the Section interface.
+func (sb SectionBody) AppendSection(dest []byte) []byte {
+	dest = append(dest, byte(SingleDocument))
+	dest = append(dest, sb.Document...)
+	return dest
+}
+
+// SectionDocumentSequence represents the kind document sequence of an OP_MSG message.
+type SectionDocumentSequence struct {
+	PayloadType SectionType
+	Size        int32
+	Identifier  string
+	Documents   []bson.Raw
+}
+
+// Kind implements the Section interface.
+func (sds SectionDocumentSequence) Kind() SectionType {
+	return DocumentSequence
+}
+
+// Len implements the Section interface
+func (sds SectionDocumentSequence) Len() int {
+	// PayloadType + Size + Identifier + 1 (null terminator) + totalDocLen
+	totalDocLen := 0
+	for _, doc := range sds.Documents {
+		totalDocLen += len(doc)
+	}
+
+	return 1 + 4 + len(sds.Identifier) + 1 + totalDocLen
+}
+
+// PayloadLen returns the length of the payload
+func (sds SectionDocumentSequence) PayloadLen() int {
+	// 4 bytes for size field, len identifier (including \0), and total docs len
+	return sds.Len() - 1
+}
+
+// AppendSection implements the Section interface
+func (sds SectionDocumentSequence) AppendSection(dest []byte) []byte {
+	dest = append(dest, byte(DocumentSequence))
+	dest = appendInt32(dest, sds.Size)
+	dest = appendCString(dest, sds.Identifier)
+
+	for _, doc := range sds.Documents {
+		dest = append(dest, doc...)
+	}
+
+	return dest
+}
+
+// SectionType represents the type for 1 section in an OP_MSG
+type SectionType uint8
+
+// These constants represent the individual section types for a section in an OP_MSG
+const (
+	SingleDocument SectionType = iota
+	DocumentSequence
+)
+
+// OpmsgWireVersion is the minimum wire version needed to use OP_MSG
+const OpmsgWireVersion = 6
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/query.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/query.go
new file mode 100644
index 0000000..568a3ec
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/query.go
@@ -0,0 +1,336 @@
+// 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 wiremessage
+
+import (
+	"errors"
+	"fmt"
+	"strings"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+)
+
+// Query represents the OP_QUERY message of the MongoDB wire protocol.
+type Query struct {
+	MsgHeader            Header
+	Flags                QueryFlag
+	FullCollectionName   string
+	NumberToSkip         int32
+	NumberToReturn       int32
+	Query                bson.Raw
+	ReturnFieldsSelector bson.Raw
+
+	SkipSet   bool
+	Limit     *int32
+	BatchSize *int32
+}
+
+var optionsMap = map[string]string{
+	"$orderby":     "sort",
+	"$hint":        "hint",
+	"$comment":     "comment",
+	"$maxScan":     "maxScan",
+	"$max":         "max",
+	"$min":         "min",
+	"$returnKey":   "returnKey",
+	"$showDiskLoc": "showRecordId",
+	"$maxTimeMS":   "maxTimeMS",
+	"$snapshot":    "snapshot",
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+//
+// See AppendWireMessage for a description of the rules this method follows.
+func (q Query) MarshalWireMessage() ([]byte, error) {
+	b := make([]byte, 0, q.Len())
+	return q.AppendWireMessage(b)
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (q Query) ValidateWireMessage() error {
+	if int(q.MsgHeader.MessageLength) != q.Len() {
+		return errors.New("incorrect header: message length is not correct")
+	}
+	if q.MsgHeader.OpCode != OpQuery {
+		return errors.New("incorrect header: op code is not OpQuery")
+	}
+	if strings.Index(q.FullCollectionName, ".") == -1 {
+		return errors.New("incorrect header: collection name does not contain a dot")
+	}
+	if q.Query != nil && len(q.Query) > 0 {
+		err := q.Query.Validate()
+		if err != nil {
+			return err
+		}
+	}
+
+	if q.ReturnFieldsSelector != nil && len(q.ReturnFieldsSelector) > 0 {
+		err := q.ReturnFieldsSelector.Validate()
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+//
+// AppendWireMessage will set the MessageLength property of the MsgHeader
+// if it is zero. It will also set the OpCode to OpQuery if the OpCode is
+// zero. If either of these properties are non-zero and not correct, this
+// method will return both the []byte with the wire message appended to it
+// and an invalid header error.
+func (q Query) AppendWireMessage(b []byte) ([]byte, error) {
+	var err error
+	err = q.MsgHeader.SetDefaults(q.Len(), OpQuery)
+
+	b = q.MsgHeader.AppendHeader(b)
+	b = appendInt32(b, int32(q.Flags))
+	b = appendCString(b, q.FullCollectionName)
+	b = appendInt32(b, q.NumberToSkip)
+	b = appendInt32(b, q.NumberToReturn)
+	b = append(b, q.Query...)
+	b = append(b, q.ReturnFieldsSelector...)
+	return b, err
+}
+
+// String implements the fmt.Stringer interface.
+func (q Query) String() string {
+	return fmt.Sprintf(
+		`OP_QUERY{MsgHeader: %s, Flags: %s, FullCollectionname: %s, NumberToSkip: %d, NumberToReturn: %d, Query: %s, ReturnFieldsSelector: %s}`,
+		q.MsgHeader, q.Flags, q.FullCollectionName, q.NumberToSkip, q.NumberToReturn, q.Query, q.ReturnFieldsSelector,
+	)
+}
+
+// Len implements the WireMessage interface.
+func (q Query) Len() int {
+	// Header + Flags + CollectionName + Null Byte + Skip + Return + Query + ReturnFieldsSelector
+	return 16 + 4 + len(q.FullCollectionName) + 1 + 4 + 4 + len(q.Query) + len(q.ReturnFieldsSelector)
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (q *Query) UnmarshalWireMessage(b []byte) error {
+	var err error
+	q.MsgHeader, err = ReadHeader(b, 0)
+	if err != nil {
+		return err
+	}
+	if len(b) < int(q.MsgHeader.MessageLength) {
+		return Error{Type: ErrOpQuery, Message: "[]byte too small"}
+	}
+
+	q.Flags = QueryFlag(readInt32(b, 16))
+	q.FullCollectionName, err = readCString(b, 20)
+	if err != nil {
+		return err
+	}
+	pos := 20 + len(q.FullCollectionName) + 1
+	q.NumberToSkip = readInt32(b, int32(pos))
+	pos += 4
+	q.NumberToReturn = readInt32(b, int32(pos))
+	pos += 4
+
+	var size int
+	var wmerr Error
+	q.Query, size, wmerr = readDocument(b, int32(pos))
+	if wmerr.Message != "" {
+		wmerr.Type = ErrOpQuery
+		return wmerr
+	}
+	pos += size
+	if pos < len(b) {
+		q.ReturnFieldsSelector, size, wmerr = readDocument(b, int32(pos))
+		if wmerr.Message != "" {
+			wmerr.Type = ErrOpQuery
+			return wmerr
+		}
+		pos += size
+	}
+
+	return nil
+}
+
+// AcknowledgedWrite returns true if this command represents an acknowledged write
+func (q *Query) AcknowledgedWrite() bool {
+	wcElem, err := q.Query.LookupErr("writeConcern")
+	if err != nil {
+		// no wc --> ack
+		return true
+	}
+
+	return writeconcern.AcknowledgedValue(wcElem)
+}
+
+// Legacy returns true if the query represents a legacy find operation.
+func (q Query) Legacy() bool {
+	return !strings.Contains(q.FullCollectionName, "$cmd")
+}
+
+// DatabaseName returns the database name for the query.
+func (q Query) DatabaseName() string {
+	if q.Legacy() {
+		return strings.Split(q.FullCollectionName, ".")[0]
+	}
+
+	return q.FullCollectionName[:len(q.FullCollectionName)-5] // remove .$cmd
+}
+
+// CollectionName returns the collection name for the query.
+func (q Query) CollectionName() string {
+	parts := strings.Split(q.FullCollectionName, ".")
+	return parts[len(parts)-1]
+}
+
+// CommandDocument creates a BSON document representing this command.
+func (q Query) CommandDocument() (bsonx.Doc, error) {
+	if q.Legacy() {
+		return q.legacyCommandDocument()
+	}
+
+	cmd, err := bsonx.ReadDoc([]byte(q.Query))
+	if err != nil {
+		return nil, err
+	}
+
+	cmdElem := cmd[0]
+	if cmdElem.Key == "$query" {
+		cmd = cmdElem.Value.Document()
+	}
+
+	return cmd, nil
+}
+
+func (q Query) legacyCommandDocument() (bsonx.Doc, error) {
+	doc, err := bsonx.ReadDoc(q.Query)
+	if err != nil {
+		return nil, err
+	}
+
+	parts := strings.Split(q.FullCollectionName, ".")
+	collName := parts[len(parts)-1]
+	doc = append(bsonx.Doc{{"find", bsonx.String(collName)}}, doc...)
+
+	var filter bsonx.Doc
+	var queryIndex int
+	for i, elem := range doc {
+		if newKey, ok := optionsMap[elem.Key]; ok {
+			doc[i].Key = newKey
+			continue
+		}
+
+		if elem.Key == "$query" {
+			filter = elem.Value.Document()
+		} else {
+			// the element is the filter
+			filter = filter.Append(elem.Key, elem.Value)
+		}
+
+		queryIndex = i
+	}
+
+	doc = append(doc[:queryIndex], doc[queryIndex+1:]...) // remove $query
+	if len(filter) != 0 {
+		doc = doc.Append("filter", bsonx.Document(filter))
+	}
+
+	doc, err = q.convertLegacyParams(doc)
+	if err != nil {
+		return nil, err
+	}
+
+	return doc, nil
+}
+
+func (q Query) convertLegacyParams(doc bsonx.Doc) (bsonx.Doc, error) {
+	if q.ReturnFieldsSelector != nil {
+		projDoc, err := bsonx.ReadDoc(q.ReturnFieldsSelector)
+		if err != nil {
+			return nil, err
+		}
+		doc = doc.Append("projection", bsonx.Document(projDoc))
+	}
+	if q.Limit != nil {
+		limit := *q.Limit
+		if limit < 0 {
+			limit *= -1
+			doc = doc.Append("singleBatch", bsonx.Boolean(true))
+		}
+
+		doc = doc.Append("limit", bsonx.Int32(*q.Limit))
+	}
+	if q.BatchSize != nil {
+		doc = doc.Append("batchSize", bsonx.Int32(*q.BatchSize))
+	}
+	if q.SkipSet {
+		doc = doc.Append("skip", bsonx.Int32(q.NumberToSkip))
+	}
+	if q.Flags&TailableCursor > 0 {
+		doc = doc.Append("tailable", bsonx.Boolean(true))
+	}
+	if q.Flags&OplogReplay > 0 {
+		doc = doc.Append("oplogReplay", bsonx.Boolean(true))
+	}
+	if q.Flags&NoCursorTimeout > 0 {
+		doc = doc.Append("noCursorTimeout", bsonx.Boolean(true))
+	}
+	if q.Flags&AwaitData > 0 {
+		doc = doc.Append("awaitData", bsonx.Boolean(true))
+	}
+	if q.Flags&Partial > 0 {
+		doc = doc.Append("allowPartialResults", bsonx.Boolean(true))
+	}
+
+	return doc, nil
+}
+
+// QueryFlag represents the flags on an OP_QUERY message.
+type QueryFlag int32
+
+// These constants represent the individual flags on an OP_QUERY message.
+const (
+	_ QueryFlag = 1 << iota
+	TailableCursor
+	SlaveOK
+	OplogReplay
+	NoCursorTimeout
+	AwaitData
+	Exhaust
+	Partial
+)
+
+// String implements the fmt.Stringer interface.
+func (qf QueryFlag) String() string {
+	strs := make([]string, 0)
+	if qf&TailableCursor == TailableCursor {
+		strs = append(strs, "TailableCursor")
+	}
+	if qf&SlaveOK == SlaveOK {
+		strs = append(strs, "SlaveOK")
+	}
+	if qf&OplogReplay == OplogReplay {
+		strs = append(strs, "OplogReplay")
+	}
+	if qf&NoCursorTimeout == NoCursorTimeout {
+		strs = append(strs, "NoCursorTimeout")
+	}
+	if qf&AwaitData == AwaitData {
+		strs = append(strs, "AwaitData")
+	}
+	if qf&Exhaust == Exhaust {
+		strs = append(strs, "Exhaust")
+	}
+	if qf&Partial == Partial {
+		strs = append(strs, "Partial")
+	}
+	str := "["
+	str += strings.Join(strs, ", ")
+	str += "]"
+	return str
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/readers.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/readers.go
new file mode 100644
index 0000000..bbf394d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/readers.go
@@ -0,0 +1,51 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package wiremessage
+
+import (
+	"bytes"
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+)
+
+func readInt32(b []byte, pos int32) int32 {
+	return (int32(b[pos+0])) | (int32(b[pos+1]) << 8) | (int32(b[pos+2]) << 16) | (int32(b[pos+3]) << 24)
+}
+
+func readCString(b []byte, pos int32) (string, error) {
+	null := bytes.IndexByte(b[pos:], 0x00)
+	if null == -1 {
+		return "", errors.New("invalid cstring")
+	}
+	return string(b[pos : int(pos)+null]), nil
+}
+
+func readInt64(b []byte, pos int32) int64 {
+	return (int64(b[pos+0])) | (int64(b[pos+1]) << 8) | (int64(b[pos+2]) << 16) | (int64(b[pos+3]) << 24) | (int64(b[pos+4]) << 32) |
+		(int64(b[pos+5]) << 40) | (int64(b[pos+6]) << 48) | (int64(b[pos+7]) << 56)
+
+}
+
+// readDocument will attempt to read a bson.Reader from the given slice of bytes
+// from the given position.
+func readDocument(b []byte, pos int32) (bson.Raw, int, Error) {
+	if int(pos)+4 > len(b) {
+		return nil, 0, Error{Message: "document too small to be valid"}
+	}
+	size := int(readInt32(b, int32(pos)))
+	if int(pos)+size > len(b) {
+		return nil, 0, Error{Message: "document size is larger than available bytes"}
+	}
+	if b[int(pos)+size-1] != 0x00 {
+		return nil, 0, Error{Message: "document invalid, last byte is not null"}
+	}
+	// TODO(GODRIVER-138): When we add 3.0 support, alter this so we either do one larger make or use a pool.
+	rdr := make(bson.Raw, size)
+	copy(rdr, b[pos:int(pos)+size])
+	return rdr, size, Error{Type: ErrNil}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/reply.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/reply.go
new file mode 100644
index 0000000..dc8e450
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/reply.go
@@ -0,0 +1,201 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package wiremessage
+
+import (
+	"errors"
+	"fmt"
+	"strings"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+)
+
+// Reply represents the OP_REPLY message of the MongoDB wire protocol.
+type Reply struct {
+	MsgHeader      Header
+	ResponseFlags  ReplyFlag
+	CursorID       int64
+	StartingFrom   int32
+	NumberReturned int32
+	Documents      []bson.Raw
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+//
+// See AppendWireMessage for a description of the rules this method follows.
+func (r Reply) MarshalWireMessage() ([]byte, error) {
+	b := make([]byte, 0, r.Len())
+	return r.AppendWireMessage(b)
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (r Reply) ValidateWireMessage() error {
+	if int(r.MsgHeader.MessageLength) != r.Len() {
+		return errors.New("incorrect header: message length is not correct")
+	}
+	if r.MsgHeader.OpCode != OpReply {
+		return errors.New("incorrect header: op code is not OpReply")
+	}
+
+	return nil
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+//
+// AppendWireMessage will set the MessageLength property of the MsgHeader
+// if it is zero. It will also set the OpCode to OpQuery if the OpCode is
+// zero. If either of these properties are non-zero and not correct, this
+// method will return both the []byte with the wire message appended to it
+// and an invalid header error.
+func (r Reply) AppendWireMessage(b []byte) ([]byte, error) {
+	var err error
+	err = r.MsgHeader.SetDefaults(r.Len(), OpReply)
+
+	b = r.MsgHeader.AppendHeader(b)
+	b = appendInt32(b, int32(r.ResponseFlags))
+	b = appendInt64(b, r.CursorID)
+	b = appendInt32(b, r.StartingFrom)
+	b = appendInt32(b, r.NumberReturned)
+	for _, d := range r.Documents {
+		b = append(b, d...)
+	}
+	return b, err
+}
+
+// String implements the fmt.Stringer interface.
+func (r Reply) String() string {
+	return fmt.Sprintf(
+		`OP_REPLY{MsgHeader: %s, ResponseFlags: %s, CursorID: %d, StartingFrom: %d, NumberReturned: %d, Documents: %v}`,
+		r.MsgHeader, r.ResponseFlags, r.CursorID, r.StartingFrom, r.NumberReturned, r.Documents,
+	)
+}
+
+// Len implements the WireMessage interface.
+func (r Reply) Len() int {
+	// Header + Flags + CursorID + StartingFrom + NumberReturned + Length of Length of Documents
+	docsLen := 0
+	for _, d := range r.Documents {
+		docsLen += len(d)
+	}
+	return 16 + 4 + 8 + 4 + 4 + docsLen
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (r *Reply) UnmarshalWireMessage(b []byte) error {
+	var err error
+	r.MsgHeader, err = ReadHeader(b, 0)
+	if err != nil {
+		return err
+	}
+	if r.MsgHeader.MessageLength < 36 {
+		return errors.New("invalid OP_REPLY: header length too small")
+	}
+	if len(b) < int(r.MsgHeader.MessageLength) {
+		return errors.New("invalid OP_REPLY: []byte too small")
+	}
+
+	r.ResponseFlags = ReplyFlag(readInt32(b, 16))
+	r.CursorID = readInt64(b, 20)
+	r.StartingFrom = readInt32(b, 28)
+	r.NumberReturned = readInt32(b, 32)
+	pos := 36
+	for pos < len(b) {
+		rdr, size, err := readDocument(b, int32(pos))
+		if err.Message != "" {
+			err.Type = ErrOpReply
+			return err
+		}
+		r.Documents = append(r.Documents, rdr)
+		pos += size
+	}
+
+	return nil
+}
+
+// GetMainLegacyDocument constructs and returns a BSON document for this reply.
+func (r *Reply) GetMainLegacyDocument(fullCollectionName string) (bsonx.Doc, error) {
+	if r.ResponseFlags&CursorNotFound > 0 {
+		fmt.Println("cursor not found err")
+		return bsonx.Doc{
+			{"ok", bsonx.Int32(0)},
+		}, nil
+	}
+	if r.ResponseFlags&QueryFailure > 0 {
+		firstDoc := r.Documents[0]
+		return bsonx.Doc{
+			{"ok", bsonx.Int32(0)},
+			{"errmsg", bsonx.String(firstDoc.Lookup("$err").StringValue())},
+			{"code", bsonx.Int32(firstDoc.Lookup("code").Int32())},
+		}, nil
+	}
+
+	doc := bsonx.Doc{
+		{"ok", bsonx.Int32(1)},
+	}
+
+	batchStr := "firstBatch"
+	if r.StartingFrom != 0 {
+		batchStr = "nextBatch"
+	}
+
+	batchArr := make([]bsonx.Val, len(r.Documents))
+	for i, docRaw := range r.Documents {
+		doc, err := bsonx.ReadDoc(docRaw)
+		if err != nil {
+			return nil, err
+		}
+
+		batchArr[i] = bsonx.Document(doc)
+	}
+
+	cursorDoc := bsonx.Doc{
+		{"id", bsonx.Int64(r.CursorID)},
+		{"ns", bsonx.String(fullCollectionName)},
+		{batchStr, bsonx.Array(batchArr)},
+	}
+
+	doc = doc.Append("cursor", bsonx.Document(cursorDoc))
+	return doc, nil
+}
+
+// GetMainDocument returns the main BSON document for this reply.
+func (r *Reply) GetMainDocument() (bsonx.Doc, error) {
+	return bsonx.ReadDoc([]byte(r.Documents[0]))
+}
+
+// ReplyFlag represents the flags of an OP_REPLY message.
+type ReplyFlag int32
+
+// These constants represent the individual flags of an OP_REPLY message.
+const (
+	CursorNotFound ReplyFlag = 1 << iota
+	QueryFailure
+	ShardConfigStale
+	AwaitCapable
+)
+
+// String implements the fmt.Stringer interface.
+func (rf ReplyFlag) String() string {
+	strs := make([]string, 0)
+	if rf&CursorNotFound == CursorNotFound {
+		strs = append(strs, "CursorNotFound")
+	}
+	if rf&QueryFailure == QueryFailure {
+		strs = append(strs, "QueryFailure")
+	}
+	if rf&ShardConfigStale == ShardConfigStale {
+		strs = append(strs, "ShardConfigStale")
+	}
+	if rf&AwaitCapable == AwaitCapable {
+		strs = append(strs, "AwaitCapable")
+	}
+	str := "["
+	str += strings.Join(strs, ", ")
+	str += "]"
+	return str
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/update.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/update.go
new file mode 100644
index 0000000..a987327
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/update.go
@@ -0,0 +1,57 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package wiremessage
+
+import "github.com/mongodb/mongo-go-driver/bson"
+
+// Update represents the OP_UPDATE message of the MongoDB wire protocol.
+type Update struct {
+	MsgHeader          Header
+	FullCollectionName string
+	Flags              UpdateFlag
+	Selector           bson.Raw
+	Update             bson.Raw
+}
+
+// MarshalWireMessage implements the Marshaler and WireMessage interfaces.
+func (u Update) MarshalWireMessage() ([]byte, error) {
+	panic("not implemented")
+}
+
+// ValidateWireMessage implements the Validator and WireMessage interfaces.
+func (u Update) ValidateWireMessage() error {
+	panic("not implemented")
+}
+
+// AppendWireMessage implements the Appender and WireMessage interfaces.
+func (u Update) AppendWireMessage([]byte) ([]byte, error) {
+	panic("not implemented")
+}
+
+// String implements the fmt.Stringer interface.
+func (u Update) String() string {
+	panic("not implemented")
+}
+
+// Len implements the WireMessage interface.
+func (u Update) Len() int {
+	panic("not implemented")
+}
+
+// UnmarshalWireMessage implements the Unmarshaler interface.
+func (u *Update) UnmarshalWireMessage([]byte) error {
+	panic("not implemented")
+}
+
+// UpdateFlag represents the flags on an OP_UPDATE message.
+type UpdateFlag int32
+
+// These constants represent the individual flags on an OP_UPDATE message.
+const (
+	Upsert UpdateFlag = 1 << iota
+	MultiUpdate
+)
diff --git a/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/wiremessage.go b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/wiremessage.go
new file mode 100644
index 0000000..c2cb153
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/x/network/wiremessage/wiremessage.go
@@ -0,0 +1,206 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+// Package wiremessage contains types for speaking the MongoDB Wire Protocol. Since this low
+// level library is meant to be used in the context of a driver and in the context of a server
+// all of the flags and types of the wire protocol are implemented. For each op there are two
+// corresponding implementations. One prefixed with Immutable which can be created by casting a
+// []byte to the type, and another prefixed with Mutable that is a struct with methods to mutate
+// the op.
+package wiremessage
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"io"
+	"sync/atomic"
+)
+
+// ErrInvalidMessageLength is returned when the provided message length is too small to be valid.
+var ErrInvalidMessageLength = errors.New("the message length is too small, it must be at least 16")
+
+// ErrUnknownOpCode is returned when the provided opcode is not a valid opcode.
+var ErrUnknownOpCode = errors.New("the opcode is unknown")
+
+var globalRequestID int32
+
+// CurrentRequestID returns the current request ID.
+func CurrentRequestID() int32 { return atomic.LoadInt32(&globalRequestID) }
+
+// NextRequestID returns the next request ID.
+func NextRequestID() int32 { return atomic.AddInt32(&globalRequestID, 1) }
+
+// Error represents an error related to wire protocol messages.
+type Error struct {
+	Type    ErrorType
+	Message string
+}
+
+// Error implements the err interface.
+func (e Error) Error() string {
+	return e.Message
+}
+
+// ErrorType is the type of error, which indicates from which part of the code
+// the error originated.
+type ErrorType uint16
+
+// These constants are the types of errors exposed by this package.
+const (
+	ErrNil ErrorType = iota
+	ErrHeader
+	ErrOpQuery
+	ErrOpReply
+	ErrOpCompressed
+	ErrOpMsg
+	ErrRead
+)
+
+// OpCode represents a MongoDB wire protocol opcode.
+type OpCode int32
+
+// These constants are the valid opcodes for the version of the wireprotocol
+// supported by this library. The skipped OpCodes are historical OpCodes that
+// are no longer used.
+const (
+	OpReply        OpCode = 1
+	_              OpCode = 1001
+	OpUpdate       OpCode = 2001
+	OpInsert       OpCode = 2002
+	_              OpCode = 2003
+	OpQuery        OpCode = 2004
+	OpGetMore      OpCode = 2005
+	OpDelete       OpCode = 2006
+	OpKillCursors  OpCode = 2007
+	OpCommand      OpCode = 2010
+	OpCommandReply OpCode = 2011
+	OpCompressed   OpCode = 2012
+	OpMsg          OpCode = 2013
+)
+
+// String implements the fmt.Stringer interface.
+func (oc OpCode) String() string {
+	switch oc {
+	case OpReply:
+		return "OP_REPLY"
+	case OpUpdate:
+		return "OP_UPDATE"
+	case OpInsert:
+		return "OP_INSERT"
+	case OpQuery:
+		return "OP_QUERY"
+	case OpGetMore:
+		return "OP_GET_MORE"
+	case OpDelete:
+		return "OP_DELETE"
+	case OpKillCursors:
+		return "OP_KILL_CURSORS"
+	case OpCommand:
+		return "OP_COMMAND"
+	case OpCommandReply:
+		return "OP_COMMANDREPLY"
+	case OpCompressed:
+		return "OP_COMPRESSED"
+	case OpMsg:
+		return "OP_MSG"
+	default:
+		return "<invalid opcode>"
+	}
+}
+
+// WireMessage represents a message in the MongoDB wire protocol.
+type WireMessage interface {
+	Marshaler
+	Validator
+	Appender
+	fmt.Stringer
+
+	// Len returns the length in bytes of this WireMessage.
+	Len() int
+}
+
+// Validator is the interface implemented by types that can validate
+// themselves as a MongoDB wire protocol message.
+type Validator interface {
+	ValidateWireMessage() error
+}
+
+// Marshaler is the interface implemented by types that can marshal
+// themselves into a valid MongoDB wire protocol message.
+type Marshaler interface {
+	MarshalWireMessage() ([]byte, error)
+}
+
+// Appender is the interface implemented by types that can append themselves, as
+// a MongoDB wire protocol message, to the provided slice of bytes.
+type Appender interface {
+	AppendWireMessage([]byte) ([]byte, error)
+}
+
+// Unmarshaler is the interface implemented by types that can unmarshal a
+// MongoDB wire protocol message version of themselves. The input can be
+// assumed to be a valid MongoDB wire protocol message. UnmarshalWireMessage
+// must copy the data if it wishes to retain the data after returning.
+type Unmarshaler interface {
+	UnmarshalWireMessage([]byte) error
+}
+
+// Writer is the interface implemented by types that can have WireMessages
+// written to them.
+//
+// Implementation must obey the cancellation, timeouts, and deadlines of the
+// provided context.Context object.
+type Writer interface {
+	WriteWireMessage(context.Context, WireMessage) error
+}
+
+// Reader is the interface implemented by types that can have WireMessages
+// read from them.
+//
+// Implementation must obey the cancellation, timeouts, and deadlines of the
+// provided context.Context object.
+type Reader interface {
+	ReadWireMessage(context.Context) (WireMessage, error)
+}
+
+// ReadWriter is the interface implemented by types that can both read and write
+// WireMessages.
+type ReadWriter interface {
+	Reader
+	Writer
+}
+
+// ReadWriteCloser is the interface implemented by types that can read and write
+// WireMessages and can also be closed.
+type ReadWriteCloser interface {
+	Reader
+	Writer
+	io.Closer
+}
+
+// Transformer is the interface implemented by types that can alter a WireMessage.
+// Implementations should not directly alter the provided WireMessage and instead
+// make a copy of the message, alter it, and returned the new message.
+type Transformer interface {
+	TransformWireMessage(WireMessage) (WireMessage, error)
+}
+
+// ReadFrom will read a single WireMessage from the given io.Reader. This function will
+// validate the WireMessage. If the WireMessage is not valid, this method will
+// return both the error and the invalid WireMessage. If another type of processing
+// error occurs, WireMessage will be nil.
+//
+// This function will return the immutable versions of wire protocol messages. The
+// Convert function can be used to retrieve a mutable version of wire protocol
+// messages.
+func ReadFrom(io.Reader) (WireMessage, error) { return nil, nil }
+
+// Unmarshal will unmarshal data into a WireMessage.
+func Unmarshal([]byte) (WireMessage, error) { return nil, nil }
+
+// Validate will validate that data is a valid MongoDB wire protocol message.
+func Validate([]byte) error { return nil }