| // 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...) |
| } |