Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
qingyang-hu committed May 21, 2024
1 parent 7a0b8bf commit 8d43b10
Show file tree
Hide file tree
Showing 27 changed files with 192 additions and 112 deletions.
4 changes: 2 additions & 2 deletions bson/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ type Decoder struct {
vr ValueReader
}

// NewDecoder returns a new decoder that uses the DefaultRegistry to read from vr.
// NewDecoder returns a new decoder that uses the default registry to read from vr.
func NewDecoder(vr ValueReader) *Decoder {
return &Decoder{
reg: DefaultRegistry,
reg: NewRegistryBuilder().Build(),
vr: vr,
}
}
Expand Down
26 changes: 13 additions & 13 deletions bson/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,19 @@ func TestDecoderv2(t *testing.T) {
t.Errorf("Decoder should use the value reader provided. got %v; want %v", dec.vr, vr2)
}
})
t.Run("SetRegistry", func(t *testing.T) {
t.Parallel()

r1, r2 := DefaultRegistry, NewRegistryBuilder().Build()
dec := NewDecoder(NewValueReader([]byte{}))
if !reflect.DeepEqual(dec.reg, r1) {
t.Errorf("Decoder should use the Registry provided. got %v; want %v", dec.reg, r1)
}
dec.SetRegistry(r2)
if !reflect.DeepEqual(dec.reg, r2) {
t.Errorf("Decoder should use the Registry provided. got %v; want %v", dec.reg, r2)
}
})
// t.Run("SetRegistry", func(t *testing.T) {
// t.Parallel()

// r1, r2 := DefaultRegistry, NewRegistryBuilder().Build()
// dec := NewDecoder(NewValueReader([]byte{}))
// if !reflect.DeepEqual(dec.reg, r1) {
// t.Errorf("Decoder should use the Registry provided. got %v; want %v", dec.reg, r1)
// }
// dec.SetRegistry(r2)
// if !reflect.DeepEqual(dec.reg, r2) {
// t.Errorf("Decoder should use the Registry provided. got %v; want %v", dec.reg, r2)
// }
// })
t.Run("DecodeToNil", func(t *testing.T) {
t.Parallel()

Expand Down
98 changes: 70 additions & 28 deletions bson/default_value_decoders_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,11 @@ func TestDefaultValueDecoders(t *testing.T) {
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)},
readInt32,
ValueDecoderError{
Name: "IntDecodeValue",
Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf(wrong),
},
},
Expand Down Expand Up @@ -214,44 +217,59 @@ func TestDefaultValueDecoders(t *testing.T) {
"int8/fast path - nil", (*int8)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "IntDecodeValue",
Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*int8)(nil)),
},
},
{
"int16/fast path - nil", (*int16)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "IntDecodeValue",
Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*int16)(nil)),
},
},
{
"int32/fast path - nil", (*int32)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "IntDecodeValue",
Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*int32)(nil)),
},
},
{
"int64/fast path - nil", (*int64)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "IntDecodeValue",
Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*int64)(nil)),
},
},
{
"int/fast path - nil", (*int)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "IntDecodeValue",
Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*int)(nil)),
},
},
Expand Down Expand Up @@ -347,8 +365,11 @@ func TestDefaultValueDecoders(t *testing.T) {
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)},
nothing,
ValueDecoderError{
Name: "IntDecodeValue",
Kinds: []reflect.Kind{reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
},
},
{
Expand Down Expand Up @@ -380,8 +401,11 @@ func TestDefaultValueDecoders(t *testing.T) {
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)},
readInt32,
ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf(wrong),
},
},
Expand Down Expand Up @@ -446,44 +470,59 @@ func TestDefaultValueDecoders(t *testing.T) {
"uint8/fast path - nil", (*uint8)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*uint8)(nil)),
},
},
{
"uint16/fast path - nil", (*uint16)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*uint16)(nil)),
},
},
{
"uint32/fast path - nil", (*uint32)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*uint32)(nil)),
},
},
{
"uint64/fast path - nil", (*uint64)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*uint64)(nil)),
},
},
{
"uint/fast path - nil", (*uint)(nil), nil,
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)}, readInt32,
ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: reflect.ValueOf((*uint)(nil)),
},
},
Expand Down Expand Up @@ -599,8 +638,11 @@ func TestDefaultValueDecoders(t *testing.T) {
&valueReaderWriter{BSONType: TypeInt32, Return: int32(0)},
nothing,
ValueDecoderError{
Name: "UintDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
},
},
},
Expand Down
10 changes: 5 additions & 5 deletions bson/empty_interface_codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type emptyInterfaceCodec struct {
}

// EncodeValue is the ValueEncoderFunc for interface{}.
func (eic emptyInterfaceCodec) EncodeValue(reg EncoderRegistry, vw ValueWriter, val reflect.Value) error {
func (eic *emptyInterfaceCodec) EncodeValue(reg EncoderRegistry, vw ValueWriter, val reflect.Value) error {
if !val.IsValid() || val.Type() != tEmpty {
return ValueEncoderError{Name: "EmptyInterfaceEncodeValue", Types: []reflect.Type{tEmpty}, Received: val}
}
Expand All @@ -40,7 +40,7 @@ func (eic emptyInterfaceCodec) EncodeValue(reg EncoderRegistry, vw ValueWriter,
return encoder.EncodeValue(reg, vw, val.Elem())
}

func (eic emptyInterfaceCodec) getEmptyInterfaceDecodeType(reg DecoderRegistry, valueType Type, ancestorType reflect.Type) (reflect.Type, error) {
func (eic *emptyInterfaceCodec) getEmptyInterfaceDecodeType(reg DecoderRegistry, valueType Type, ancestorType reflect.Type) (reflect.Type, error) {
isDocument := valueType == Type(0) || valueType == TypeEmbeddedDocument
if isDocument {
if eic.defaultDocumentType != nil {
Expand Down Expand Up @@ -81,12 +81,12 @@ func (eic emptyInterfaceCodec) getEmptyInterfaceDecodeType(reg DecoderRegistry,
return nil, err
}

func (eic emptyInterfaceCodec) decodeType(reg DecoderRegistry, vr ValueReader, t reflect.Type) (reflect.Value, error) {
func (eic *emptyInterfaceCodec) decodeType(reg DecoderRegistry, vr ValueReader, t reflect.Type) (reflect.Value, error) {
rtype, err := eic.getEmptyInterfaceDecodeType(reg, vr.Type(), t)
if err != nil {
switch vr.Type() {
case TypeNull:
return reflect.Zero(t), vr.ReadNull()
return reflect.Zero(tEmpty), vr.ReadNull()
default:
return emptyValue, err
}
Expand Down Expand Up @@ -116,7 +116,7 @@ func (eic emptyInterfaceCodec) decodeType(reg DecoderRegistry, vr ValueReader, t
}

// DecodeValue is the ValueDecoderFunc for interface{}.
func (eic emptyInterfaceCodec) DecodeValue(reg DecoderRegistry, vr ValueReader, val reflect.Value) error {
func (eic *emptyInterfaceCodec) DecodeValue(reg DecoderRegistry, vr ValueReader, val reflect.Value) error {
if !val.CanSet() || val.Type() != tEmpty {
return ValueDecoderError{Name: "EmptyInterfaceDecodeValue", Types: []reflect.Type{tEmpty}, Received: val}
}
Expand Down
6 changes: 3 additions & 3 deletions bson/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ type Encoder struct {
vw ValueWriter
}

// NewEncoder returns a new encoder that uses the DefaultRegistry to write to vw.
// NewEncoder returns a new encoder that uses the default registry to write to vw.
func NewEncoder(vw ValueWriter) *Encoder {
return &Encoder{
reg: DefaultRegistry,
reg: NewRegistryBuilder().Build(),
vw: vw,
}
}
Expand Down Expand Up @@ -95,7 +95,7 @@ func (e *Encoder) IntMinSize() {
t := reflect.TypeOf((*intCodec)(nil))
if v, ok := e.reg.codecTypeMap[t]; ok && v != nil {
for i := range v {
v[i].(*intCodec).encodeToMinSize = true
v[i].(*intCodec).minSize = true
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion bson/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestBasicEncode(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
got := make(SliceWriter, 0, 1024)
vw := NewValueWriter(&got)
reg := DefaultRegistry
reg := NewRegistryBuilder().Build()
encoder, err := reg.LookupEncoder(reflect.TypeOf(tc.val))
noerr(t, err)
err = encoder.EncodeValue(reg, vw, reflect.ValueOf(tc.val))
Expand Down
26 changes: 19 additions & 7 deletions bson/int_codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ import (

// intCodec is the Codec used for uint values.
type intCodec struct {
// encodeToMinSize causes EncodeValue to marshal Go uint values (excluding uint64) as the
// minSize causes the Encoder to marshal Go integer values (int, int8, int16, int32, int64,
// uint, uint8, uint16, uint32, or uint64) as the minimum BSON int size (either 32 or 64 bits)
// that can represent the integer value.
minSize bool

// encodeUintToMinSize causes EncodeValue to marshal Go uint values (excluding uint64) as the
// minimum BSON int size (either 32-bit or 64-bit) that can represent the integer value.
encodeToMinSize bool
encodeUintToMinSize bool

// truncate, if true, instructs decoders to to truncate the fractional part of BSON "double"
// values when attempting to unmarshal them into a Go integer (int, int8, int16, int32, int64,
Expand All @@ -38,7 +43,7 @@ func (ic *intCodec) EncodeValue(_ EncoderRegistry, vw ValueWriter, val reflect.V
return vw.WriteInt64(i64)
case reflect.Int64:
i64 := val.Int()
if ic.encodeToMinSize && fitsIn32Bits(i64) {
if ic.minSize && fitsIn32Bits(i64) {
return vw.WriteInt32(int32(i64))
}
return vw.WriteInt64(i64)
Expand All @@ -48,8 +53,8 @@ func (ic *intCodec) EncodeValue(_ EncoderRegistry, vw ValueWriter, val reflect.V
case reflect.Uint, reflect.Uint32, reflect.Uint64:
u64 := val.Uint()

// If encodeToMinSize is true for a non-uint64 value we should write val as an int32
useMinSize := ic.encodeToMinSize && val.Kind() != reflect.Uint64
// If minSize or encodeToMinSize is true for a non-uint64 value we should write val as an int32
useMinSize := ic.minSize || (ic.encodeUintToMinSize && val.Kind() != reflect.Uint64)

if u64 <= math.MaxInt32 && useMinSize {
return vw.WriteInt32(int32(u64))
Expand Down Expand Up @@ -183,8 +188,11 @@ func (ic *intCodec) decodeType(_ DecoderRegistry, vr ValueReader, t reflect.Type
func (ic *intCodec) DecodeValue(reg DecoderRegistry, vr ValueReader, val reflect.Value) error {
if !val.CanSet() {
return ValueDecoderError{
Name: "IntDecodeValue",
Kinds: []reflect.Kind{reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint},
Name: "IntDecodeValue",
Kinds: []reflect.Kind{
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int,
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint,
},
Received: val,
}
}
Expand All @@ -194,6 +202,10 @@ func (ic *intCodec) DecodeValue(reg DecoderRegistry, vr ValueReader, val reflect
return err
}

if t := val.Type(); elem.Type() != t {
elem = elem.Convert(t)
}

val.Set(elem)
return nil
}
Loading

0 comments on commit 8d43b10

Please sign in to comment.