|
@@ -6,6 +6,7 @@ package codec
|
|
|
import (
|
|
import (
|
|
|
"io"
|
|
"io"
|
|
|
"reflect"
|
|
"reflect"
|
|
|
|
|
+ // "runtime/debug"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// Some tagging information for error messages.
|
|
// Some tagging information for error messages.
|
|
@@ -14,35 +15,6 @@ var (
|
|
|
msgBadDesc = "Unrecognized descriptor byte"
|
|
msgBadDesc = "Unrecognized descriptor byte"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-// when decoding without schema, the nakedContext tells us what
|
|
|
|
|
-// we decoded into, or if decoding has been handled.
|
|
|
|
|
-type decodeNakedContext uint8
|
|
|
|
|
-
|
|
|
|
|
-const (
|
|
|
|
|
- dncHandled decodeNakedContext = iota
|
|
|
|
|
- dncNil
|
|
|
|
|
- // dncExt
|
|
|
|
|
- dncContainer
|
|
|
|
|
-)
|
|
|
|
|
-
|
|
|
|
|
-// decodeEncodedType is the current type in the encoded stream
|
|
|
|
|
-type decodeEncodedType uint8
|
|
|
|
|
-
|
|
|
|
|
-const (
|
|
|
|
|
- detUnset decodeEncodedType = iota
|
|
|
|
|
- detNil
|
|
|
|
|
- detInt
|
|
|
|
|
- detUint
|
|
|
|
|
- detFloat
|
|
|
|
|
- detBool
|
|
|
|
|
- detString
|
|
|
|
|
- detBytes
|
|
|
|
|
- detMap
|
|
|
|
|
- detArray
|
|
|
|
|
- detTimestamp
|
|
|
|
|
- detExt
|
|
|
|
|
-)
|
|
|
|
|
-
|
|
|
|
|
// decReader abstracts the reading source, allowing implementations that can
|
|
// decReader abstracts the reading source, allowing implementations that can
|
|
|
// read from an io.Reader or directly off a byte slice with zero-copying.
|
|
// read from an io.Reader or directly off a byte slice with zero-copying.
|
|
|
type decReader interface {
|
|
type decReader interface {
|
|
@@ -57,12 +29,11 @@ type decReader interface {
|
|
|
type decDriver interface {
|
|
type decDriver interface {
|
|
|
initReadNext()
|
|
initReadNext()
|
|
|
tryDecodeAsNil() bool
|
|
tryDecodeAsNil() bool
|
|
|
- currentEncodedType() decodeEncodedType
|
|
|
|
|
|
|
+ currentEncodedType() valueType
|
|
|
isBuiltinType(rt uintptr) bool
|
|
isBuiltinType(rt uintptr) bool
|
|
|
- decodeBuiltinType(rt uintptr, rv reflect.Value)
|
|
|
|
|
- //decodeNaked should completely handle extensions, builtins, primitives, etc.
|
|
|
|
|
- //Numbers are decoded as int64, uint64, float64 only (no smaller sized number types).
|
|
|
|
|
- decodeNaked() (rv reflect.Value, ctx decodeNakedContext)
|
|
|
|
|
|
|
+ decodeBuiltin(rt uintptr, v interface{})
|
|
|
|
|
+ //decodeNaked: Numbers are decoded as int64, uint64, float64 only (no smaller sized number types).
|
|
|
|
|
+ decodeNaked() (v interface{}, vt valueType, decodeFurther bool)
|
|
|
decodeInt(bitsize uint8) (i int64)
|
|
decodeInt(bitsize uint8) (i int64)
|
|
|
decodeUint(bitsize uint8) (ui uint64)
|
|
decodeUint(bitsize uint8) (ui uint64)
|
|
|
decodeFloat(chkOverflow32 bool) (f float64)
|
|
decodeFloat(chkOverflow32 bool) (f float64)
|
|
@@ -75,33 +46,139 @@ type decDriver interface {
|
|
|
readArrayLen() int
|
|
readArrayLen() int
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// decFnInfo has methods for registering handling decoding of a specific type
|
|
|
|
|
-// based on some characteristics (builtin, extension, reflect Kind, etc)
|
|
|
|
|
-type decFnInfo struct {
|
|
|
|
|
- ti *typeInfo
|
|
|
|
|
- d *Decoder
|
|
|
|
|
- dd decDriver
|
|
|
|
|
- xfFn func(reflect.Value, []byte) error
|
|
|
|
|
- xfTag byte
|
|
|
|
|
|
|
+type DecodeOptions struct {
|
|
|
|
|
+ // An instance of MapType is used during schema-less decoding of a map in the stream.
|
|
|
|
|
+ // If nil, we use map[interface{}]interface{}
|
|
|
|
|
+ MapType reflect.Type
|
|
|
|
|
+ // An instance of SliceType is used during schema-less decoding of an array in the stream.
|
|
|
|
|
+ // If nil, we use []interface{}
|
|
|
|
|
+ SliceType reflect.Type
|
|
|
|
|
+ // ErrorIfNoField controls whether an error is returned when decoding a map
|
|
|
|
|
+ // from a codec stream into a struct, and no matching struct field is found.
|
|
|
|
|
+ ErrorIfNoField bool
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type decFn struct {
|
|
|
|
|
- i *decFnInfo
|
|
|
|
|
- f func(*decFnInfo, reflect.Value)
|
|
|
|
|
|
|
+// ------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+// ioDecReader is a decReader that reads off an io.Reader
|
|
|
|
|
+type ioDecReader struct {
|
|
|
|
|
+ r io.Reader
|
|
|
|
|
+ br io.ByteReader
|
|
|
|
|
+ x [8]byte //temp byte array re-used internally for efficiency
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// A Decoder reads and decodes an object from an input stream in the codec format.
|
|
|
|
|
-type Decoder struct {
|
|
|
|
|
- r decReader
|
|
|
|
|
- d decDriver
|
|
|
|
|
- h decodeHandleI
|
|
|
|
|
- f map[uintptr]decFn
|
|
|
|
|
- x []uintptr
|
|
|
|
|
- s []decFn
|
|
|
|
|
|
|
+func (z *ioDecReader) readn(n int) (bs []byte) {
|
|
|
|
|
+ bs = make([]byte, n)
|
|
|
|
|
+ if _, err := io.ReadAtLeast(z.r, bs, n); err != nil {
|
|
|
|
|
+ panic(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *ioDecReader) readb(bs []byte) {
|
|
|
|
|
+ if _, err := io.ReadAtLeast(z.r, bs, len(bs)); err != nil {
|
|
|
|
|
+ panic(err)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *ioDecReader) readn1() uint8 {
|
|
|
|
|
+ if z.br != nil {
|
|
|
|
|
+ b, err := z.br.ReadByte()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ panic(err)
|
|
|
|
|
+ }
|
|
|
|
|
+ return b
|
|
|
|
|
+ }
|
|
|
|
|
+ z.readb(z.x[:1])
|
|
|
|
|
+ return z.x[0]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *ioDecReader) readUint16() uint16 {
|
|
|
|
|
+ z.readb(z.x[:2])
|
|
|
|
|
+ return bigen.Uint16(z.x[:2])
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *ioDecReader) readUint32() uint32 {
|
|
|
|
|
+ z.readb(z.x[:4])
|
|
|
|
|
+ return bigen.Uint32(z.x[:4])
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *ioDecReader) readUint64() uint64 {
|
|
|
|
|
+ z.readb(z.x[:8])
|
|
|
|
|
+ return bigen.Uint64(z.x[:8])
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+// bytesDecReader is a decReader that reads off a byte slice with zero copying
|
|
|
|
|
+type bytesDecReader struct {
|
|
|
|
|
+ b []byte // data
|
|
|
|
|
+ c int // cursor
|
|
|
|
|
+ a int // available
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *bytesDecReader) consume(n int) (oldcursor int) {
|
|
|
|
|
+ if z.a == 0 {
|
|
|
|
|
+ panic(io.EOF)
|
|
|
|
|
+ }
|
|
|
|
|
+ if n > z.a {
|
|
|
|
|
+ decErr("Trying to read %v bytes. Only %v available", n, z.a)
|
|
|
|
|
+ }
|
|
|
|
|
+ // z.checkAvailable(n)
|
|
|
|
|
+ oldcursor = z.c
|
|
|
|
|
+ z.c = oldcursor + n
|
|
|
|
|
+ z.a = z.a - n
|
|
|
|
|
+ return
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *bytesDecReader) readn(n int) (bs []byte) {
|
|
|
|
|
+ c0 := z.consume(n)
|
|
|
|
|
+ bs = z.b[c0:z.c]
|
|
|
|
|
+ return
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *bytesDecReader) readb(bs []byte) {
|
|
|
|
|
+ copy(bs, z.readn(len(bs)))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *bytesDecReader) readn1() uint8 {
|
|
|
|
|
+ c0 := z.consume(1)
|
|
|
|
|
+ return z.b[c0]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Use binaryEncoding helper for 4 and 8 bits, but inline it for 2 bits
|
|
|
|
|
+// creating temp slice variable and copying it to helper function is expensive
|
|
|
|
|
+// for just 2 bits.
|
|
|
|
|
+
|
|
|
|
|
+func (z *bytesDecReader) readUint16() uint16 {
|
|
|
|
|
+ c0 := z.consume(2)
|
|
|
|
|
+ return uint16(z.b[c0+1]) | uint16(z.b[c0])<<8
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *bytesDecReader) readUint32() uint32 {
|
|
|
|
|
+ c0 := z.consume(4)
|
|
|
|
|
+ return bigen.Uint32(z.b[c0:z.c])
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (z *bytesDecReader) readUint64() uint64 {
|
|
|
|
|
+ c0 := z.consume(8)
|
|
|
|
|
+ return bigen.Uint64(z.b[c0:z.c])
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ------------------------------------
|
|
|
|
|
+
|
|
|
|
|
+// decFnInfo has methods for registering handling decoding of a specific type
|
|
|
|
|
+// based on some characteristics (builtin, extension, reflect Kind, etc)
|
|
|
|
|
+type decFnInfo struct {
|
|
|
|
|
+ ti *typeInfo
|
|
|
|
|
+ d *Decoder
|
|
|
|
|
+ dd decDriver
|
|
|
|
|
+ xfFn func(reflect.Value, []byte) error
|
|
|
|
|
+ xfTag byte
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (f *decFnInfo) builtin(rv reflect.Value) {
|
|
func (f *decFnInfo) builtin(rv reflect.Value) {
|
|
|
- f.dd.decodeBuiltinType(f.ti.rtid, rv)
|
|
|
|
|
|
|
+ f.dd.decodeBuiltin(f.ti.rtid, rv.Addr().Interface())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (f *decFnInfo) rawExt(rv reflect.Value) {
|
|
func (f *decFnInfo) rawExt(rv reflect.Value) {
|
|
@@ -207,38 +284,80 @@ func (f *decFnInfo) kUint16(rv reflect.Value) {
|
|
|
// }
|
|
// }
|
|
|
|
|
|
|
|
func (f *decFnInfo) kInterface(rv reflect.Value) {
|
|
func (f *decFnInfo) kInterface(rv reflect.Value) {
|
|
|
- if rv.IsNil() {
|
|
|
|
|
- // if nil interface, use some hieristics to set the nil interface to an
|
|
|
|
|
- // appropriate value based on the first byte read (byte descriptor bd)
|
|
|
|
|
- rv2, ndesc := f.dd.decodeNaked()
|
|
|
|
|
- if ndesc == dncNil {
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ // debugf("\t===> kInterface")
|
|
|
|
|
+ if !rv.IsNil() {
|
|
|
|
|
+ f.d.decodeValue(rv.Elem())
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ // nil interface:
|
|
|
|
|
+ // use some hieristics to set the nil interface to an
|
|
|
|
|
+ // appropriate value based on the first byte read (byte descriptor bd)
|
|
|
|
|
+ v, vt, decodeFurther := f.dd.decodeNaked()
|
|
|
|
|
+ if vt == valueTypeNil {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ // Cannot decode into nil interface with methods (e.g. error, io.Reader, etc)
|
|
|
|
|
+ // if non-nil value in stream.
|
|
|
|
|
+ if num := f.ti.rt.NumMethod(); num > 0 {
|
|
|
|
|
+ decErr("decodeValue: Cannot decode non-nil codec value into nil %v (%v methods)",
|
|
|
|
|
+ f.ti.rt, num)
|
|
|
|
|
+ }
|
|
|
|
|
+ var rvn reflect.Value
|
|
|
|
|
+ var useRvn bool
|
|
|
|
|
+ switch vt {
|
|
|
|
|
+ case valueTypeMap:
|
|
|
|
|
+ if f.d.h.MapType == nil {
|
|
|
|
|
+ var m2 map[interface{}]interface{}
|
|
|
|
|
+ v = &m2
|
|
|
|
|
+ } else {
|
|
|
|
|
+ rvn = reflect.New(f.d.h.MapType).Elem()
|
|
|
|
|
+ useRvn = true
|
|
|
}
|
|
}
|
|
|
- // Cannot decode into nil interface with methods (e.g. error, io.Reader, etc)
|
|
|
|
|
- // if non-nil value in stream.
|
|
|
|
|
- if num := f.ti.rt.NumMethod(); num > 0 {
|
|
|
|
|
- decErr("decodeValue: Cannot decode non-nil codec value into nil %v (%v methods)",
|
|
|
|
|
- f.ti.rt , num)
|
|
|
|
|
- }
|
|
|
|
|
- if ndesc == dncHandled {
|
|
|
|
|
- rv.Set(rv2)
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ case valueTypeArray:
|
|
|
|
|
+ if f.d.h.SliceType == nil {
|
|
|
|
|
+ var m2 []interface{}
|
|
|
|
|
+ v = &m2
|
|
|
|
|
+ } else {
|
|
|
|
|
+ rvn = reflect.New(f.d.h.SliceType).Elem()
|
|
|
|
|
+ useRvn = true
|
|
|
}
|
|
}
|
|
|
- f.d.decodeValue(rv2)
|
|
|
|
|
- rv.Set(rv2)
|
|
|
|
|
- } else {
|
|
|
|
|
- f.d.decodeValue(rv.Elem())
|
|
|
|
|
|
|
+ case valueTypeExt:
|
|
|
|
|
+ re := v.(*RawExt)
|
|
|
|
|
+ var bfn func(reflect.Value, []byte) error
|
|
|
|
|
+ rvn, bfn = f.d.h.getDecodeExtForTag(re.Tag)
|
|
|
|
|
+ if bfn == nil {
|
|
|
|
|
+ rvn = reflect.ValueOf(*re)
|
|
|
|
|
+ } else if fnerr := bfn(rvn, re.Data); fnerr != nil {
|
|
|
|
|
+ panic(fnerr)
|
|
|
|
|
+ }
|
|
|
|
|
+ rv.Set(rvn)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if decodeFurther {
|
|
|
|
|
+ if useRvn {
|
|
|
|
|
+ f.d.decodeValue(rvn)
|
|
|
|
|
+ } else if v != nil {
|
|
|
|
|
+ // this v is a pointer, so we need to dereference it when done
|
|
|
|
|
+ f.d.decode(v)
|
|
|
|
|
+ rvn = reflect.ValueOf(v).Elem()
|
|
|
|
|
+ useRvn = true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if useRvn {
|
|
|
|
|
+ rv.Set(rvn)
|
|
|
|
|
+ } else if v != nil {
|
|
|
|
|
+ rv.Set(reflect.ValueOf(v))
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (f *decFnInfo) kStruct(rv reflect.Value) {
|
|
func (f *decFnInfo) kStruct(rv reflect.Value) {
|
|
|
fti := f.ti
|
|
fti := f.ti
|
|
|
- if currEncodedType := f.dd.currentEncodedType(); currEncodedType == detMap {
|
|
|
|
|
|
|
+ if currEncodedType := f.dd.currentEncodedType(); currEncodedType == valueTypeMap {
|
|
|
containerLen := f.dd.readMapLen()
|
|
containerLen := f.dd.readMapLen()
|
|
|
if containerLen == 0 {
|
|
if containerLen == 0 {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
- tisfi := fti.sfi
|
|
|
|
|
|
|
+ tisfi := fti.sfi
|
|
|
for j := 0; j < containerLen; j++ {
|
|
for j := 0; j < containerLen; j++ {
|
|
|
// var rvkencname string
|
|
// var rvkencname string
|
|
|
// ddecode(&rvkencname)
|
|
// ddecode(&rvkencname)
|
|
@@ -254,8 +373,8 @@ func (f *decFnInfo) kStruct(rv reflect.Value) {
|
|
|
}
|
|
}
|
|
|
// f.d.decodeValue(ti.field(k, rv))
|
|
// f.d.decodeValue(ti.field(k, rv))
|
|
|
} else {
|
|
} else {
|
|
|
- if f.d.h.errorIfNoField() {
|
|
|
|
|
- decErr("No matching struct field found when decoding stream map with key: %v",
|
|
|
|
|
|
|
+ if f.d.h.ErrorIfNoField {
|
|
|
|
|
+ decErr("No matching struct field found when decoding stream map with key: %v",
|
|
|
rvkencname)
|
|
rvkencname)
|
|
|
} else {
|
|
} else {
|
|
|
var nilintf0 interface{}
|
|
var nilintf0 interface{}
|
|
@@ -263,7 +382,7 @@ func (f *decFnInfo) kStruct(rv reflect.Value) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- } else if currEncodedType == detArray {
|
|
|
|
|
|
|
+ } else if currEncodedType == valueTypeArray {
|
|
|
containerLen := f.dd.readArrayLen()
|
|
containerLen := f.dd.readArrayLen()
|
|
|
if containerLen == 0 {
|
|
if containerLen == 0 {
|
|
|
return
|
|
return
|
|
@@ -286,7 +405,7 @@ func (f *decFnInfo) kStruct(rv reflect.Value) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- decErr("Only encoded map or array can be decoded into a struct. (decodeEncodedType: %x)",
|
|
|
|
|
|
|
+ decErr("Only encoded map or array can be decoded into a struct. (valueType: %x)",
|
|
|
currEncodedType)
|
|
currEncodedType)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -296,6 +415,24 @@ func (f *decFnInfo) kSlice(rv reflect.Value) {
|
|
|
// may have come in here (which may not be settable).
|
|
// may have come in here (which may not be settable).
|
|
|
// In places where the slice got from an array could be, we should guard with CanSet() calls.
|
|
// In places where the slice got from an array could be, we should guard with CanSet() calls.
|
|
|
|
|
|
|
|
|
|
+ // A slice can be set from a map or array in stream.
|
|
|
|
|
+
|
|
|
|
|
+ if shortCircuitReflectToFastPath {
|
|
|
|
|
+ if rv.CanAddr() {
|
|
|
|
|
+ switch f.ti.rtid {
|
|
|
|
|
+ case intfSliceTypId:
|
|
|
|
|
+ f.d.decSliceIntf(rv.Addr().Interface().(*[]interface{}))
|
|
|
|
|
+ return
|
|
|
|
|
+ case intSliceTypId:
|
|
|
|
|
+ f.d.decSliceInt(rv.Addr().Interface().(*[]int))
|
|
|
|
|
+ return
|
|
|
|
|
+ case strSliceTypId:
|
|
|
|
|
+ f.d.decSliceStr(rv.Addr().Interface().(*[]string))
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if f.ti.rtid == byteSliceTypId { // rawbytes
|
|
if f.ti.rtid == byteSliceTypId { // rawbytes
|
|
|
if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 {
|
|
if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 {
|
|
|
rv.SetBytes(bs2)
|
|
rv.SetBytes(bs2)
|
|
@@ -303,57 +440,83 @@ func (f *decFnInfo) kSlice(rv reflect.Value) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- containerLen := f.dd.readArrayLen()
|
|
|
|
|
|
|
+ containerLen, containerLenS := decContLens(f.dd)
|
|
|
|
|
|
|
|
if rv.IsNil() {
|
|
if rv.IsNil() {
|
|
|
- rv.Set(reflect.MakeSlice(f.ti.rt, containerLen, containerLen))
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ rv.Set(reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS))
|
|
|
|
|
+ }
|
|
|
if containerLen == 0 {
|
|
if containerLen == 0 {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// if we need to reset rv but it cannot be set, we should err out.
|
|
// if we need to reset rv but it cannot be set, we should err out.
|
|
|
// for example, if slice is got from unaddressable array, CanSet = false
|
|
// for example, if slice is got from unaddressable array, CanSet = false
|
|
|
- if rvcap, rvlen := rv.Len(), rv.Cap(); containerLen > rvcap {
|
|
|
|
|
|
|
+ if rvcap, rvlen := rv.Len(), rv.Cap(); containerLenS > rvcap {
|
|
|
if rv.CanSet() {
|
|
if rv.CanSet() {
|
|
|
- rvn := reflect.MakeSlice(f.ti.rt, containerLen, containerLen)
|
|
|
|
|
|
|
+ rvn := reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS)
|
|
|
if rvlen > 0 {
|
|
if rvlen > 0 {
|
|
|
reflect.Copy(rvn, rv)
|
|
reflect.Copy(rvn, rv)
|
|
|
}
|
|
}
|
|
|
rv.Set(rvn)
|
|
rv.Set(rvn)
|
|
|
} else {
|
|
} else {
|
|
|
- decErr("Cannot reset slice with less cap: %v than stream contents: %v",
|
|
|
|
|
- rvcap, containerLen)
|
|
|
|
|
|
|
+ decErr("Cannot reset slice with less cap: %v than stream contents: %v",
|
|
|
|
|
+ rvcap, containerLenS)
|
|
|
}
|
|
}
|
|
|
- } else if containerLen > rvlen {
|
|
|
|
|
- rv.SetLen(containerLen)
|
|
|
|
|
|
|
+ } else if containerLenS > rvlen {
|
|
|
|
|
+ rv.SetLen(containerLenS)
|
|
|
}
|
|
}
|
|
|
- for j := 0; j < containerLen; j++ {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ for j := 0; j < containerLenS; j++ {
|
|
|
f.d.decodeValue(rv.Index(j))
|
|
f.d.decodeValue(rv.Index(j))
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (f *decFnInfo) kArray(rv reflect.Value) {
|
|
func (f *decFnInfo) kArray(rv reflect.Value) {
|
|
|
- f.d.decodeValue(rv.Slice(0, rv.Len()))
|
|
|
|
|
|
|
+ // f.d.decodeValue(rv.Slice(0, rv.Len()))
|
|
|
|
|
+ f.kSlice(rv.Slice(0, rv.Len()))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (f *decFnInfo) kMap(rv reflect.Value) {
|
|
func (f *decFnInfo) kMap(rv reflect.Value) {
|
|
|
|
|
+ // debugf("\t=> kMap: rv: %v", rv)
|
|
|
|
|
+ if shortCircuitReflectToFastPath {
|
|
|
|
|
+ if rv.CanAddr() {
|
|
|
|
|
+ switch f.ti.rtid {
|
|
|
|
|
+ case mapStringIntfTypId:
|
|
|
|
|
+ f.d.decMapStrIntf(rv.Addr().Interface().(*map[string]interface{}))
|
|
|
|
|
+ return
|
|
|
|
|
+ case mapIntfIntfTypId:
|
|
|
|
|
+ f.d.decMapIntfIntf(rv.Addr().Interface().(*map[interface{}]interface{}))
|
|
|
|
|
+ return
|
|
|
|
|
+ case mapIntIntfTypId:
|
|
|
|
|
+ f.d.decMapIntIntf(rv.Addr().Interface().(*map[int]interface{}))
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
containerLen := f.dd.readMapLen()
|
|
containerLen := f.dd.readMapLen()
|
|
|
|
|
+ // defer func() {
|
|
|
|
|
+ // if rv.CanInterface() {
|
|
|
|
|
+ // debugf("\t=> kMap: containerLen: %v, rv.I: %v", containerLen, rv.Interface())
|
|
|
|
|
+ // }
|
|
|
|
|
+ // }()
|
|
|
|
|
|
|
|
if rv.IsNil() {
|
|
if rv.IsNil() {
|
|
|
rv.Set(reflect.MakeMap(f.ti.rt))
|
|
rv.Set(reflect.MakeMap(f.ti.rt))
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if containerLen == 0 {
|
|
if containerLen == 0 {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ktype, vtype := f.ti.rt.Key(), f.ti.rt.Elem()
|
|
ktype, vtype := f.ti.rt.Key(), f.ti.rt.Elem()
|
|
|
|
|
+ ktypeId := reflect.ValueOf(ktype).Pointer()
|
|
|
for j := 0; j < containerLen; j++ {
|
|
for j := 0; j < containerLen; j++ {
|
|
|
rvk := reflect.New(ktype).Elem()
|
|
rvk := reflect.New(ktype).Elem()
|
|
|
f.d.decodeValue(rvk)
|
|
f.d.decodeValue(rvk)
|
|
|
|
|
|
|
|
- if ktype == intfTyp {
|
|
|
|
|
|
|
+ // if ktype == intfTyp {
|
|
|
|
|
+ if ktypeId == intfTypId {
|
|
|
rvk = rvk.Elem()
|
|
rvk = rvk.Elem()
|
|
|
if rvk.Type() == byteSliceTyp {
|
|
if rvk.Type() == byteSliceTyp {
|
|
|
rvk = reflect.ValueOf(string(rvk.Bytes()))
|
|
rvk = reflect.ValueOf(string(rvk.Bytes()))
|
|
@@ -369,51 +532,33 @@ func (f *decFnInfo) kMap(rv reflect.Value) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// ioDecReader is a decReader that reads off an io.Reader
|
|
|
|
|
-type ioDecReader struct {
|
|
|
|
|
- r io.Reader
|
|
|
|
|
- br io.ByteReader
|
|
|
|
|
- x [8]byte //temp byte array re-used internally for efficiency
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// bytesDecReader is a decReader that reads off a byte slice with zero copying
|
|
|
|
|
-type bytesDecReader struct {
|
|
|
|
|
- b []byte // data
|
|
|
|
|
- c int // cursor
|
|
|
|
|
- a int // available
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-type decodeHandleI interface {
|
|
|
|
|
- getDecodeExt(rt uintptr) (tag byte, fn func(reflect.Value, []byte) error)
|
|
|
|
|
- errorIfNoField() bool
|
|
|
|
|
-}
|
|
|
|
|
|
|
+// ----------------------------------------
|
|
|
|
|
|
|
|
-type DecodeOptions struct {
|
|
|
|
|
- // An instance of MapType is used during schema-less decoding of a map in the stream.
|
|
|
|
|
- // If nil, we use map[interface{}]interface{}
|
|
|
|
|
- MapType reflect.Type
|
|
|
|
|
- // An instance of SliceType is used during schema-less decoding of an array in the stream.
|
|
|
|
|
- // If nil, we use []interface{}
|
|
|
|
|
- SliceType reflect.Type
|
|
|
|
|
- // ErrorIfNoField controls whether an error is returned when decoding a map
|
|
|
|
|
- // from a codec stream into a struct, and no matching struct field is found.
|
|
|
|
|
- ErrorIfNoField bool
|
|
|
|
|
|
|
+type decFn struct {
|
|
|
|
|
+ i *decFnInfo
|
|
|
|
|
+ f func(*decFnInfo, reflect.Value)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (o *DecodeOptions) errorIfNoField() bool {
|
|
|
|
|
- return o.ErrorIfNoField
|
|
|
|
|
|
|
+// A Decoder reads and decodes an object from an input stream in the codec format.
|
|
|
|
|
+type Decoder struct {
|
|
|
|
|
+ r decReader
|
|
|
|
|
+ d decDriver
|
|
|
|
|
+ h *BasicHandle
|
|
|
|
|
+ f map[uintptr]decFn
|
|
|
|
|
+ x []uintptr
|
|
|
|
|
+ s []decFn
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// NewDecoder returns a Decoder for decoding a stream of bytes from an io.Reader.
|
|
// NewDecoder returns a Decoder for decoding a stream of bytes from an io.Reader.
|
|
|
-//
|
|
|
|
|
|
|
+//
|
|
|
// For efficiency, Users are encouraged to pass in a memory buffered writer
|
|
// For efficiency, Users are encouraged to pass in a memory buffered writer
|
|
|
-// (eg bufio.Reader, bytes.Buffer).
|
|
|
|
|
|
|
+// (eg bufio.Reader, bytes.Buffer).
|
|
|
func NewDecoder(r io.Reader, h Handle) *Decoder {
|
|
func NewDecoder(r io.Reader, h Handle) *Decoder {
|
|
|
z := ioDecReader{
|
|
z := ioDecReader{
|
|
|
r: r,
|
|
r: r,
|
|
|
}
|
|
}
|
|
|
z.br, _ = r.(io.ByteReader)
|
|
z.br, _ = r.(io.ByteReader)
|
|
|
- return &Decoder{r: &z, d: h.newDecDriver(&z), h: h}
|
|
|
|
|
|
|
+ return &Decoder{r: &z, d: h.newDecDriver(&z), h: h.getBasicHandle()}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// NewDecoderBytes returns a Decoder which efficiently decodes directly
|
|
// NewDecoderBytes returns a Decoder which efficiently decodes directly
|
|
@@ -423,7 +568,7 @@ func NewDecoderBytes(in []byte, h Handle) *Decoder {
|
|
|
b: in,
|
|
b: in,
|
|
|
a: len(in),
|
|
a: len(in),
|
|
|
}
|
|
}
|
|
|
- return &Decoder{r: &z, d: h.newDecDriver(&z), h: h}
|
|
|
|
|
|
|
+ return &Decoder{r: &z, d: h.newDecDriver(&z), h: h.getBasicHandle()}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Decode decodes the stream from reader and stores the result in the
|
|
// Decode decodes the stream from reader and stores the result in the
|
|
@@ -433,7 +578,7 @@ func NewDecoderBytes(in []byte, h Handle) *Decoder {
|
|
|
// Note that a pointer to a nil interface is not a nil pointer.
|
|
// Note that a pointer to a nil interface is not a nil pointer.
|
|
|
// If you do not know what type of stream it is, pass in a pointer to a nil interface.
|
|
// If you do not know what type of stream it is, pass in a pointer to a nil interface.
|
|
|
// We will decode and store a value in that nil interface.
|
|
// We will decode and store a value in that nil interface.
|
|
|
-//
|
|
|
|
|
|
|
+//
|
|
|
// Sample usages:
|
|
// Sample usages:
|
|
|
// // Decoding into a non-nil typed value
|
|
// // Decoding into a non-nil typed value
|
|
|
// var f float32
|
|
// var f float32
|
|
@@ -443,32 +588,39 @@ func NewDecoderBytes(in []byte, h Handle) *Decoder {
|
|
|
// var v interface{}
|
|
// var v interface{}
|
|
|
// dec := codec.NewDecoder(r, handle)
|
|
// dec := codec.NewDecoder(r, handle)
|
|
|
// err = dec.Decode(&v)
|
|
// err = dec.Decode(&v)
|
|
|
-//
|
|
|
|
|
|
|
+//
|
|
|
// When decoding into a nil interface{}, we will decode into an appropriate value based
|
|
// When decoding into a nil interface{}, we will decode into an appropriate value based
|
|
|
// on the contents of the stream:
|
|
// on the contents of the stream:
|
|
|
-// - Numbers are decoded as float64, int64 or uint64.
|
|
|
|
|
-// - Other values are decoded appropriately depending on the encoding:
|
|
|
|
|
|
|
+// - Numbers are decoded as float64, int64 or uint64.
|
|
|
|
|
+// - Other values are decoded appropriately depending on the type:
|
|
|
// bool, string, []byte, time.Time, etc
|
|
// bool, string, []byte, time.Time, etc
|
|
|
// - Extensions are decoded as RawExt (if no ext function registered for the tag)
|
|
// - Extensions are decoded as RawExt (if no ext function registered for the tag)
|
|
|
-// Configurations exist on the Handle to override defaults
|
|
|
|
|
|
|
+// Configurations exist on the Handle to override defaults
|
|
|
// (e.g. for MapType, SliceType and how to decode raw bytes).
|
|
// (e.g. for MapType, SliceType and how to decode raw bytes).
|
|
|
-//
|
|
|
|
|
-// When decoding into a non-nil interface{} value, the mode of encoding is based on the
|
|
|
|
|
|
|
+//
|
|
|
|
|
+// When decoding into a non-nil interface{} value, the mode of encoding is based on the
|
|
|
// type of the value. When a value is seen:
|
|
// type of the value. When a value is seen:
|
|
|
// - If an extension is registered for it, call that extension function
|
|
// - If an extension is registered for it, call that extension function
|
|
|
// - If it implements BinaryUnmarshaler, call its UnmarshalBinary(data []byte) error
|
|
// - If it implements BinaryUnmarshaler, call its UnmarshalBinary(data []byte) error
|
|
|
// - Else decode it based on its reflect.Kind
|
|
// - Else decode it based on its reflect.Kind
|
|
|
-//
|
|
|
|
|
|
|
+//
|
|
|
// There are some special rules when decoding into containers (slice/array/map/struct).
|
|
// There are some special rules when decoding into containers (slice/array/map/struct).
|
|
|
-// Decode will typically use the stream contents to UPDATE the container.
|
|
|
|
|
-// - This means that for a struct or map, we just update matching fields or keys.
|
|
|
|
|
-// - For a slice/array, we just update the first n elements, where n is length of the stream.
|
|
|
|
|
-// - However, if decoding into a nil map/slice and the length of the stream is 0,
|
|
|
|
|
-// we reset the destination map/slice to be a zero-length non-nil map/slice.
|
|
|
|
|
-// - Also, if the encoded value is Nil in the stream, then we try to set
|
|
|
|
|
-// the container to its "zero" value (e.g. nil for slice/map).
|
|
|
|
|
-// - Note that a struct can be decoded from an array in the stream,
|
|
|
|
|
-// by updating fields as they occur in the struct.
|
|
|
|
|
|
|
+// Decode will typically use the stream contents to UPDATE the container.
|
|
|
|
|
+// - A map can be decoded from a stream map, by updating matching keys.
|
|
|
|
|
+// - A slice can be decoded from a stream array,
|
|
|
|
|
+// by updating the first n elements, where n is length of the stream.
|
|
|
|
|
+// - A slice can be decoded from a stream map, by decoding as if
|
|
|
|
|
+// it contains a sequence of key-value pairs.
|
|
|
|
|
+// - A struct can be decoded from a stream map, by updating matching fields.
|
|
|
|
|
+// - A struct can be decoded from a stream array,
|
|
|
|
|
+// by updating fields as they occur in the struct (by index).
|
|
|
|
|
+//
|
|
|
|
|
+// When decoding a stream map or array with length of 0 into a nil map or slice,
|
|
|
|
|
+// we reset the destination map or slice to a zero-length value.
|
|
|
|
|
+//
|
|
|
|
|
+// However, when decoding a stream nil, we reset the destination container
|
|
|
|
|
+// to its "zero" value (e.g. nil for slice/map, etc).
|
|
|
|
|
+//
|
|
|
func (d *Decoder) Decode(v interface{}) (err error) {
|
|
func (d *Decoder) Decode(v interface{}) (err error) {
|
|
|
defer panicToErr(&err)
|
|
defer panicToErr(&err)
|
|
|
d.decode(v)
|
|
d.decode(v)
|
|
@@ -478,13 +630,14 @@ func (d *Decoder) Decode(v interface{}) (err error) {
|
|
|
func (d *Decoder) decode(iv interface{}) {
|
|
func (d *Decoder) decode(iv interface{}) {
|
|
|
d.d.initReadNext()
|
|
d.d.initReadNext()
|
|
|
|
|
|
|
|
- // Fast path included for various pointer types which cannot be registered as extensions
|
|
|
|
|
switch v := iv.(type) {
|
|
switch v := iv.(type) {
|
|
|
case nil:
|
|
case nil:
|
|
|
decErr("Cannot decode into nil.")
|
|
decErr("Cannot decode into nil.")
|
|
|
|
|
+
|
|
|
case reflect.Value:
|
|
case reflect.Value:
|
|
|
d.chkPtrValue(v)
|
|
d.chkPtrValue(v)
|
|
|
d.decodeValue(v)
|
|
d.decodeValue(v)
|
|
|
|
|
+
|
|
|
case *string:
|
|
case *string:
|
|
|
*v = d.d.decodeString()
|
|
*v = d.d.decodeString()
|
|
|
case *bool:
|
|
case *bool:
|
|
@@ -498,7 +651,7 @@ func (d *Decoder) decode(iv interface{}) {
|
|
|
case *int32:
|
|
case *int32:
|
|
|
*v = int32(d.d.decodeInt(32))
|
|
*v = int32(d.d.decodeInt(32))
|
|
|
case *int64:
|
|
case *int64:
|
|
|
- *v = int64(d.d.decodeInt(64))
|
|
|
|
|
|
|
+ *v = d.d.decodeInt(64)
|
|
|
case *uint:
|
|
case *uint:
|
|
|
*v = uint(d.d.decodeUint(uintBitsize))
|
|
*v = uint(d.d.decodeUint(uintBitsize))
|
|
|
case *uint8:
|
|
case *uint8:
|
|
@@ -508,13 +661,31 @@ func (d *Decoder) decode(iv interface{}) {
|
|
|
case *uint32:
|
|
case *uint32:
|
|
|
*v = uint32(d.d.decodeUint(32))
|
|
*v = uint32(d.d.decodeUint(32))
|
|
|
case *uint64:
|
|
case *uint64:
|
|
|
- *v = uint64(d.d.decodeUint(64))
|
|
|
|
|
|
|
+ *v = d.d.decodeUint(64)
|
|
|
case *float32:
|
|
case *float32:
|
|
|
*v = float32(d.d.decodeFloat(true))
|
|
*v = float32(d.d.decodeFloat(true))
|
|
|
case *float64:
|
|
case *float64:
|
|
|
*v = d.d.decodeFloat(false)
|
|
*v = d.d.decodeFloat(false)
|
|
|
|
|
+ case *[]byte:
|
|
|
|
|
+ v2 := *v
|
|
|
|
|
+ *v, _ = d.d.decodeBytes(v2)
|
|
|
|
|
+
|
|
|
|
|
+ case *[]interface{}:
|
|
|
|
|
+ d.decSliceIntf(v)
|
|
|
|
|
+ case *[]int:
|
|
|
|
|
+ d.decSliceInt(v)
|
|
|
|
|
+ case *[]string:
|
|
|
|
|
+ d.decSliceStr(v)
|
|
|
|
|
+ case *map[string]interface{}:
|
|
|
|
|
+ d.decMapStrIntf(v)
|
|
|
|
|
+ case *map[interface{}]interface{}:
|
|
|
|
|
+ d.decMapIntfIntf(v)
|
|
|
|
|
+ case *map[int]interface{}:
|
|
|
|
|
+ d.decMapIntIntf(v)
|
|
|
|
|
+
|
|
|
case *interface{}:
|
|
case *interface{}:
|
|
|
d.decodeValue(reflect.ValueOf(iv).Elem())
|
|
d.decodeValue(reflect.ValueOf(iv).Elem())
|
|
|
|
|
+
|
|
|
default:
|
|
default:
|
|
|
rv := reflect.ValueOf(iv)
|
|
rv := reflect.ValueOf(iv)
|
|
|
d.chkPtrValue(rv)
|
|
d.chkPtrValue(rv)
|
|
@@ -535,7 +706,7 @@ func (d *Decoder) decodeValue(rv reflect.Value) {
|
|
|
}
|
|
}
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// If stream is not containing a nil value, then we can deref to the base
|
|
// If stream is not containing a nil value, then we can deref to the base
|
|
|
// non-pointer value, and decode into that.
|
|
// non-pointer value, and decode into that.
|
|
|
for rv.Kind() == reflect.Ptr {
|
|
for rv.Kind() == reflect.Ptr {
|
|
@@ -544,17 +715,15 @@ func (d *Decoder) decodeValue(rv reflect.Value) {
|
|
|
}
|
|
}
|
|
|
rv = rv.Elem()
|
|
rv = rv.Elem()
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
rt := rv.Type()
|
|
rt := rv.Type()
|
|
|
rtid := reflect.ValueOf(rt).Pointer()
|
|
rtid := reflect.ValueOf(rt).Pointer()
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// retrieve or register a focus'ed function for this type
|
|
// retrieve or register a focus'ed function for this type
|
|
|
// to eliminate need to do the retrieval multiple times
|
|
// to eliminate need to do the retrieval multiple times
|
|
|
-
|
|
|
|
|
- // if d.f == nil && d.s == nil {
|
|
|
|
|
- // // debugf("---->Creating new dec f map for type: %v\n", rt)
|
|
|
|
|
- // }
|
|
|
|
|
- var fn decFn
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // if d.f == nil && d.s == nil { debugf("---->Creating new dec f map for type: %v\n", rt) }
|
|
|
|
|
+ var fn decFn
|
|
|
var ok bool
|
|
var ok bool
|
|
|
if useMapForCodecCache {
|
|
if useMapForCodecCache {
|
|
|
fn, ok = d.f[rtid]
|
|
fn, ok = d.f[rtid]
|
|
@@ -568,8 +737,8 @@ func (d *Decoder) decodeValue(rv reflect.Value) {
|
|
|
}
|
|
}
|
|
|
if !ok {
|
|
if !ok {
|
|
|
// debugf("\tCreating new dec fn for type: %v\n", rt)
|
|
// debugf("\tCreating new dec fn for type: %v\n", rt)
|
|
|
- fi := decFnInfo { ti:getTypeInfo(rtid, rt), d:d, dd:d.d }
|
|
|
|
|
- fn.i = &fi
|
|
|
|
|
|
|
+ fi := decFnInfo{ti: getTypeInfo(rtid, rt), d: d, dd: d.d}
|
|
|
|
|
+ fn.i = &fi
|
|
|
// An extension can be registered for any type, regardless of the Kind
|
|
// An extension can be registered for any type, regardless of the Kind
|
|
|
// (e.g. type BitSet int64, type MyStruct { / * unexported fields * / }, type X []int, etc.
|
|
// (e.g. type BitSet int64, type MyStruct { / * unexported fields * / }, type X []int, etc.
|
|
|
//
|
|
//
|
|
@@ -580,58 +749,58 @@ func (d *Decoder) decodeValue(rv reflect.Value) {
|
|
|
// NOTE: if decoding into a nil interface{}, we return a non-nil
|
|
// NOTE: if decoding into a nil interface{}, we return a non-nil
|
|
|
// value except even if the container registers a length of 0.
|
|
// value except even if the container registers a length of 0.
|
|
|
if rtid == rawExtTypId {
|
|
if rtid == rawExtTypId {
|
|
|
- fn.f = (*decFnInfo).rawExt
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).rawExt
|
|
|
} else if d.d.isBuiltinType(rtid) {
|
|
} else if d.d.isBuiltinType(rtid) {
|
|
|
- fn.f = (*decFnInfo).builtin
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).builtin
|
|
|
} else if xfTag, xfFn := d.h.getDecodeExt(rtid); xfFn != nil {
|
|
} else if xfTag, xfFn := d.h.getDecodeExt(rtid); xfFn != nil {
|
|
|
fi.xfTag, fi.xfFn = xfTag, xfFn
|
|
fi.xfTag, fi.xfFn = xfTag, xfFn
|
|
|
- fn.f = (*decFnInfo).ext
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).ext
|
|
|
} else if supportBinaryMarshal && fi.ti.unm {
|
|
} else if supportBinaryMarshal && fi.ti.unm {
|
|
|
- fn.f = (*decFnInfo).binaryMarshal
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).binaryMarshal
|
|
|
} else {
|
|
} else {
|
|
|
switch rk := rt.Kind(); rk {
|
|
switch rk := rt.Kind(); rk {
|
|
|
case reflect.String:
|
|
case reflect.String:
|
|
|
- fn.f = (*decFnInfo).kString
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kString
|
|
|
case reflect.Bool:
|
|
case reflect.Bool:
|
|
|
- fn.f = (*decFnInfo).kBool
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kBool
|
|
|
case reflect.Int:
|
|
case reflect.Int:
|
|
|
- fn.f = (*decFnInfo).kInt
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kInt
|
|
|
case reflect.Int64:
|
|
case reflect.Int64:
|
|
|
- fn.f = (*decFnInfo).kInt64
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kInt64
|
|
|
case reflect.Int32:
|
|
case reflect.Int32:
|
|
|
- fn.f = (*decFnInfo).kInt32
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kInt32
|
|
|
case reflect.Int8:
|
|
case reflect.Int8:
|
|
|
- fn.f = (*decFnInfo).kInt8
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kInt8
|
|
|
case reflect.Int16:
|
|
case reflect.Int16:
|
|
|
- fn.f = (*decFnInfo).kInt16
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kInt16
|
|
|
case reflect.Float32:
|
|
case reflect.Float32:
|
|
|
- fn.f = (*decFnInfo).kFloat32
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kFloat32
|
|
|
case reflect.Float64:
|
|
case reflect.Float64:
|
|
|
- fn.f = (*decFnInfo).kFloat64
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kFloat64
|
|
|
case reflect.Uint8:
|
|
case reflect.Uint8:
|
|
|
- fn.f = (*decFnInfo).kUint8
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kUint8
|
|
|
case reflect.Uint64:
|
|
case reflect.Uint64:
|
|
|
- fn.f = (*decFnInfo).kUint64
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kUint64
|
|
|
case reflect.Uint:
|
|
case reflect.Uint:
|
|
|
- fn.f = (*decFnInfo).kUint
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kUint
|
|
|
case reflect.Uint32:
|
|
case reflect.Uint32:
|
|
|
- fn.f = (*decFnInfo).kUint32
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kUint32
|
|
|
case reflect.Uint16:
|
|
case reflect.Uint16:
|
|
|
- fn.f = (*decFnInfo).kUint16
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kUint16
|
|
|
// case reflect.Ptr:
|
|
// case reflect.Ptr:
|
|
|
- // fn.f = (*decFnInfo).kPtr
|
|
|
|
|
|
|
+ // fn.f = (*decFnInfo).kPtr
|
|
|
case reflect.Interface:
|
|
case reflect.Interface:
|
|
|
- fn.f = (*decFnInfo).kInterface
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kInterface
|
|
|
case reflect.Struct:
|
|
case reflect.Struct:
|
|
|
- fn.f = (*decFnInfo).kStruct
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kStruct
|
|
|
case reflect.Slice:
|
|
case reflect.Slice:
|
|
|
- fn.f = (*decFnInfo).kSlice
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kSlice
|
|
|
case reflect.Array:
|
|
case reflect.Array:
|
|
|
- fn.f = (*decFnInfo).kArray
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kArray
|
|
|
case reflect.Map:
|
|
case reflect.Map:
|
|
|
- fn.f = (*decFnInfo).kMap
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kMap
|
|
|
default:
|
|
default:
|
|
|
- fn.f = (*decFnInfo).kErr
|
|
|
|
|
|
|
+ fn.f = (*decFnInfo).kErr
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if useMapForCodecCache {
|
|
if useMapForCodecCache {
|
|
@@ -644,9 +813,9 @@ func (d *Decoder) decodeValue(rv reflect.Value) {
|
|
|
d.x = append(d.x, rtid)
|
|
d.x = append(d.x, rtid)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
fn.f(fn.i, rv)
|
|
fn.f(fn.i, rv)
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -663,102 +832,128 @@ func (d *Decoder) chkPtrValue(rv reflect.Value) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// ------------------------------------
|
|
|
|
|
|
|
+// --------------------------------------------------
|
|
|
|
|
|
|
|
-func (z *ioDecReader) readn(n int) (bs []byte) {
|
|
|
|
|
- bs = make([]byte, n)
|
|
|
|
|
- if _, err := io.ReadAtLeast(z.r, bs, n); err != nil {
|
|
|
|
|
- panic(err)
|
|
|
|
|
- }
|
|
|
|
|
- return
|
|
|
|
|
-}
|
|
|
|
|
|
|
+// short circuit functions for common maps and slices
|
|
|
|
|
|
|
|
-func (z *ioDecReader) readb(bs []byte) {
|
|
|
|
|
- if _, err := io.ReadAtLeast(z.r, bs, len(bs)); err != nil {
|
|
|
|
|
- panic(err)
|
|
|
|
|
|
|
+func (d *Decoder) decSliceIntf(v *[]interface{}) {
|
|
|
|
|
+ _, containerLenS := decContLens(d.d)
|
|
|
|
|
+ s := *v
|
|
|
|
|
+ if s == nil {
|
|
|
|
|
+ s = make([]interface{}, containerLenS, containerLenS)
|
|
|
|
|
+ } else if containerLenS > cap(s) {
|
|
|
|
|
+ s = make([]interface{}, containerLenS, containerLenS)
|
|
|
|
|
+ copy(s, *v)
|
|
|
|
|
+ } else if containerLenS > len(s) {
|
|
|
|
|
+ s = s[:containerLenS]
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (z *ioDecReader) readn1() uint8 {
|
|
|
|
|
- if z.br != nil {
|
|
|
|
|
- b, err := z.br.ReadByte()
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- panic(err)
|
|
|
|
|
- }
|
|
|
|
|
- return b
|
|
|
|
|
|
|
+ // debugf("\t=> decSliceIntf: containerLenS: %v", containerLenS)
|
|
|
|
|
+ for j := 0; j < containerLenS; j++ {
|
|
|
|
|
+ // debugf("\t=> decSliceIntf: j: %v", j)
|
|
|
|
|
+ d.decode(&s[j])
|
|
|
}
|
|
}
|
|
|
- z.readb(z.x[:1])
|
|
|
|
|
- return z.x[0]
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (z *ioDecReader) readUint16() uint16 {
|
|
|
|
|
- z.readb(z.x[:2])
|
|
|
|
|
- return bigen.Uint16(z.x[:2])
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (z *ioDecReader) readUint32() uint32 {
|
|
|
|
|
- z.readb(z.x[:4])
|
|
|
|
|
- return bigen.Uint32(z.x[:4])
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (z *ioDecReader) readUint64() uint64 {
|
|
|
|
|
- z.readb(z.x[:8])
|
|
|
|
|
- return bigen.Uint64(z.x[:8])
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// ------------------------------------
|
|
|
|
|
-
|
|
|
|
|
-func (z *bytesDecReader) consume(n int) (oldcursor int) {
|
|
|
|
|
- if z.a == 0 {
|
|
|
|
|
- panic(io.EOF)
|
|
|
|
|
|
|
+ *v = s
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (d *Decoder) decSliceInt(v *[]int) {
|
|
|
|
|
+ _, containerLenS := decContLens(d.d)
|
|
|
|
|
+ s := *v
|
|
|
|
|
+ if s == nil {
|
|
|
|
|
+ s = make([]int, containerLenS, containerLenS)
|
|
|
|
|
+ } else if containerLenS > cap(s) {
|
|
|
|
|
+ s = make([]int, containerLenS, containerLenS)
|
|
|
|
|
+ copy(s, *v)
|
|
|
|
|
+ } else if containerLenS > len(s) {
|
|
|
|
|
+ s = s[:containerLenS]
|
|
|
}
|
|
}
|
|
|
- if n > z.a {
|
|
|
|
|
- decErr("Trying to read %v bytes. Only %v available", n, z.a)
|
|
|
|
|
|
|
+ for j := 0; j < containerLenS; j++ {
|
|
|
|
|
+ d.decode(&s[j])
|
|
|
}
|
|
}
|
|
|
- // z.checkAvailable(n)
|
|
|
|
|
- oldcursor = z.c
|
|
|
|
|
- z.c = oldcursor + n
|
|
|
|
|
- z.a = z.a - n
|
|
|
|
|
- return
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-func (z *bytesDecReader) readn(n int) (bs []byte) {
|
|
|
|
|
- c0 := z.consume(n)
|
|
|
|
|
- bs = z.b[c0:z.c]
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ *v = s
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (d *Decoder) decSliceStr(v *[]string) {
|
|
|
|
|
+ _, containerLenS := decContLens(d.d)
|
|
|
|
|
+ s := *v
|
|
|
|
|
+ if s == nil {
|
|
|
|
|
+ s = make([]string, containerLenS, containerLenS)
|
|
|
|
|
+ } else if containerLenS > cap(s) {
|
|
|
|
|
+ s = make([]string, containerLenS, containerLenS)
|
|
|
|
|
+ copy(s, *v)
|
|
|
|
|
+ } else if containerLenS > len(s) {
|
|
|
|
|
+ s = s[:containerLenS]
|
|
|
|
|
+ }
|
|
|
|
|
+ for j := 0; j < containerLenS; j++ {
|
|
|
|
|
+ d.decode(&s[j])
|
|
|
|
|
+ }
|
|
|
|
|
+ *v = s
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (z *bytesDecReader) readb(bs []byte) {
|
|
|
|
|
- copy(bs, z.readn(len(bs)))
|
|
|
|
|
|
|
+func (d *Decoder) decMapIntfIntf(v *map[interface{}]interface{}) {
|
|
|
|
|
+ containerLen := d.d.readMapLen()
|
|
|
|
|
+ m := *v
|
|
|
|
|
+ if m == nil {
|
|
|
|
|
+ m = make(map[interface{}]interface{}, containerLen)
|
|
|
|
|
+ *v = m
|
|
|
|
|
+ }
|
|
|
|
|
+ for j := 0; j < containerLen; j++ {
|
|
|
|
|
+ var mk interface{}
|
|
|
|
|
+ d.decode(&mk)
|
|
|
|
|
+ mv := m[mk]
|
|
|
|
|
+ d.decode(&mv)
|
|
|
|
|
+ m[mk] = mv
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (z *bytesDecReader) readn1() uint8 {
|
|
|
|
|
- c0 := z.consume(1)
|
|
|
|
|
- return z.b[c0]
|
|
|
|
|
|
|
+func (d *Decoder) decMapIntIntf(v *map[int]interface{}) {
|
|
|
|
|
+ containerLen := d.d.readMapLen()
|
|
|
|
|
+ m := *v
|
|
|
|
|
+ if m == nil {
|
|
|
|
|
+ m = make(map[int]interface{}, containerLen)
|
|
|
|
|
+ *v = m
|
|
|
|
|
+ }
|
|
|
|
|
+ for j := 0; j < containerLen; j++ {
|
|
|
|
|
+ d.d.initReadNext()
|
|
|
|
|
+ mk := int(d.d.decodeInt(intBitsize))
|
|
|
|
|
+ mv := m[mk]
|
|
|
|
|
+ d.decode(&mv)
|
|
|
|
|
+ m[mk] = mv
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Use binaryEncoding helper for 4 and 8 bits, but inline it for 2 bits
|
|
|
|
|
-// creating temp slice variable and copying it to helper function is expensive
|
|
|
|
|
-// for just 2 bits.
|
|
|
|
|
-
|
|
|
|
|
-func (z *bytesDecReader) readUint16() uint16 {
|
|
|
|
|
- c0 := z.consume(2)
|
|
|
|
|
- return uint16(z.b[c0+1]) | uint16(z.b[c0])<<8
|
|
|
|
|
|
|
+func (d *Decoder) decMapStrIntf(v *map[string]interface{}) {
|
|
|
|
|
+ containerLen := d.d.readMapLen()
|
|
|
|
|
+ m := *v
|
|
|
|
|
+ if m == nil {
|
|
|
|
|
+ m = make(map[string]interface{}, containerLen)
|
|
|
|
|
+ *v = m
|
|
|
|
|
+ }
|
|
|
|
|
+ for j := 0; j < containerLen; j++ {
|
|
|
|
|
+ d.d.initReadNext()
|
|
|
|
|
+ mk := d.d.decodeString()
|
|
|
|
|
+ mv := m[mk]
|
|
|
|
|
+ d.decode(&mv)
|
|
|
|
|
+ m[mk] = mv
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (z *bytesDecReader) readUint32() uint32 {
|
|
|
|
|
- c0 := z.consume(4)
|
|
|
|
|
- return bigen.Uint32(z.b[c0:z.c])
|
|
|
|
|
-}
|
|
|
|
|
|
|
+// ----------------------------------------
|
|
|
|
|
|
|
|
-func (z *bytesDecReader) readUint64() uint64 {
|
|
|
|
|
- c0 := z.consume(8)
|
|
|
|
|
- return bigen.Uint64(z.b[c0:z.c])
|
|
|
|
|
|
|
+func decContLens(dd decDriver) (containerLen, containerLenS int) {
|
|
|
|
|
+ switch currEncodedType := dd.currentEncodedType(); currEncodedType {
|
|
|
|
|
+ case valueTypeArray:
|
|
|
|
|
+ containerLen = dd.readArrayLen()
|
|
|
|
|
+ containerLenS = containerLen
|
|
|
|
|
+ case valueTypeMap:
|
|
|
|
|
+ containerLen = dd.readMapLen()
|
|
|
|
|
+ containerLenS = containerLen * 2
|
|
|
|
|
+ default:
|
|
|
|
|
+ decErr("Only encoded map or array can be decoded into a slice. (valueType: %x)",
|
|
|
|
|
+ currEncodedType)
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// ----------------------------------------
|
|
|
|
|
-
|
|
|
|
|
func decErr(format string, params ...interface{}) {
|
|
func decErr(format string, params ...interface{}) {
|
|
|
doPanic(msgTagDec, format, params...)
|
|
doPanic(msgTagDec, format, params...)
|
|
|
}
|
|
}
|
|
|
-
|
|
|