1
0
Fork 0
forked from forgejo/forgejo

[Vendor] Update directly used dependencys (#15593)

* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3

* github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0

* github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2

* github.com/go-chi/cors v1.1.1 -> v1.2.0

* github.com/go-git/go-billy v5.0.0 -> v5.1.0

* github.com/go-git/go-git v5.2.0 -> v5.3.0

* github.com/go-ldap/ldap v3.2.4 -> v3.3.0

* github.com/go-redis/redis v8.6.0 -> v8.8.2

* github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0

* github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0

* github.com/lib/pq v1.9.0 -> v1.10.1

* github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7

* github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0

* github.com/issue9/identicon v1.0.1 -> v1.2.0

* github.com/klauspost/compress v1.11.8 -> v1.12.1

* github.com/mgechev/revive v1.0.3 -> v1.0.6

* github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8

* github.com/niklasfasching/go-org v1.4.0 -> v1.5.0

* github.com/olivere/elastic v7.0.22 -> v7.0.24

* github.com/pelletier/go-toml v1.8.1 -> v1.9.0

* github.com/prometheus/client_golang v1.9.0 -> v1.10.0

* github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0

* github.com/yuin/goldmark v1.3.3 -> v1.3.5

* github.com/6543/go-version v1.2.4 -> v1.3.1

* do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
This commit is contained in:
6543 2021-04-23 02:08:53 +02:00 committed by GitHub
parent 834fc74873
commit 792b4dba2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
558 changed files with 32080 additions and 24669 deletions

View file

@ -0,0 +1,50 @@
// Copyright (C) MongoDB, Inc. 2017-present.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
package bsoncodec
import (
"reflect"
"go.mongodb.org/mongo-driver/bson/bsonrw"
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
)
// ArrayCodec is the Codec used for bsoncore.Array values.
type ArrayCodec struct{}
var defaultArrayCodec = NewArrayCodec()
// NewArrayCodec returns an ArrayCodec.
func NewArrayCodec() *ArrayCodec {
return &ArrayCodec{}
}
// EncodeValue is the ValueEncoder for bsoncore.Array values.
func (ac *ArrayCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
if !val.IsValid() || val.Type() != tCoreArray {
return ValueEncoderError{Name: "CoreArrayEncodeValue", Types: []reflect.Type{tCoreArray}, Received: val}
}
arr := val.Interface().(bsoncore.Array)
return bsonrw.Copier{}.CopyArrayFromBytes(vw, arr)
}
// DecodeValue is the ValueDecoder for bsoncore.Array values.
func (ac *ArrayCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Type() != tCoreArray {
return ValueDecoderError{Name: "CoreArrayDecodeValue", Types: []reflect.Type{tCoreArray}, Received: val}
}
if val.IsNil() {
val.Set(reflect.MakeSlice(val.Type(), 0, 0))
}
val.SetLen(0)
arr, err := bsonrw.Copier{}.AppendArrayBytes(val.Interface().(bsoncore.Array), vr)
val.Set(reflect.ValueOf(arr))
return err
}

View file

@ -15,6 +15,10 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
var (
emptyValue = reflect.Value{}
)
// Marshaler is an interface implemented by types that can marshal themselves
// into a BSON document represented as bytes. The bytes returned must be a valid
// BSON document if the error is nil.
@ -156,6 +160,55 @@ func (fn ValueDecoderFunc) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader,
return fn(dc, vr, val)
}
// typeDecoder is the interface implemented by types that can handle the decoding of a value given its type.
type typeDecoder interface {
decodeType(DecodeContext, bsonrw.ValueReader, reflect.Type) (reflect.Value, error)
}
// typeDecoderFunc is an adapter function that allows a function with the correct signature to be used as a typeDecoder.
type typeDecoderFunc func(DecodeContext, bsonrw.ValueReader, reflect.Type) (reflect.Value, error)
func (fn typeDecoderFunc) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
return fn(dc, vr, t)
}
// decodeAdapter allows two functions with the correct signatures to be used as both a ValueDecoder and typeDecoder.
type decodeAdapter struct {
ValueDecoderFunc
typeDecoderFunc
}
var _ ValueDecoder = decodeAdapter{}
var _ typeDecoder = decodeAdapter{}
// decodeTypeOrValue calls decoder.decodeType is decoder is a typeDecoder. Otherwise, it allocates a new element of type
// t and calls decoder.DecodeValue on it.
func decodeTypeOrValue(decoder ValueDecoder, dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
td, _ := decoder.(typeDecoder)
return decodeTypeOrValueWithInfo(decoder, td, dc, vr, t, true)
}
func decodeTypeOrValueWithInfo(vd ValueDecoder, td typeDecoder, dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type, convert bool) (reflect.Value, error) {
if td != nil {
val, err := td.decodeType(dc, vr, t)
if err == nil && convert && val.Type() != t {
// This conversion step is necessary for slices and maps. If a user declares variables like:
//
// type myBool bool
// var m map[string]myBool
//
// and tries to decode BSON bytes into the map, the decoding will fail if this conversion is not present
// because we'll try to assign a value of type bool to one of type myBool.
val = val.Convert(t)
}
return val, err
}
val := reflect.New(t).Elem()
err := vd.DecodeValue(dc, vr, val)
return val, err
}
// CodecZeroer is the interface implemented by Codecs that can also determine if
// a value of the type that would be encoded is zero.
type CodecZeroer interface {

View file

@ -15,14 +15,17 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
var defaultByteSliceCodec = NewByteSliceCodec()
// ByteSliceCodec is the Codec used for []byte values.
type ByteSliceCodec struct {
EncodeNilAsEmpty bool
}
var _ ValueCodec = &ByteSliceCodec{}
var (
defaultByteSliceCodec = NewByteSliceCodec()
_ ValueCodec = defaultByteSliceCodec
_ typeDecoder = defaultByteSliceCodec
)
// NewByteSliceCodec returns a StringCodec with options opts.
func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec {
@ -45,10 +48,13 @@ func (bsc *ByteSliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter,
return vw.WriteBinary(val.Interface().([]byte))
}
// DecodeValue is the ValueDecoder for []byte.
func (bsc *ByteSliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Type() != tByteSlice {
return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val}
func (bsc *ByteSliceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
if t != tByteSlice {
return emptyValue, ValueDecoderError{
Name: "ByteSliceDecodeValue",
Types: []reflect.Type{tByteSlice},
Received: reflect.Zero(t),
}
}
var data []byte
@ -57,34 +63,49 @@ func (bsc *ByteSliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader,
case bsontype.String:
str, err := vr.ReadString()
if err != nil {
return err
return emptyValue, err
}
data = []byte(str)
case bsontype.Symbol:
sym, err := vr.ReadSymbol()
if err != nil {
return err
return emptyValue, err
}
data = []byte(sym)
case bsontype.Binary:
var subtype byte
data, subtype, err = vr.ReadBinary()
if err != nil {
return err
return emptyValue, err
}
if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
return fmt.Errorf("ByteSliceDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype)
return emptyValue, decodeBinaryError{subtype: subtype, typeName: "[]byte"}
}
case bsontype.Null:
val.Set(reflect.Zero(val.Type()))
return vr.ReadNull()
err = vr.ReadNull()
case bsontype.Undefined:
val.Set(reflect.Zero(val.Type()))
return vr.ReadUndefined()
err = vr.ReadUndefined()
default:
return fmt.Errorf("cannot decode %v into a []byte", vrType)
return emptyValue, fmt.Errorf("cannot decode %v into a []byte", vrType)
}
if err != nil {
return emptyValue, err
}
val.Set(reflect.ValueOf(data))
return reflect.ValueOf(data), nil
}
// DecodeValue is the ValueDecoder for []byte.
func (bsc *ByteSliceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Type() != tByteSlice {
return ValueDecoderError{Name: "ByteSliceDecodeValue", Types: []reflect.Type{tByteSlice}, Received: val}
}
elem, err := bsc.decodeType(dc, vr, tByteSlice)
if err != nil {
return err
}
val.Set(elem)
return nil
}

File diff suppressed because it is too large Load diff

View file

@ -70,6 +70,7 @@ func (dve DefaultValueEncoders) RegisterDefaultEncoders(rb *RegistryBuilder) {
RegisterTypeEncoder(tByteSlice, defaultByteSliceCodec).
RegisterTypeEncoder(tTime, defaultTimeCodec).
RegisterTypeEncoder(tEmpty, defaultEmptyInterfaceCodec).
RegisterTypeEncoder(tCoreArray, defaultArrayCodec).
RegisterTypeEncoder(tOID, ValueEncoderFunc(dve.ObjectIDEncodeValue)).
RegisterTypeEncoder(tDecimal, ValueEncoderFunc(dve.Decimal128EncodeValue)).
RegisterTypeEncoder(tJSONNumber, ValueEncoderFunc(dve.JSONNumberEncodeValue)).

View file

@ -15,14 +15,17 @@ import (
"go.mongodb.org/mongo-driver/bson/primitive"
)
var defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec()
// EmptyInterfaceCodec is the Codec used for interface{} values.
type EmptyInterfaceCodec struct {
DecodeBinaryAsSlice bool
}
var _ ValueCodec = &EmptyInterfaceCodec{}
var (
defaultEmptyInterfaceCodec = NewEmptyInterfaceCodec()
_ ValueCodec = defaultEmptyInterfaceCodec
_ typeDecoder = defaultEmptyInterfaceCodec
)
// NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts.
func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec {
@ -86,33 +89,31 @@ func (eic EmptyInterfaceCodec) getEmptyInterfaceDecodeType(dc DecodeContext, val
return nil, err
}
// DecodeValue is the ValueDecoderFunc for interface{}.
func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Type() != tEmpty {
return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val}
func (eic EmptyInterfaceCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
if t != tEmpty {
return emptyValue, ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: reflect.Zero(t)}
}
rtype, err := eic.getEmptyInterfaceDecodeType(dc, vr.Type())
if err != nil {
switch vr.Type() {
case bsontype.Null:
val.Set(reflect.Zero(val.Type()))
return vr.ReadNull()
return reflect.Zero(t), vr.ReadNull()
default:
return err
return emptyValue, err
}
}
decoder, err := dc.LookupDecoder(rtype)
if err != nil {
return err
return emptyValue, err
}
elem := reflect.New(rtype).Elem()
err = decoder.DecodeValue(dc, vr, elem)
elem, err := decodeTypeOrValue(decoder, dc, vr, rtype)
if err != nil {
return err
return emptyValue, err
}
if eic.DecodeBinaryAsSlice && rtype == tBinary {
binElem := elem.Interface().(primitive.Binary)
if binElem.Subtype == bsontype.BinaryGeneric || binElem.Subtype == bsontype.BinaryBinaryOld {
@ -120,6 +121,20 @@ func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueRead
}
}
return elem, nil
}
// DecodeValue is the ValueDecoderFunc for interface{}.
func (eic EmptyInterfaceCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Type() != tEmpty {
return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val}
}
elem, err := eic.decodeType(dc, vr, val.Type())
if err != nil {
return err
}
val.Set(elem)
return nil
}

View file

@ -178,6 +178,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref
if err != nil {
return err
}
eTypeDecoder, _ := decoder.(typeDecoder)
if eType == tEmpty {
dc.Ancestor = val.Type()
@ -199,8 +200,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref
return err
}
elem := reflect.New(eType).Elem()
err = decoder.DecodeValue(dc, vr, elem)
elem, err := decodeTypeOrValueWithInfo(decoder, eTypeDecoder, dc, vr, eType, true)
if err != nil {
return newDecodeError(key, err)
}

View file

@ -15,14 +15,17 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
var defaultStringCodec = NewStringCodec()
// StringCodec is the Codec used for struct values.
type StringCodec struct {
DecodeObjectIDAsHex bool
}
var _ ValueCodec = &StringCodec{}
var (
defaultStringCodec = NewStringCodec()
_ ValueCodec = defaultStringCodec
_ typeDecoder = defaultStringCodec
)
// NewStringCodec returns a StringCodec with options opts.
func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec {
@ -43,23 +46,27 @@ func (sc *StringCodec) EncodeValue(ectx EncodeContext, vw bsonrw.ValueWriter, va
return vw.WriteString(val.String())
}
// DecodeValue is the ValueDecoder for string types.
func (sc *StringCodec) DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Kind() != reflect.String {
return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val}
func (sc *StringCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
if t.Kind() != reflect.String {
return emptyValue, ValueDecoderError{
Name: "StringDecodeValue",
Kinds: []reflect.Kind{reflect.String},
Received: reflect.Zero(t),
}
}
var str string
var err error
switch vr.Type() {
case bsontype.String:
str, err = vr.ReadString()
if err != nil {
return err
return emptyValue, err
}
case bsontype.ObjectID:
oid, err := vr.ReadObjectID()
if err != nil {
return err
return emptyValue, err
}
if sc.DecodeObjectIDAsHex {
str = oid.Hex()
@ -70,29 +77,43 @@ func (sc *StringCodec) DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, va
case bsontype.Symbol:
str, err = vr.ReadSymbol()
if err != nil {
return err
return emptyValue, err
}
case bsontype.Binary:
data, subtype, err := vr.ReadBinary()
if err != nil {
return err
return emptyValue, err
}
if subtype != bsontype.BinaryGeneric && subtype != bsontype.BinaryBinaryOld {
return fmt.Errorf("SliceDecodeValue can only be used to decode subtype 0x00 or 0x02 for %s, got %v", bsontype.Binary, subtype)
return emptyValue, decodeBinaryError{subtype: subtype, typeName: "string"}
}
str = string(data)
case bsontype.Null:
if err = vr.ReadNull(); err != nil {
return err
return emptyValue, err
}
case bsontype.Undefined:
if err = vr.ReadUndefined(); err != nil {
return err
return emptyValue, err
}
default:
return fmt.Errorf("cannot decode %v into a string type", vr.Type())
return emptyValue, fmt.Errorf("cannot decode %v into a string type", vr.Type())
}
val.SetString(str)
return reflect.ValueOf(str), nil
}
// DecodeValue is the ValueDecoder for string types.
func (sc *StringCodec) DecodeValue(dctx DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Kind() != reflect.String {
return ValueDecoderError{Name: "StringDecodeValue", Kinds: []reflect.Kind{reflect.String}, Received: val}
}
elem, err := sc.decodeType(dctx, vr, val.Type())
if err != nil {
return err
}
val.SetString(elem.String())
return nil
}

View file

@ -91,6 +91,10 @@ var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (S
if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 {
tag = string(sf.Tag)
}
return parseTags(key, tag)
}
func parseTags(key string, tag string) (StructTags, error) {
var st StructTags
if tag == "-" {
st.Skip = true
@ -117,3 +121,19 @@ var DefaultStructTagParser StructTagParserFunc = func(sf reflect.StructField) (S
return st, nil
}
// JSONFallbackStructTagParser has the same behavior as DefaultStructTagParser
// but will also fallback to parsing the json tag instead on a field where the
// bson tag isn't available.
var JSONFallbackStructTagParser StructTagParserFunc = func(sf reflect.StructField) (StructTags, error) {
key := strings.ToLower(sf.Name)
tag, ok := sf.Tag.Lookup("bson")
if !ok {
tag, ok = sf.Tag.Lookup("json")
}
if !ok && !strings.Contains(string(sf.Tag), ":") && len(sf.Tag) > 0 {
tag = string(sf.Tag)
}
return parseTags(key, tag)
}

View file

@ -21,14 +21,17 @@ const (
timeFormatString = "2006-01-02T15:04:05.999Z07:00"
)
var defaultTimeCodec = NewTimeCodec()
// TimeCodec is the Codec used for time.Time values.
type TimeCodec struct {
UseLocalTimeZone bool
}
var _ ValueCodec = &TimeCodec{}
var (
defaultTimeCodec = NewTimeCodec()
_ ValueCodec = defaultTimeCodec
_ typeDecoder = defaultTimeCodec
)
// NewTimeCodec returns a TimeCodec with options opts.
func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec {
@ -41,10 +44,13 @@ func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec {
return &codec
}
// DecodeValue is the ValueDecoderFunc for time.Time.
func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Type() != tTime {
return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val}
func (tc *TimeCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
if t != tTime {
return emptyValue, ValueDecoderError{
Name: "TimeDecodeValue",
Types: []reflect.Type{tTime},
Received: reflect.Zero(t),
}
}
var timeVal time.Time
@ -52,47 +58,61 @@ func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val re
case bsontype.DateTime:
dt, err := vr.ReadDateTime()
if err != nil {
return err
return emptyValue, err
}
timeVal = time.Unix(dt/1000, dt%1000*1000000)
case bsontype.String:
// assume strings are in the isoTimeFormat
timeStr, err := vr.ReadString()
if err != nil {
return err
return emptyValue, err
}
timeVal, err = time.Parse(timeFormatString, timeStr)
if err != nil {
return err
return emptyValue, err
}
case bsontype.Int64:
i64, err := vr.ReadInt64()
if err != nil {
return err
return emptyValue, err
}
timeVal = time.Unix(i64/1000, i64%1000*1000000)
case bsontype.Timestamp:
t, _, err := vr.ReadTimestamp()
if err != nil {
return err
return emptyValue, err
}
timeVal = time.Unix(int64(t), 0)
case bsontype.Null:
if err := vr.ReadNull(); err != nil {
return err
return emptyValue, err
}
case bsontype.Undefined:
if err := vr.ReadUndefined(); err != nil {
return err
return emptyValue, err
}
default:
return fmt.Errorf("cannot decode %v into a time.Time", vrType)
return emptyValue, fmt.Errorf("cannot decode %v into a time.Time", vrType)
}
if !tc.UseLocalTimeZone {
timeVal = timeVal.UTC()
}
val.Set(reflect.ValueOf(timeVal))
return reflect.ValueOf(timeVal), nil
}
// DecodeValue is the ValueDecoderFunc for time.Time.
func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Type() != tTime {
return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val}
}
elem, err := tc.decodeType(dc, vr, tTime)
if err != nil {
return err
}
val.Set(elem)
return nil
}

View file

@ -79,3 +79,4 @@ var tA = reflect.TypeOf(primitive.A{})
var tE = reflect.TypeOf(primitive.E{})
var tCoreDocument = reflect.TypeOf(bsoncore.Document{})
var tCoreArray = reflect.TypeOf(bsoncore.Array{})

View file

@ -7,7 +7,6 @@
package bsoncodec
import (
"errors"
"fmt"
"math"
"reflect"
@ -17,14 +16,17 @@ import (
"go.mongodb.org/mongo-driver/bson/bsontype"
)
var defaultUIntCodec = NewUIntCodec()
// UIntCodec is the Codec used for uint values.
type UIntCodec struct {
EncodeToMinSize bool
}
var _ ValueCodec = &UIntCodec{}
var (
defaultUIntCodec = NewUIntCodec()
_ ValueCodec = defaultUIntCodec
_ typeDecoder = defaultUIntCodec
)
// NewUIntCodec returns a UIntCodec with options opts.
func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec {
@ -64,6 +66,93 @@ func (uic *UIntCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val r
}
}
func (uic *UIntCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
var i64 int64
var err error
switch vrType := vr.Type(); vrType {
case bsontype.Int32:
i32, err := vr.ReadInt32()
if err != nil {
return emptyValue, err
}
i64 = int64(i32)
case bsontype.Int64:
i64, err = vr.ReadInt64()
if err != nil {
return emptyValue, err
}
case bsontype.Double:
f64, err := vr.ReadDouble()
if err != nil {
return emptyValue, err
}
if !dc.Truncate && math.Floor(f64) != f64 {
return emptyValue, errCannotTruncate
}
if f64 > float64(math.MaxInt64) {
return emptyValue, fmt.Errorf("%g overflows int64", f64)
}
i64 = int64(f64)
case bsontype.Boolean:
b, err := vr.ReadBoolean()
if err != nil {
return emptyValue, err
}
if b {
i64 = 1
}
case bsontype.Null:
if err = vr.ReadNull(); err != nil {
return emptyValue, err
}
case bsontype.Undefined:
if err = vr.ReadUndefined(); err != nil {
return emptyValue, err
}
default:
return emptyValue, fmt.Errorf("cannot decode %v into an integer type", vrType)
}
switch t.Kind() {
case reflect.Uint8:
if i64 < 0 || i64 > math.MaxUint8 {
return emptyValue, fmt.Errorf("%d overflows uint8", i64)
}
return reflect.ValueOf(uint8(i64)), nil
case reflect.Uint16:
if i64 < 0 || i64 > math.MaxUint16 {
return emptyValue, fmt.Errorf("%d overflows uint16", i64)
}
return reflect.ValueOf(uint16(i64)), nil
case reflect.Uint32:
if i64 < 0 || i64 > math.MaxUint32 {
return emptyValue, fmt.Errorf("%d overflows uint32", i64)
}
return reflect.ValueOf(uint32(i64)), nil
case reflect.Uint64:
if i64 < 0 {
return emptyValue, fmt.Errorf("%d overflows uint64", i64)
}
return reflect.ValueOf(uint64(i64)), nil
case reflect.Uint:
if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint
return emptyValue, fmt.Errorf("%d overflows uint", i64)
}
return reflect.ValueOf(uint(i64)), nil
default:
return emptyValue, ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Received: reflect.Zero(t),
}
}
}
// DecodeValue is the ValueDecoder for uint types.
func (uic *UIntCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
if !val.CanSet() {
@ -74,81 +163,11 @@ func (uic *UIntCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val r
}
}
var i64 int64
var err error
switch vrType := vr.Type(); vrType {
case bsontype.Int32:
i32, err := vr.ReadInt32()
if err != nil {
return err
}
i64 = int64(i32)
case bsontype.Int64:
i64, err = vr.ReadInt64()
if err != nil {
return err
}
case bsontype.Double:
f64, err := vr.ReadDouble()
if err != nil {
return err
}
if !dc.Truncate && math.Floor(f64) != f64 {
return errors.New("UintDecodeValue can only truncate float64 to an integer type when truncation is enabled")
}
if f64 > float64(math.MaxInt64) {
return fmt.Errorf("%g overflows int64", f64)
}
i64 = int64(f64)
case bsontype.Boolean:
b, err := vr.ReadBoolean()
if err != nil {
return err
}
if b {
i64 = 1
}
case bsontype.Null:
if err = vr.ReadNull(); err != nil {
return err
}
case bsontype.Undefined:
if err = vr.ReadUndefined(); err != nil {
return err
}
default:
return fmt.Errorf("cannot decode %v into an integer type", vrType)
elem, err := uic.decodeType(dc, vr, val.Type())
if err != nil {
return err
}
switch val.Kind() {
case reflect.Uint8:
if i64 < 0 || i64 > math.MaxUint8 {
return fmt.Errorf("%d overflows uint8", i64)
}
case reflect.Uint16:
if i64 < 0 || i64 > math.MaxUint16 {
return fmt.Errorf("%d overflows uint16", i64)
}
case reflect.Uint32:
if i64 < 0 || i64 > math.MaxUint32 {
return fmt.Errorf("%d overflows uint32", i64)
}
case reflect.Uint64:
if i64 < 0 {
return fmt.Errorf("%d overflows uint64", i64)
}
case reflect.Uint:
if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint
return fmt.Errorf("%d overflows uint", i64)
}
default:
return ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Received: val,
}
}
val.SetUint(uint64(i64))
val.SetUint(elem.Uint())
return nil
}

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

View file

@ -12,6 +12,7 @@ import (
"io"
"math"
"strconv"
"strings"
"sync"
"go.mongodb.org/mongo-driver/bson/bsontype"
@ -247,7 +248,12 @@ func (vw *valueWriter) invalidTransitionError(destination mode, name string, mod
func (vw *valueWriter) writeElementHeader(t bsontype.Type, destination mode, callerName string, addmodes ...mode) error {
switch vw.stack[vw.frame].mode {
case mElement:
vw.buf = bsoncore.AppendHeader(vw.buf, t, vw.stack[vw.frame].key)
key := vw.stack[vw.frame].key
if !isValidCString(key) {
return errors.New("BSON element key cannot contain null bytes")
}
vw.buf = bsoncore.AppendHeader(vw.buf, t, key)
case mValue:
// TODO: Do this with a cache of the first 1000 or so array keys.
vw.buf = bsoncore.AppendHeader(vw.buf, t, strconv.Itoa(vw.stack[vw.frame].arrkey))
@ -430,6 +436,9 @@ func (vw *valueWriter) WriteObjectID(oid primitive.ObjectID) error {
}
func (vw *valueWriter) WriteRegex(pattern string, options string) error {
if !isValidCString(pattern) || !isValidCString(options) {
return errors.New("BSON regex values cannot contain null bytes")
}
if err := vw.writeElementHeader(bsontype.Regex, mode(0), "WriteRegex"); err != nil {
return err
}
@ -602,3 +611,7 @@ func (vw *valueWriter) writeLength() error {
vw.buf[start+3] = byte(length >> 24)
return nil
}
func isValidCString(cs string) bool {
return !strings.ContainsRune(cs, '\x00')
}

View file

@ -43,7 +43,7 @@
// 6. BSON embedded document unmarshals to the parent type (i.e. D for a D, M for an M).
// 7. BSON array unmarshals to a bson.A.
// 8. BSON ObjectId unmarshals to a primitive.ObjectID.
// 9. BSON datetime unmarshals to a primitive.Datetime.
// 9. BSON datetime unmarshals to a primitive.DateTime.
// 10. BSON binary unmarshals to a primitive.Binary.
// 11. BSON regular expression unmarshals to a primitive.Regex.
// 12. BSON JavaScript unmarshals to a primitive.JavaScript.
@ -90,14 +90,26 @@
// unmarshalled into an interface{} field will be unmarshalled as a D.
//
// The encoding of each struct field can be customized by the "bson" struct tag.
// The tag gives the name of the field, possibly followed by a comma-separated list of options.
//
// This tag behavior is configurable, and different struct tag behavior can be configured by initializing a new
// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON tags
// are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below:
//
// Example:
// structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.JSONFallbackStructTagParser)
//
// The bson tag gives the name of the field, possibly followed by a comma-separated list of options.
// The name may be empty in order to specify options without overriding the default field name. The following options can be used
// to configure behavior:
//
// 1. omitempty: If the omitempty struct tag is specified on a field, the field will not be marshalled if it is set to
// the zero value. By default, a struct field is only considered empty if the field's type implements the Zeroer
// interface and the IsZero method returns true. Struct fields of types that do not implement Zeroer are always
// marshalled as embedded documents. This tag should be used for all slice and map values.
// the zero value. Fields with language primitive types such as integers, booleans, and strings are considered empty if
// their value is equal to the zero value for the type (i.e. 0 for integers, false for booleans, and "" for strings).
// Slices, maps, and arrays are considered empty if they are of length zero. Interfaces and pointers are considered
// empty if their value is nil. By default, structs are only considered empty if the struct type implements the
// bsoncodec.Zeroer interface and the IsZero method returns true. Struct fields whose types do not implement Zeroer are
// never considered empty and will be marshalled as embedded documents.
// NOTE: It is recommended that this tag be used for all slice and map fields.
//
// 2. minsize: If the minsize struct tag is specified on a field of type int64, uint, uint32, or uint64 and the value of
// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For other

View file

@ -10,6 +10,7 @@
package primitive
import (
"encoding/json"
"errors"
"fmt"
"math/big"
@ -211,6 +212,49 @@ func (d Decimal128) IsZero() bool {
return d.h == 0 && d.l == 0
}
// MarshalJSON returns Decimal128 as a string.
func (d Decimal128) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
// UnmarshalJSON creates a primitive.Decimal128 from a JSON string, an extended JSON $numberDecimal value, or the string
// "null". If b is a JSON string or extended JSON value, d will have the value of that string, and if b is "null", d will
// be unchanged.
func (d *Decimal128) UnmarshalJSON(b []byte) error {
// Ignore "null" to keep parity with the standard library. Decoding a JSON null into a non-pointer Decimal128 field
// will leave the field unchanged. For pointer values, encoding/json will set the pointer to nil and will not
// enter the UnmarshalJSON hook.
if string(b) == "null" {
return nil
}
var res interface{}
err := json.Unmarshal(b, &res)
if err != nil {
return err
}
str, ok := res.(string)
// Extended JSON
if !ok {
m, ok := res.(map[string]interface{})
if !ok {
return errors.New("not an extended JSON Decimal128: expected document")
}
d128, ok := m["$numberDecimal"]
if !ok {
return errors.New("not an extended JSON Decimal128: expected key $numberDecimal")
}
str, ok = d128.(string)
if !ok {
return errors.New("not an extended JSON Decimal128: expected decimal to be string")
}
}
*d, err = ParseDecimal128(str)
return err
}
func divmod(h, l uint64, div uint32) (qh, ql uint64, rem uint32) {
div64 := uint64(div)
a := h >> 32

View file

@ -88,6 +88,12 @@ func ObjectIDFromHex(s string) (ObjectID, error) {
return oid, nil
}
// IsValidObjectID returns true if the provided hex string represents a valid ObjectID and false if not.
func IsValidObjectID(s string) bool {
_, err := ObjectIDFromHex(s)
return err == nil
}
// MarshalJSON returns the ObjectID as a string
func (id ObjectID) MarshalJSON() ([]byte, error) {
return json.Marshal(id.Hex())

View file

@ -266,6 +266,14 @@ func (rv RawValue) Int32() int32 { return convertToCoreValue(rv).Int32() }
// panicking.
func (rv RawValue) Int32OK() (int32, bool) { return convertToCoreValue(rv).Int32OK() }
// AsInt32 returns a BSON number as an int32. If the BSON type is not a numeric one, this method
// will panic.
func (rv RawValue) AsInt32() int32 { return convertToCoreValue(rv).AsInt32() }
// AsInt32OK is the same as AsInt32, except that it returns a boolean instead of
// panicking.
func (rv RawValue) AsInt32OK() (int32, bool) { return convertToCoreValue(rv).AsInt32OK() }
// Timestamp returns the BSON timestamp value the Value represents. It panics if the value is a
// BSON type other than timestamp.
func (rv RawValue) Timestamp() (t, i uint32) { return convertToCoreValue(rv).Timestamp() }
@ -282,6 +290,14 @@ func (rv RawValue) Int64() int64 { return convertToCoreValue(rv).Int64() }
// panicking.
func (rv RawValue) Int64OK() (int64, bool) { return convertToCoreValue(rv).Int64OK() }
// AsInt64 returns a BSON number as an int64. If the BSON type is not a numeric one, this method
// will panic.
func (rv RawValue) AsInt64() int64 { return convertToCoreValue(rv).AsInt64() }
// AsInt64OK is the same as AsInt64, except that it returns a boolean instead of
// panicking.
func (rv RawValue) AsInt64OK() (int64, bool) { return convertToCoreValue(rv).AsInt64OK() }
// Decimal128 returns the decimal the Value represents. It panics if the value is a BSON type other than
// decimal.
func (rv RawValue) Decimal128() primitive.Decimal128 { return convertToCoreValue(rv).Decimal128() }