Upgrade dependent version: go.mongodb.org/mongo-driver (#5320)

Upgrade dependent version: go.mongodb.org/mongo-driver v1.3.2 -> v1.10.4

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>

Signed-off-by: hongzhouzi <hongzhouzi@kubesphere.io>
This commit is contained in:
hongzhouzi
2022-12-02 15:08:55 +08:00
committed by GitHub
parent 493586d9a6
commit 0ca413cea3
61 changed files with 3025 additions and 1695 deletions

View File

@@ -45,6 +45,22 @@ func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error {
return c.copyDocumentCore(dw, dr)
}
// CopyArrayFromBytes copies the values from a BSON array represented as a
// []byte to a ValueWriter.
func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error {
aw, err := dst.WriteArray()
if err != nil {
return err
}
err = c.CopyBytesToArrayWriter(aw, src)
if err != nil {
return err
}
return aw.WriteArrayEnd()
}
// CopyDocumentFromBytes copies the values from a BSON document represented as a
// []byte to a ValueWriter.
func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error {
@@ -61,9 +77,29 @@ func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error {
return dw.WriteDocumentEnd()
}
type writeElementFn func(key string) (ValueWriter, error)
// CopyBytesToArrayWriter copies the values from a BSON Array represented as a []byte to an
// ArrayWriter.
func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error {
wef := func(_ string) (ValueWriter, error) {
return dst.WriteArrayElement()
}
return c.copyBytesToValueWriter(src, wef)
}
// CopyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a
// DocumentWriter.
func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error {
wef := func(key string) (ValueWriter, error) {
return dst.WriteDocumentElement(key)
}
return c.copyBytesToValueWriter(src, wef)
}
func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error {
// TODO(skriptble): Create errors types here. Anything thats a tag should be a property.
length, rem, ok := bsoncore.ReadLength(src)
if !ok {
@@ -93,15 +129,18 @@ func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error
if !ok {
return fmt.Errorf("invalid key found. remaining bytes=%v", rem)
}
dvw, err := dst.WriteDocumentElement(key)
// write as either array element or document element using writeElementFn
vw, err := wef(key)
if err != nil {
return err
}
val, rem, ok = bsoncore.ReadValue(rem, t)
if !ok {
return fmt.Errorf("not enough bytes available to read type. bytes=%d type=%s", len(rem), t)
}
err = c.CopyValueFromBytes(dvw, t, val.Data)
err = c.CopyValueFromBytes(vw, t, val.Data)
if err != nil {
return err
}
@@ -133,6 +172,23 @@ func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error)
return dst, err
}
// AppendArrayBytes copies an array from the ValueReader to dst.
func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) {
if br, ok := src.(BytesReader); ok {
_, dst, err := br.ReadValueBytes(dst)
return dst, err
}
vw := vwPool.Get().(*valueWriter)
defer vwPool.Put(vw)
vw.reset(dst)
err := c.copyArray(vw, src)
dst = vw.buf
return dst, err
}
// CopyValueFromBytes will write the value represtend by t and src to dst.
func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) error {
if wvb, ok := dst.(BytesWriter); ok {

View File

@@ -7,9 +7,12 @@
package bsonrw
import (
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"io"
"strings"
"go.mongodb.org/mongo-driver/bson/bsontype"
)
@@ -66,6 +69,7 @@ type extJSONParser struct {
maxDepth int
emptyObject bool
relaxedUUID bool
}
// newExtJSONParser returns a new extended JSON parser, ready to to begin
@@ -119,6 +123,12 @@ func (ejp *extJSONParser) peekType() (bsontype.Type, error) {
}
t = wrapperKeyBSONType(ejp.k)
// if $uuid is encountered, parse as binary subtype 4
if ejp.k == "$uuid" {
ejp.relaxedUUID = true
t = bsontype.Binary
}
switch t {
case bsontype.JavaScript:
// just saw $code, need to check for $scope at same level
@@ -273,6 +283,64 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) {
ejp.advanceState()
if t == bsontype.Binary && ejp.s == jpsSawValue {
// convert relaxed $uuid format
if ejp.relaxedUUID {
defer func() { ejp.relaxedUUID = false }()
uuid, err := ejp.v.parseSymbol()
if err != nil {
return nil, err
}
// RFC 4122 defines the length of a UUID as 36 and the hyphens in a UUID as appearing
// in the 8th, 13th, 18th, and 23rd characters.
//
// See https://tools.ietf.org/html/rfc4122#section-3
valid := len(uuid) == 36 &&
string(uuid[8]) == "-" &&
string(uuid[13]) == "-" &&
string(uuid[18]) == "-" &&
string(uuid[23]) == "-"
if !valid {
return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding length and hyphens")
}
// remove hyphens
uuidNoHyphens := strings.Replace(uuid, "-", "", -1)
if len(uuidNoHyphens) != 32 {
return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding length and hyphens")
}
// convert hex to bytes
bytes, err := hex.DecodeString(uuidNoHyphens)
if err != nil {
return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %v", err)
}
ejp.advanceState()
if ejp.s != jpsSawEndObject {
return nil, invalidJSONErrorForType("$uuid and value and then }", bsontype.Binary)
}
base64 := &extJSONValue{
t: bsontype.String,
v: base64.StdEncoding.EncodeToString(bytes),
}
subType := &extJSONValue{
t: bsontype.String,
v: "04",
}
v = &extJSONValue{
t: bsontype.EmbeddedDocument,
v: &extJSONObject{
keys: []string{"base64", "subType"},
values: []*extJSONValue{base64, subType},
},
}
break
}
// convert legacy $binary format
base64 := ejp.v
@@ -355,7 +423,7 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) {
if ejp.canonical {
return nil, invalidJSONErrorForType("object", t)
}
return nil, invalidJSONErrorForType("ISO-8601 Internet Date/Time Format as decribed in RFC-3339", t)
return nil, invalidJSONErrorForType("ISO-8601 Internet Date/Time Format as described in RFC-3339", t)
}
ejp.advanceState()

View File

@@ -159,29 +159,35 @@ func (ejvr *extJSONValueReader) pop() {
}
}
func (ejvr *extJSONValueReader) skipDocument() error {
// read entire document until ErrEOD (using readKey and readValue)
_, typ, err := ejvr.p.readKey()
for err == nil {
_, err = ejvr.p.readValue(typ)
if err != nil {
break
func (ejvr *extJSONValueReader) skipObject() {
// read entire object until depth returns to 0 (last ending } or ] seen)
depth := 1
for depth > 0 {
ejvr.p.advanceState()
// If object is empty, raise depth and continue. When emptyObject is true, the
// parser has already read both the opening and closing brackets of an empty
// object ("{}"), so the next valid token will be part of the parent document,
// not part of the nested document.
//
// If there is a comma, there are remaining fields, emptyObject must be set back
// to false, and comma must be skipped with advanceState().
if ejvr.p.emptyObject {
if ejvr.p.s == jpsSawComma {
ejvr.p.emptyObject = false
ejvr.p.advanceState()
}
depth--
continue
}
_, typ, err = ejvr.p.readKey()
switch ejvr.p.s {
case jpsSawBeginObject, jpsSawBeginArray:
depth++
case jpsSawEndObject, jpsSawEndArray:
depth--
}
}
return err
}
func (ejvr *extJSONValueReader) skipArray() error {
// read entire array until ErrEOA (using peekType)
_, err := ejvr.p.peekType()
for err == nil {
_, err = ejvr.p.peekType()
}
return err
}
func (ejvr *extJSONValueReader) invalidTransitionErr(destination mode, name string, modes []mode) error {
@@ -234,30 +240,9 @@ func (ejvr *extJSONValueReader) Skip() error {
t := ejvr.stack[ejvr.frame].vType
switch t {
case bsontype.Array:
// read entire array until ErrEOA
err := ejvr.skipArray()
if err != ErrEOA {
return err
}
case bsontype.EmbeddedDocument:
// read entire doc until ErrEOD
err := ejvr.skipDocument()
if err != ErrEOD {
return err
}
case bsontype.CodeWithScope:
// read the code portion and set up parser in document mode
_, err := ejvr.p.readValue(t)
if err != nil {
return err
}
// read until ErrEOD
err = ejvr.skipDocument()
if err != ErrEOD {
return err
}
case bsontype.Array, bsontype.EmbeddedDocument, bsontype.CodeWithScope:
// read entire array, doc or CodeWithScope
ejvr.skipObject()
default:
_, err := ejvr.p.readValue(t)
if err != nil {

View File

@@ -19,7 +19,7 @@ import (
)
func wrapperKeyBSONType(key string) bsontype.Type {
switch string(key) {
switch key {
case "$numberInt":
return bsontype.Int32
case "$numberLong":
@@ -46,12 +46,6 @@ func wrapperKeyBSONType(key string) bsontype.Type {
return bsontype.DBPointer
case "$date":
return bsontype.DateTime
case "$ref":
fallthrough
case "$id":
fallthrough
case "$db":
return bsontype.EmbeddedDocument // dbrefs aren't bson types
case "$minKey":
return bsontype.MinKey
case "$maxKey":
@@ -217,7 +211,7 @@ func parseDatetimeString(data string) (int64, error) {
return 0, fmt.Errorf("invalid $date value string: %s", data)
}
return t.Unix()*1e3 + int64(t.Nanosecond())/1e6, nil
return int64(primitive.NewDateTimeFromTime(t)), nil
}
func parseDatetimeObject(data *extJSONObject) (d int64, err error) {
@@ -275,7 +269,7 @@ func (ejv *extJSONValue) parseDouble() (float64, error) {
return 0, fmt.Errorf("$numberDouble value should be string, but instead is %s", ejv.t)
}
switch string(ejv.v.(string)) {
switch ejv.v.(string) {
case "Infinity":
return math.Inf(1), nil
case "-Infinity":
@@ -370,7 +364,7 @@ func (ejv *extJSONValue) parseRegex() (pattern, options string, err error) {
for i, key := range regexObj.keys {
val := regexObj.values[i]
switch string(key) {
switch key {
case "pattern":
if patFound {
return "", "", errors.New("duplicate pattern key in $regularExpression")

View File

@@ -10,7 +10,6 @@ import (
"bytes"
"encoding/base64"
"fmt"
"go.mongodb.org/mongo-driver/bson/primitive"
"io"
"math"
"sort"
@@ -19,13 +18,9 @@ import (
"sync"
"time"
"unicode/utf8"
)
var ejvwPool = sync.Pool{
New: func() interface{} {
return new(extJSONValueWriter)
},
}
"go.mongodb.org/mongo-driver/bson/primitive"
)
// ExtJSONValueWriterPool is a pool for ExtJSON ValueWriters.
type ExtJSONValueWriterPool struct {

View File

@@ -13,8 +13,8 @@ import (
"io"
"math"
"strconv"
"strings"
"unicode"
"unicode/utf16"
)
type jsonTokenType byte
@@ -162,6 +162,31 @@ func isValueTerminator(c byte) bool {
return c == ',' || c == '}' || c == ']' || isWhiteSpace(c)
}
// getu4 decodes the 4-byte hex sequence from the beginning of s, returning the hex value as a rune,
// or it returns -1. Note that the "\u" from the unicode escape sequence should not be present.
// It is copied and lightly modified from the Go JSON decode function at
// https://github.com/golang/go/blob/1b0a0316802b8048d69da49dc23c5a5ab08e8ae8/src/encoding/json/decode.go#L1169-L1188
func getu4(s []byte) rune {
if len(s) < 4 {
return -1
}
var r rune
for _, c := range s[:4] {
switch {
case '0' <= c && c <= '9':
c = c - '0'
case 'a' <= c && c <= 'f':
c = c - 'a' + 10
case 'A' <= c && c <= 'F':
c = c - 'A' + 10
default:
return -1
}
r = r*16 + rune(c)
}
return r
}
// scanString reads from an opening '"' to a closing '"' and handles escaped characters
func (js *jsonScanner) scanString() (*jsonToken, error) {
var b bytes.Buffer
@@ -179,9 +204,18 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
return nil, err
}
evalNextChar:
switch c {
case '\\':
c, err = js.readNextByte()
if err != nil {
if err == io.EOF {
return nil, errors.New("end of input in JSON string")
}
return nil, err
}
evalNextEscapeChar:
switch c {
case '"', '\\', '/':
b.WriteByte(c)
@@ -202,13 +236,68 @@ func (js *jsonScanner) scanString() (*jsonToken, error) {
return nil, fmt.Errorf("invalid unicode sequence in JSON string: %s", us)
}
s := fmt.Sprintf(`\u%s`, us)
s, err = strconv.Unquote(strings.Replace(strconv.Quote(s), `\\u`, `\u`, 1))
if err != nil {
return nil, err
rn := getu4(us)
// If the rune we just decoded is the high or low value of a possible surrogate pair,
// try to decode the next sequence as the low value of a surrogate pair. We're
// expecting the next sequence to be another Unicode escape sequence (e.g. "\uDD1E"),
// but need to handle cases where the input is not a valid surrogate pair.
// For more context on unicode surrogate pairs, see:
// https://www.christianfscott.com/rust-chars-vs-go-runes/
// https://www.unicode.org/glossary/#high_surrogate_code_point
if utf16.IsSurrogate(rn) {
c, err = js.readNextByte()
if err != nil {
if err == io.EOF {
return nil, errors.New("end of input in JSON string")
}
return nil, err
}
// If the next value isn't the beginning of a backslash escape sequence, write
// the Unicode replacement character for the surrogate value and goto the
// beginning of the next char eval block.
if c != '\\' {
b.WriteRune(unicode.ReplacementChar)
goto evalNextChar
}
c, err = js.readNextByte()
if err != nil {
if err == io.EOF {
return nil, errors.New("end of input in JSON string")
}
return nil, err
}
// If the next value isn't the beginning of a unicode escape sequence, write the
// Unicode replacement character for the surrogate value and goto the beginning
// of the next escape char eval block.
if c != 'u' {
b.WriteRune(unicode.ReplacementChar)
goto evalNextEscapeChar
}
err = js.readNNextBytes(us, 4, 0)
if err != nil {
return nil, fmt.Errorf("invalid unicode sequence in JSON string: %s", us)
}
rn2 := getu4(us)
// Try to decode the pair of runes as a utf16 surrogate pair. If that fails, write
// the Unicode replacement character for the surrogate value and the 2nd decoded rune.
if rnPair := utf16.DecodeRune(rn, rn2); rnPair != unicode.ReplacementChar {
b.WriteRune(rnPair)
} else {
b.WriteRune(unicode.ReplacementChar)
b.WriteRune(rn2)
}
break
}
b.WriteString(s)
b.WriteRune(rn)
default:
return nil, fmt.Errorf("invalid escape sequence in JSON string '\\%c'", c)
}

View File

@@ -86,12 +86,11 @@ type valueReader struct {
// NewBSONDocumentReader returns a ValueReader using b for the underlying BSON
// representation. Parameter b must be a BSON Document.
//
// TODO(skriptble): There's a lack of symmetry between the reader and writer, since the reader takes
// a []byte while the writer takes an io.Writer. We should have two versions of each, one that takes
// a []byte and one that takes an io.Reader or io.Writer. The []byte version will need to return a
// thing that can return the finished []byte since it might be reallocated when appended to.
func NewBSONDocumentReader(b []byte) ValueReader {
// TODO(skriptble): There's a lack of symmetry between the reader and writer, since the reader takes a []byte while the
// TODO writer takes an io.Writer. We should have two versions of each, one that takes a []byte and one that takes an
// TODO io.Reader or io.Writer. The []byte version will need to return a thing that can return the finished []byte since
// TODO it might be reallocated when appended to.
return newValueReader(b)
}
@@ -384,9 +383,13 @@ func (vr *valueReader) ReadBinary() (b []byte, btype byte, err error) {
if err != nil {
return nil, 0, err
}
// Make a copy of the returned byte slice because it's just a subslice from the valueReader's
// buffer and is not safe to return in the unmarshaled value.
cp := make([]byte, len(b))
copy(cp, b)
vr.pop()
return b, btype, nil
return cp, btype, nil
}
func (vr *valueReader) ReadBoolean() (bool, error) {
@@ -737,6 +740,9 @@ func (vr *valueReader) ReadValue() (ValueReader, error) {
return vr, nil
}
// readBytes reads length bytes from the valueReader starting at the current offset. Note that the
// returned byte slice is a subslice from the valueReader buffer and must be converted or copied
// before returning in an unmarshaled value.
func (vr *valueReader) readBytes(length int32) ([]byte, error) {
if length < 0 {
return nil, fmt.Errorf("invalid length: %d", length)
@@ -748,6 +754,7 @@ func (vr *valueReader) readBytes(length int32) ([]byte, error) {
start := vr.offset
vr.offset += int64(length)
return vr.d[start : start+int64(length)], nil
}
@@ -790,16 +797,6 @@ func (vr *valueReader) readCString() (string, error) {
return string(vr.d[start : start+int64(idx)]), nil
}
func (vr *valueReader) skipCString() error {
idx := bytes.IndexByte(vr.d[vr.offset:], 0x00)
if idx < 0 {
return io.EOF
}
// idx does not include the null byte
vr.offset += int64(idx) + 1
return nil
}
func (vr *valueReader) readString() (string, error) {
length, err := vr.readLength()
if err != nil {

View File

@@ -12,6 +12,7 @@ import (
"io"
"math"
"strconv"
"strings"
"sync"
"go.mongodb.org/mongo-driver/bson/bsontype"
@@ -46,11 +47,9 @@ func NewBSONValueWriterPool() *BSONValueWriterPool {
// Get retrieves a BSON ValueWriter from the pool and resets it to use w as the destination.
func (bvwp *BSONValueWriterPool) Get(w io.Writer) ValueWriter {
vw := bvwp.pool.Get().(*valueWriter)
if writer, ok := w.(*SliceWriter); ok {
vw.reset(*writer)
vw.w = writer
return vw
}
// TODO: Having to call reset here with the same buffer doesn't really make sense.
vw.reset(vw.buf)
vw.buf = vw.buf[:0]
vw.w = w
return vw
@@ -71,11 +70,6 @@ func (bvwp *BSONValueWriterPool) Put(vw ValueWriter) (ok bool) {
return false
}
if _, ok := bvw.w.(*SliceWriter); ok {
bvw.buf = nil
}
bvw.w = nil
bvwp.pool.Put(bvw)
return true
}
@@ -247,7 +241,12 @@ func (vw *valueWriter) invalidTransitionError(destination mode, name string, mod
func (vw *valueWriter) writeElementHeader(t bsontype.Type, destination mode, callerName string, addmodes ...mode) error {
switch vw.stack[vw.frame].mode {
case mElement:
vw.buf = bsoncore.AppendHeader(vw.buf, t, vw.stack[vw.frame].key)
key := vw.stack[vw.frame].key
if !isValidCString(key) {
return errors.New("BSON element key cannot contain null bytes")
}
vw.buf = bsoncore.AppendHeader(vw.buf, t, key)
case mValue:
// TODO: Do this with a cache of the first 1000 or so array keys.
vw.buf = bsoncore.AppendHeader(vw.buf, t, strconv.Itoa(vw.stack[vw.frame].arrkey))
@@ -430,6 +429,9 @@ func (vw *valueWriter) WriteObjectID(oid primitive.ObjectID) error {
}
func (vw *valueWriter) WriteRegex(pattern string, options string) error {
if !isValidCString(pattern) || !isValidCString(options) {
return errors.New("BSON regex values cannot contain null bytes")
}
if err := vw.writeElementHeader(bsontype.Regex, mode(0), "WriteRegex"); err != nil {
return err
}
@@ -527,7 +529,7 @@ func (vw *valueWriter) WriteDocumentEnd() error {
vw.pop()
if vw.stack[vw.frame].mode == mCodeWithScope {
// We ignore the error here because of the gaurantee of writeLength.
// We ignore the error here because of the guarantee of writeLength.
// See the docs for writeLength for more info.
_ = vw.writeLength()
vw.pop()
@@ -540,10 +542,6 @@ func (vw *valueWriter) Flush() error {
return nil
}
if sw, ok := vw.w.(*SliceWriter); ok {
*sw = vw.buf
return nil
}
if _, err := vw.w.Write(vw.buf); err != nil {
return err
}
@@ -602,3 +600,7 @@ func (vw *valueWriter) writeLength() error {
vw.buf[start+3] = byte(length >> 24)
return nil
}
func isValidCString(cs string) bool {
return !strings.ContainsRune(cs, '\x00')
}

View File

@@ -76,27 +76,3 @@ func (sw *SliceWriter) Write(p []byte) (int, error) {
*sw = append(*sw, p...)
return written, nil
}
type writer []byte
func (w *writer) Write(p []byte) (int, error) {
index := len(*w)
return w.WriteAt(p, int64(index))
}
func (w *writer) WriteAt(p []byte, off int64) (int, error) {
newend := off + int64(len(p))
if newend < int64(len(*w)) {
newend = int64(len(*w))
}
if newend > int64(cap(*w)) {
buf := make([]byte, int64(2*cap(*w))+newend)
copy(buf, *w)
*w = buf
}
*w = []byte(*w)[:newend]
copy([]byte(*w)[off:], p)
return len(p), nil
}