summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/hashicorp/go-msgpack/codec/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-msgpack/codec/decode.go')
-rw-r--r--vendor/github.com/hashicorp/go-msgpack/codec/decode.go1048
1 files changed, 1048 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-msgpack/codec/decode.go b/vendor/github.com/hashicorp/go-msgpack/codec/decode.go
new file mode 100644
index 000000000..87bef2b93
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-msgpack/codec/decode.go
@@ -0,0 +1,1048 @@
+// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a BSD-style license found in the LICENSE file.
+
+package codec
+
+import (
+ "io"
+ "reflect"
+ // "runtime/debug"
+)
+
+// Some tagging information for error messages.
+const (
+ msgTagDec = "codec.decoder"
+ msgBadDesc = "Unrecognized descriptor byte"
+ msgDecCannotExpandArr = "cannot expand go array from %v to stream length: %v"
+)
+
+// decReader abstracts the reading source, allowing implementations that can
+// read from an io.Reader or directly off a byte slice with zero-copying.
+type decReader interface {
+ readn(n int) []byte
+ readb([]byte)
+ readn1() uint8
+ readUint16() uint16
+ readUint32() uint32
+ readUint64() uint64
+}
+
+type decDriver interface {
+ initReadNext()
+ tryDecodeAsNil() bool
+ currentEncodedType() valueType
+ isBuiltinType(rt uintptr) bool
+ 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)
+ decodeUint(bitsize uint8) (ui uint64)
+ decodeFloat(chkOverflow32 bool) (f float64)
+ decodeBool() (b bool)
+ // decodeString can also decode symbols
+ decodeString() (s string)
+ decodeBytes(bs []byte) (bsOut []byte, changed bool)
+ decodeExt(verifyTag bool, tag byte) (xtag byte, xbs []byte)
+ readMapLen() int
+ readArrayLen() int
+}
+
+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
+}
+
+// ------------------------------------
+
+// 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
+}
+
+func (z *ioDecReader) readn(n int) (bs []byte) {
+ if n <= 0 {
+ return
+ }
+ 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) {
+ if n <= 0 {
+ return
+ }
+ 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
+ array bool
+}
+
+func (f *decFnInfo) builtin(rv reflect.Value) {
+ f.dd.decodeBuiltin(f.ti.rtid, rv.Addr().Interface())
+}
+
+func (f *decFnInfo) rawExt(rv reflect.Value) {
+ xtag, xbs := f.dd.decodeExt(false, 0)
+ rv.Field(0).SetUint(uint64(xtag))
+ rv.Field(1).SetBytes(xbs)
+}
+
+func (f *decFnInfo) ext(rv reflect.Value) {
+ _, xbs := f.dd.decodeExt(true, f.xfTag)
+ if fnerr := f.xfFn(rv, xbs); fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+func (f *decFnInfo) binaryMarshal(rv reflect.Value) {
+ var bm binaryUnmarshaler
+ if f.ti.unmIndir == -1 {
+ bm = rv.Addr().Interface().(binaryUnmarshaler)
+ } else if f.ti.unmIndir == 0 {
+ bm = rv.Interface().(binaryUnmarshaler)
+ } else {
+ for j, k := int8(0), f.ti.unmIndir; j < k; j++ {
+ if rv.IsNil() {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ rv = rv.Elem()
+ }
+ bm = rv.Interface().(binaryUnmarshaler)
+ }
+ xbs, _ := f.dd.decodeBytes(nil)
+ if fnerr := bm.UnmarshalBinary(xbs); fnerr != nil {
+ panic(fnerr)
+ }
+}
+
+func (f *decFnInfo) kErr(rv reflect.Value) {
+ decErr("Unhandled value for kind: %v: %s", rv.Kind(), msgBadDesc)
+}
+
+func (f *decFnInfo) kString(rv reflect.Value) {
+ rv.SetString(f.dd.decodeString())
+}
+
+func (f *decFnInfo) kBool(rv reflect.Value) {
+ rv.SetBool(f.dd.decodeBool())
+}
+
+func (f *decFnInfo) kInt(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(intBitsize))
+}
+
+func (f *decFnInfo) kInt64(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(64))
+}
+
+func (f *decFnInfo) kInt32(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(32))
+}
+
+func (f *decFnInfo) kInt8(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(8))
+}
+
+func (f *decFnInfo) kInt16(rv reflect.Value) {
+ rv.SetInt(f.dd.decodeInt(16))
+}
+
+func (f *decFnInfo) kFloat32(rv reflect.Value) {
+ rv.SetFloat(f.dd.decodeFloat(true))
+}
+
+func (f *decFnInfo) kFloat64(rv reflect.Value) {
+ rv.SetFloat(f.dd.decodeFloat(false))
+}
+
+func (f *decFnInfo) kUint8(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(8))
+}
+
+func (f *decFnInfo) kUint64(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(64))
+}
+
+func (f *decFnInfo) kUint(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(uintBitsize))
+}
+
+func (f *decFnInfo) kUint32(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(32))
+}
+
+func (f *decFnInfo) kUint16(rv reflect.Value) {
+ rv.SetUint(f.dd.decodeUint(16))
+}
+
+// func (f *decFnInfo) kPtr(rv reflect.Value) {
+// debugf(">>>>>>> ??? decode kPtr called - shouldn't get called")
+// if rv.IsNil() {
+// rv.Set(reflect.New(rv.Type().Elem()))
+// }
+// f.d.decodeValue(rv.Elem())
+// }
+
+func (f *decFnInfo) kInterface(rv reflect.Value) {
+ // 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
+ }
+ case valueTypeArray:
+ if f.d.h.SliceType == nil {
+ var m2 []interface{}
+ v = &m2
+ } else {
+ rvn = reflect.New(f.d.h.SliceType).Elem()
+ useRvn = true
+ }
+ 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) {
+ fti := f.ti
+ if currEncodedType := f.dd.currentEncodedType(); currEncodedType == valueTypeMap {
+ containerLen := f.dd.readMapLen()
+ if containerLen == 0 {
+ return
+ }
+ tisfi := fti.sfi
+ for j := 0; j < containerLen; j++ {
+ // var rvkencname string
+ // ddecode(&rvkencname)
+ f.dd.initReadNext()
+ rvkencname := f.dd.decodeString()
+ // rvksi := ti.getForEncName(rvkencname)
+ if k := fti.indexForEncName(rvkencname); k > -1 {
+ sfik := tisfi[k]
+ if sfik.i != -1 {
+ f.d.decodeValue(rv.Field(int(sfik.i)))
+ } else {
+ f.d.decEmbeddedField(rv, sfik.is)
+ }
+ // f.d.decodeValue(ti.field(k, rv))
+ } else {
+ if f.d.h.ErrorIfNoField {
+ decErr("No matching struct field found when decoding stream map with key: %v",
+ rvkencname)
+ } else {
+ var nilintf0 interface{}
+ f.d.decodeValue(reflect.ValueOf(&nilintf0).Elem())
+ }
+ }
+ }
+ } else if currEncodedType == valueTypeArray {
+ containerLen := f.dd.readArrayLen()
+ if containerLen == 0 {
+ return
+ }
+ for j, si := range fti.sfip {
+ if j == containerLen {
+ break
+ }
+ if si.i != -1 {
+ f.d.decodeValue(rv.Field(int(si.i)))
+ } else {
+ f.d.decEmbeddedField(rv, si.is)
+ }
+ }
+ if containerLen > len(fti.sfip) {
+ // read remaining values and throw away
+ for j := len(fti.sfip); j < containerLen; j++ {
+ var nilintf0 interface{}
+ f.d.decodeValue(reflect.ValueOf(&nilintf0).Elem())
+ }
+ }
+ } else {
+ decErr("Only encoded map or array can be decoded into a struct. (valueType: %x)",
+ currEncodedType)
+ }
+}
+
+func (f *decFnInfo) kSlice(rv reflect.Value) {
+ // A slice can be set from a map or array in stream.
+ currEncodedType := f.dd.currentEncodedType()
+
+ switch currEncodedType {
+ case valueTypeBytes, valueTypeString:
+ if f.ti.rtid == uint8SliceTypId || f.ti.rt.Elem().Kind() == reflect.Uint8 {
+ if bs2, changed2 := f.dd.decodeBytes(rv.Bytes()); changed2 {
+ rv.SetBytes(bs2)
+ }
+ return
+ }
+ }
+
+ if shortCircuitReflectToFastPath && rv.CanAddr() {
+ switch f.ti.rtid {
+ case intfSliceTypId:
+ f.d.decSliceIntf(rv.Addr().Interface().(*[]interface{}), currEncodedType, f.array)
+ return
+ case uint64SliceTypId:
+ f.d.decSliceUint64(rv.Addr().Interface().(*[]uint64), currEncodedType, f.array)
+ return
+ case int64SliceTypId:
+ f.d.decSliceInt64(rv.Addr().Interface().(*[]int64), currEncodedType, f.array)
+ return
+ case strSliceTypId:
+ f.d.decSliceStr(rv.Addr().Interface().(*[]string), currEncodedType, f.array)
+ return
+ }
+ }
+
+ containerLen, containerLenS := decContLens(f.dd, currEncodedType)
+
+ // an array can never return a nil slice. so no need to check f.array here.
+
+ if rv.IsNil() {
+ rv.Set(reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS))
+ }
+
+ if containerLen == 0 {
+ return
+ }
+
+ if rvcap, rvlen := rv.Len(), rv.Cap(); containerLenS > rvcap {
+ if f.array { // !rv.CanSet()
+ decErr(msgDecCannotExpandArr, rvcap, containerLenS)
+ }
+ rvn := reflect.MakeSlice(f.ti.rt, containerLenS, containerLenS)
+ if rvlen > 0 {
+ reflect.Copy(rvn, rv)
+ }
+ rv.Set(rvn)
+ } else if containerLenS > rvlen {
+ rv.SetLen(containerLenS)
+ }
+
+ for j := 0; j < containerLenS; j++ {
+ f.d.decodeValue(rv.Index(j))
+ }
+}
+
+func (f *decFnInfo) kArray(rv reflect.Value) {
+ // f.d.decodeValue(rv.Slice(0, rv.Len()))
+ f.kSlice(rv.Slice(0, rv.Len()))
+}
+
+func (f *decFnInfo) kMap(rv reflect.Value) {
+ if shortCircuitReflectToFastPath && rv.CanAddr() {
+ switch f.ti.rtid {
+ case mapStrIntfTypId:
+ f.d.decMapStrIntf(rv.Addr().Interface().(*map[string]interface{}))
+ return
+ case mapIntfIntfTypId:
+ f.d.decMapIntfIntf(rv.Addr().Interface().(*map[interface{}]interface{}))
+ return
+ case mapInt64IntfTypId:
+ f.d.decMapInt64Intf(rv.Addr().Interface().(*map[int64]interface{}))
+ return
+ case mapUint64IntfTypId:
+ f.d.decMapUint64Intf(rv.Addr().Interface().(*map[uint64]interface{}))
+ return
+ }
+ }
+
+ containerLen := f.dd.readMapLen()
+
+ if rv.IsNil() {
+ rv.Set(reflect.MakeMap(f.ti.rt))
+ }
+
+ if containerLen == 0 {
+ return
+ }
+
+ ktype, vtype := f.ti.rt.Key(), f.ti.rt.Elem()
+ ktypeId := reflect.ValueOf(ktype).Pointer()
+ for j := 0; j < containerLen; j++ {
+ rvk := reflect.New(ktype).Elem()
+ f.d.decodeValue(rvk)
+
+ // special case if a byte array.
+ // if ktype == intfTyp {
+ if ktypeId == intfTypId {
+ rvk = rvk.Elem()
+ if rvk.Type() == uint8SliceTyp {
+ rvk = reflect.ValueOf(string(rvk.Bytes()))
+ }
+ }
+ rvv := rv.MapIndex(rvk)
+ if !rvv.IsValid() {
+ rvv = reflect.New(vtype).Elem()
+ }
+
+ f.d.decodeValue(rvv)
+ rv.SetMapIndex(rvk, rvv)
+ }
+}
+
+// ----------------------------------------
+
+type decFn struct {
+ i *decFnInfo
+ f func(*decFnInfo, reflect.Value)
+}
+
+// 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.
+//
+// For efficiency, Users are encouraged to pass in a memory buffered writer
+// (eg bufio.Reader, bytes.Buffer).
+func NewDecoder(r io.Reader, h Handle) *Decoder {
+ z := ioDecReader{
+ r: r,
+ }
+ z.br, _ = r.(io.ByteReader)
+ return &Decoder{r: &z, d: h.newDecDriver(&z), h: h.getBasicHandle()}
+}
+
+// NewDecoderBytes returns a Decoder which efficiently decodes directly
+// from a byte slice with zero copying.
+func NewDecoderBytes(in []byte, h Handle) *Decoder {
+ z := bytesDecReader{
+ b: in,
+ a: len(in),
+ }
+ return &Decoder{r: &z, d: h.newDecDriver(&z), h: h.getBasicHandle()}
+}
+
+// Decode decodes the stream from reader and stores the result in the
+// value pointed to by v. v cannot be a nil pointer. v can also be
+// a reflect.Value of a 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.
+// We will decode and store a value in that nil interface.
+//
+// Sample usages:
+// // Decoding into a non-nil typed value
+// var f float32
+// err = codec.NewDecoder(r, handle).Decode(&f)
+//
+// // Decoding into nil interface
+// var v interface{}
+// dec := codec.NewDecoder(r, handle)
+// err = dec.Decode(&v)
+//
+// When decoding into a nil interface{}, we will decode into an appropriate value based
+// on the contents of the stream:
+// - Numbers are decoded as float64, int64 or uint64.
+// - Other values are decoded appropriately depending on the type:
+// bool, string, []byte, time.Time, etc
+// - Extensions are decoded as RawExt (if no ext function registered for the tag)
+// Configurations exist on the Handle to override defaults
+// (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
+// type of the value. When a value is seen:
+// - If an extension is registered for it, call that extension function
+// - If it implements BinaryUnmarshaler, call its UnmarshalBinary(data []byte) error
+// - Else decode it based on its reflect.Kind
+//
+// There are some special rules when decoding into containers (slice/array/map/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) {
+ defer panicToErr(&err)
+ d.decode(v)
+ return
+}
+
+func (d *Decoder) decode(iv interface{}) {
+ d.d.initReadNext()
+
+ switch v := iv.(type) {
+ case nil:
+ decErr("Cannot decode into nil.")
+
+ case reflect.Value:
+ d.chkPtrValue(v)
+ d.decodeValue(v.Elem())
+
+ case *string:
+ *v = d.d.decodeString()
+ case *bool:
+ *v = d.d.decodeBool()
+ case *int:
+ *v = int(d.d.decodeInt(intBitsize))
+ case *int8:
+ *v = int8(d.d.decodeInt(8))
+ case *int16:
+ *v = int16(d.d.decodeInt(16))
+ case *int32:
+ *v = int32(d.d.decodeInt(32))
+ case *int64:
+ *v = d.d.decodeInt(64)
+ case *uint:
+ *v = uint(d.d.decodeUint(uintBitsize))
+ case *uint8:
+ *v = uint8(d.d.decodeUint(8))
+ case *uint16:
+ *v = uint16(d.d.decodeUint(16))
+ case *uint32:
+ *v = uint32(d.d.decodeUint(32))
+ case *uint64:
+ *v = d.d.decodeUint(64)
+ case *float32:
+ *v = float32(d.d.decodeFloat(true))
+ case *float64:
+ *v = d.d.decodeFloat(false)
+ case *[]byte:
+ *v, _ = d.d.decodeBytes(*v)
+
+ case *[]interface{}:
+ d.decSliceIntf(v, valueTypeInvalid, false)
+ case *[]uint64:
+ d.decSliceUint64(v, valueTypeInvalid, false)
+ case *[]int64:
+ d.decSliceInt64(v, valueTypeInvalid, false)
+ case *[]string:
+ d.decSliceStr(v, valueTypeInvalid, false)
+ case *map[string]interface{}:
+ d.decMapStrIntf(v)
+ case *map[interface{}]interface{}:
+ d.decMapIntfIntf(v)
+ case *map[uint64]interface{}:
+ d.decMapUint64Intf(v)
+ case *map[int64]interface{}:
+ d.decMapInt64Intf(v)
+
+ case *interface{}:
+ d.decodeValue(reflect.ValueOf(iv).Elem())
+
+ default:
+ rv := reflect.ValueOf(iv)
+ d.chkPtrValue(rv)
+ d.decodeValue(rv.Elem())
+ }
+}
+
+func (d *Decoder) decodeValue(rv reflect.Value) {
+ d.d.initReadNext()
+
+ if d.d.tryDecodeAsNil() {
+ // If value in stream is nil, set the dereferenced value to its "zero" value (if settable)
+ if rv.Kind() == reflect.Ptr {
+ if !rv.IsNil() {
+ rv.Set(reflect.Zero(rv.Type()))
+ }
+ return
+ }
+ // for rv.Kind() == reflect.Ptr {
+ // rv = rv.Elem()
+ // }
+ if rv.IsValid() { // rv.CanSet() // always settable, except it's invalid
+ rv.Set(reflect.Zero(rv.Type()))
+ }
+ return
+ }
+
+ // If stream is not containing a nil value, then we can deref to the base
+ // non-pointer value, and decode into that.
+ for rv.Kind() == reflect.Ptr {
+ if rv.IsNil() {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ rv = rv.Elem()
+ }
+
+ rt := rv.Type()
+ rtid := reflect.ValueOf(rt).Pointer()
+
+ // retrieve or register a focus'ed function for this type
+ // 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
+ var ok bool
+ if useMapForCodecCache {
+ fn, ok = d.f[rtid]
+ } else {
+ for i, v := range d.x {
+ if v == rtid {
+ fn, ok = d.s[i], true
+ break
+ }
+ }
+ }
+ if !ok {
+ // debugf("\tCreating new dec fn for type: %v\n", rt)
+ 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
+ // (e.g. type BitSet int64, type MyStruct { / * unexported fields * / }, type X []int, etc.
+ //
+ // We can't check if it's an extension byte here first, because the user may have
+ // registered a pointer or non-pointer type, meaning we may have to recurse first
+ // before matching a mapped type, even though the extension byte is already detected.
+ //
+ // NOTE: if decoding into a nil interface{}, we return a non-nil
+ // value except even if the container registers a length of 0.
+ if rtid == rawExtTypId {
+ fn.f = (*decFnInfo).rawExt
+ } else if d.d.isBuiltinType(rtid) {
+ fn.f = (*decFnInfo).builtin
+ } else if xfTag, xfFn := d.h.getDecodeExt(rtid); xfFn != nil {
+ fi.xfTag, fi.xfFn = xfTag, xfFn
+ fn.f = (*decFnInfo).ext
+ } else if supportBinaryMarshal && fi.ti.unm {
+ fn.f = (*decFnInfo).binaryMarshal
+ } else {
+ switch rk := rt.Kind(); rk {
+ case reflect.String:
+ fn.f = (*decFnInfo).kString
+ case reflect.Bool:
+ fn.f = (*decFnInfo).kBool
+ case reflect.Int:
+ fn.f = (*decFnInfo).kInt
+ case reflect.Int64:
+ fn.f = (*decFnInfo).kInt64
+ case reflect.Int32:
+ fn.f = (*decFnInfo).kInt32
+ case reflect.Int8:
+ fn.f = (*decFnInfo).kInt8
+ case reflect.Int16:
+ fn.f = (*decFnInfo).kInt16
+ case reflect.Float32:
+ fn.f = (*decFnInfo).kFloat32
+ case reflect.Float64:
+ fn.f = (*decFnInfo).kFloat64
+ case reflect.Uint8:
+ fn.f = (*decFnInfo).kUint8
+ case reflect.Uint64:
+ fn.f = (*decFnInfo).kUint64
+ case reflect.Uint:
+ fn.f = (*decFnInfo).kUint
+ case reflect.Uint32:
+ fn.f = (*decFnInfo).kUint32
+ case reflect.Uint16:
+ fn.f = (*decFnInfo).kUint16
+ // case reflect.Ptr:
+ // fn.f = (*decFnInfo).kPtr
+ case reflect.Interface:
+ fn.f = (*decFnInfo).kInterface
+ case reflect.Struct:
+ fn.f = (*decFnInfo).kStruct
+ case reflect.Slice:
+ fn.f = (*decFnInfo).kSlice
+ case reflect.Array:
+ fi.array = true
+ fn.f = (*decFnInfo).kArray
+ case reflect.Map:
+ fn.f = (*decFnInfo).kMap
+ default:
+ fn.f = (*decFnInfo).kErr
+ }
+ }
+ if useMapForCodecCache {
+ if d.f == nil {
+ d.f = make(map[uintptr]decFn, 16)
+ }
+ d.f[rtid] = fn
+ } else {
+ d.s = append(d.s, fn)
+ d.x = append(d.x, rtid)
+ }
+ }
+
+ fn.f(fn.i, rv)
+
+ return
+}
+
+func (d *Decoder) chkPtrValue(rv reflect.Value) {
+ // We can only decode into a non-nil pointer
+ if rv.Kind() == reflect.Ptr && !rv.IsNil() {
+ return
+ }
+ if !rv.IsValid() {
+ decErr("Cannot decode into a zero (ie invalid) reflect.Value")
+ }
+ if !rv.CanInterface() {
+ decErr("Cannot decode into a value without an interface: %v", rv)
+ }
+ rvi := rv.Interface()
+ decErr("Cannot decode into non-pointer or nil pointer. Got: %v, %T, %v",
+ rv.Kind(), rvi, rvi)
+}
+
+func (d *Decoder) decEmbeddedField(rv reflect.Value, index []int) {
+ // d.decodeValue(rv.FieldByIndex(index))
+ // nil pointers may be here; so reproduce FieldByIndex logic + enhancements
+ for _, j := range index {
+ if rv.Kind() == reflect.Ptr {
+ if rv.IsNil() {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ // If a pointer, it must be a pointer to struct (based on typeInfo contract)
+ rv = rv.Elem()
+ }
+ rv = rv.Field(j)
+ }
+ d.decodeValue(rv)
+}
+
+// --------------------------------------------------
+
+// short circuit functions for common maps and slices
+
+func (d *Decoder) decSliceIntf(v *[]interface{}, currEncodedType valueType, doNotReset bool) {
+ _, containerLenS := decContLens(d.d, currEncodedType)
+ s := *v
+ if s == nil {
+ s = make([]interface{}, containerLenS, containerLenS)
+ } else if containerLenS > cap(s) {
+ if doNotReset {
+ decErr(msgDecCannotExpandArr, cap(s), containerLenS)
+ }
+ s = make([]interface{}, 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 (d *Decoder) decSliceInt64(v *[]int64, currEncodedType valueType, doNotReset bool) {
+ _, containerLenS := decContLens(d.d, currEncodedType)
+ s := *v
+ if s == nil {
+ s = make([]int64, containerLenS, containerLenS)
+ } else if containerLenS > cap(s) {
+ if doNotReset {
+ decErr(msgDecCannotExpandArr, cap(s), containerLenS)
+ }
+ s = make([]int64, containerLenS, containerLenS)
+ copy(s, *v)
+ } else if containerLenS > len(s) {
+ s = s[:containerLenS]
+ }
+ for j := 0; j < containerLenS; j++ {
+ // d.decode(&s[j])
+ d.d.initReadNext()
+ s[j] = d.d.decodeInt(intBitsize)
+ }
+ *v = s
+}
+
+func (d *Decoder) decSliceUint64(v *[]uint64, currEncodedType valueType, doNotReset bool) {
+ _, containerLenS := decContLens(d.d, currEncodedType)
+ s := *v
+ if s == nil {
+ s = make([]uint64, containerLenS, containerLenS)
+ } else if containerLenS > cap(s) {
+ if doNotReset {
+ decErr(msgDecCannotExpandArr, cap(s), containerLenS)
+ }
+ s = make([]uint64, containerLenS, containerLenS)
+ copy(s, *v)
+ } else if containerLenS > len(s) {
+ s = s[:containerLenS]
+ }
+ for j := 0; j < containerLenS; j++ {
+ // d.decode(&s[j])
+ d.d.initReadNext()
+ s[j] = d.d.decodeUint(intBitsize)
+ }
+ *v = s
+}
+
+func (d *Decoder) decSliceStr(v *[]string, currEncodedType valueType, doNotReset bool) {
+ _, containerLenS := decContLens(d.d, currEncodedType)
+ s := *v
+ if s == nil {
+ s = make([]string, containerLenS, containerLenS)
+ } else if containerLenS > cap(s) {
+ if doNotReset {
+ decErr(msgDecCannotExpandArr, cap(s), containerLenS)
+ }
+ 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])
+ d.d.initReadNext()
+ s[j] = d.d.decodeString()
+ }
+ *v = s
+}
+
+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)
+ // special case if a byte array.
+ if bv, bok := mk.([]byte); bok {
+ mk = string(bv)
+ }
+ mv := m[mk]
+ d.decode(&mv)
+ m[mk] = mv
+ }
+}
+
+func (d *Decoder) decMapInt64Intf(v *map[int64]interface{}) {
+ containerLen := d.d.readMapLen()
+ m := *v
+ if m == nil {
+ m = make(map[int64]interface{}, containerLen)
+ *v = m
+ }
+ for j := 0; j < containerLen; j++ {
+ d.d.initReadNext()
+ mk := d.d.decodeInt(intBitsize)
+ mv := m[mk]
+ d.decode(&mv)
+ m[mk] = mv
+ }
+}
+
+func (d *Decoder) decMapUint64Intf(v *map[uint64]interface{}) {
+ containerLen := d.d.readMapLen()
+ m := *v
+ if m == nil {
+ m = make(map[uint64]interface{}, containerLen)
+ *v = m
+ }
+ for j := 0; j < containerLen; j++ {
+ d.d.initReadNext()
+ mk := d.d.decodeUint(intBitsize)
+ mv := m[mk]
+ d.decode(&mv)
+ m[mk] = mv
+ }
+}
+
+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 decContLens(dd decDriver, currEncodedType valueType) (containerLen, containerLenS int) {
+ if currEncodedType == valueTypeInvalid {
+ currEncodedType = dd.currentEncodedType()
+ }
+ switch 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: %0x)",
+ currEncodedType)
+ }
+ return
+}
+
+func decErr(format string, params ...interface{}) {
+ doPanic(msgTagDec, format, params...)
+}