| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685 |
- // 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"
- //"math"
- "fmt"
- "time"
- )
- // Some tagging information for error messages.
- var (
- msgTagDec = "codec.decoder"
- msgBadDesc = "Unrecognized descriptor byte"
- digits = [...]byte {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
- )
- type decodeNakedContext uint8
- const (
- dncHandled decodeNakedContext = iota
- dncNil
- dncExt
- dncContainer
- )
- // 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 decoder interface {
- initReadNext()
- currentIsNil() bool
- decodeBuiltinType(rt reflect.Type, rv reflect.Value) bool
- //decodeNaked should completely handle extensions, builtins, primitives, etc.
- //Numbers are decoded as int64, uint64, float64 only (no smaller sized number types).
- decodeNaked(h decodeHandleI) (rv reflect.Value, ctx decodeNakedContext)
- 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(tag byte) []byte
- readMapLen() int
- readArrayLen() int
- }
- type newDecoderFunc func(r decReader) decoder
- // A Decoder reads and decodes an object from an input stream in the codec format.
- type Decoder struct {
- r decReader
- d decoder
- h decodeHandleI
- }
- // ioDecReader is a decReader that reads off an io.Reader
- type ioDecReader struct {
- r io.Reader
- 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 decExtTagFn struct {
- fn func(reflect.Value, []byte)(error)
- tag byte
- }
- type decExtTypeTagFn struct {
- rt reflect.Type
- decExtTagFn
- }
- type decodeHandleI interface {
- getDecodeExt(rt reflect.Type) (tag byte, fn func(reflect.Value, []byte) error)
- newDecoder(r decReader) decoder
- errorIfNoField() bool
- }
- type decHandle struct {
- // put word-aligned fields first (before bools, etc)
- exts []decExtTypeTagFn
- extFuncs map[reflect.Type] decExtTagFn
- // if an extension for byte slice is defined, then always decode Raw as strings
- rawToStringOverride 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
- }
- func (o *DecodeOptions) errorIfNoField() bool {
- return o.ErrorIfNoField
- }
- // addDecodeExt registers a function to handle decoding into a given type when an
- // extension type and specific tag byte is detected in the codec stream.
- // To remove an extension, pass fn=nil.
- func (o *decHandle) addDecodeExt(rt reflect.Type, tag byte, fn func(reflect.Value, []byte) (error)) {
- if o.exts == nil {
- o.exts = make([]decExtTypeTagFn, 0, 2)
- o.extFuncs = make(map[reflect.Type]decExtTagFn, 2)
- }
- if _, ok := o.extFuncs[rt]; ok {
- delete(o.extFuncs, rt)
- if rt == byteSliceTyp {
- o.rawToStringOverride = false
- }
- }
- if fn != nil {
- o.extFuncs[rt] = decExtTagFn{fn, tag}
- if rt == byteSliceTyp {
- o.rawToStringOverride = true
- }
- }
-
- if leno := len(o.extFuncs); leno > cap(o.exts) {
- o.exts = make([]decExtTypeTagFn, leno, (leno * 3 / 2))
- } else {
- o.exts = o.exts[0:leno]
- }
- var i int
- for k, v := range o.extFuncs {
- o.exts[i] = decExtTypeTagFn {k, v}
- i++
- }
- }
- func (o *decHandle) getDecodeExtForTag(tag byte) (rt reflect.Type, fn func(reflect.Value, []byte) error) {
- for i, l := 0, len(o.exts); i < l; i++ {
- if o.exts[i].tag == tag {
- return o.exts[i].rt, o.exts[i].fn
- }
- }
- return
- }
- func (o *decHandle) getDecodeExt(rt reflect.Type) (tag byte, fn func(reflect.Value, []byte) error) {
- if l := len(o.exts); l == 0 {
- return
- } else if l < mapAccessThreshold {
- for i := 0; i < l; i++ {
- if o.exts[i].rt == rt {
- x := o.exts[i].decExtTagFn
- return x.tag, x.fn
- }
- }
- } else {
- x := o.extFuncs[rt]
- return x.tag, x.fn
- }
- return
- }
- // NewDecoder returns a Decoder for decoding a stream of bytes from an io.Reader.
- func NewDecoder(r io.Reader, h Handle) (*Decoder) {
- z := ioDecReader {
- r: r,
- }
- return &Decoder{ r: &z, d: h.newDecoder(&z), h: h }
- }
- // 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.newDecoder(&z), h: h }
- }
- // 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)
- //
- func (d *Decoder) Decode(v interface{}) (err error) {
- defer panicToErr(&err)
- d.decode(v)
- return
- }
- func (d *Decoder) decode(iv interface{}) {
- d.d.initReadNext()
-
- // Fast path included for various pointer types which cannot be registered as extensions
- switch v := iv.(type) {
- case nil:
- decErr("Cannot decode into nil.")
- case reflect.Value:
- d.chkPtrValue(v)
- d.decodeValue(v)
- 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 = int64(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 = uint64(d.d.decodeUint(64))
- case *float32:
- *v = float32(d.d.decodeFloat(true))
- case *float64:
- *v = d.d.decodeFloat(false)
- case *interface{}:
- d.decodeValue(reflect.ValueOf(iv).Elem())
- default:
- rv := reflect.ValueOf(iv)
- d.chkPtrValue(rv)
- d.decodeValue(rv)
- }
- }
- func (d *Decoder) decodeValue(rv reflect.Value) {
- // Note: if stream is set to nil, we set the corresponding value to its "zero" value
-
- // var ctr int (define this above the function if trying to do this run)
- // ctr++
- // log(".. [%v] enter decode: rv: %v <==> %T <==> %v", ctr, rv, rv.Interface(), rv.Interface())
- // defer func(ctr2 int) {
- // log(".... [%v] exit decode: rv: %v <==> %T <==> %v", ctr2, rv, rv.Interface(), rv.Interface())
- // }(ctr)
- dd := d.d //so we don't dereference constantly
- dd.initReadNext()
-
- rvOrig := rv
- wasNilIntf := rv.Kind() == reflect.Interface && rv.IsNil()
- rt := rv.Type()
-
- var ndesc decodeNakedContext
- //if nil interface, use some hieristics to set the nil interface to an
- //appropriate value based on the first byte read (byte descriptor bd)
- if wasNilIntf {
- if dd.currentIsNil() {
- return
- }
- //Prevent from decoding into e.g. error, io.Reader, etc if it's nil and non-nil value in stream.
- //We can only decode into interface{} (0 methods). Else reflect.Set fails later.
- if num := rt.NumMethod(); num > 0 {
- decErr("decodeValue: Cannot decode non-nil codec value into nil %v (%v methods)", rt, num)
- } else {
- rv, ndesc = dd.decodeNaked(d.h)
- if ndesc == dncHandled {
- rvOrig.Set(rv)
- return
- }
- rt = rv.Type()
- }
- } else if dd.currentIsNil() {
- // Note: if stream is set to nil, we set the dereferenced value to its "zero" value (if settable).
- for rv.Kind() == reflect.Ptr {
- rv = rv.Elem()
- }
- if rv.CanSet() {
- rv.Set(reflect.Zero(rv.Type()))
- }
- return
- }
-
- // 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.
- //
- // If we are checking for builtin or ext type here, it means we didn't go through decodeNaked,
- // Because decodeNaked would have handled it. It also means wasNilIntf = false.
- if dd.decodeBuiltinType(rt, rv) {
- return
- }
- if bfnTag, bfnFn := d.h.getDecodeExt(rt); bfnFn != nil {
- xbs := dd.decodeExt(bfnTag)
- if fnerr := bfnFn(rv, xbs); fnerr != nil {
- panic(fnerr)
- }
- return
- }
-
- // Note: In decoding into containers, we just use the stream 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 the length of the
- // stream.
- // However, if the encoded value is Nil in the stream, then we try to set
- // to nil, or a "zero" value.
- //
- // Also, we must ensure that, if decoding into a nil interface{}, we return a non-nil
- // value except even if the container registers a length of 0.
- //
- // NOTE: Do not make blocks for struct, slice, map, etc individual methods.
- // It ends up being more expensive, because they recursively calls decodeValue
- //
- // (Mar 7, 2013. DON'T REARRANGE ... code clarity)
- // tried arranging in sequence of most probable ones.
- // string, bool, integer, float, struct, ptr, slice, array, map, interface, uint.
- switch rk := rv.Kind(); rk {
- case reflect.String:
- rv.SetString(dd.decodeString())
- case reflect.Bool:
- rv.SetBool(dd.decodeBool())
- case reflect.Int:
- rv.SetInt(dd.decodeInt(intBitsize))
- case reflect.Int64:
- rv.SetInt(dd.decodeInt(64))
- case reflect.Int32:
- rv.SetInt(dd.decodeInt(32))
- case reflect.Int8:
- rv.SetInt(dd.decodeInt(8))
- case reflect.Int16:
- rv.SetInt(dd.decodeInt(16))
- case reflect.Float32:
- rv.SetFloat(dd.decodeFloat(true))
- case reflect.Float64:
- rv.SetFloat(dd.decodeFloat(false))
- case reflect.Uint8:
- rv.SetUint(dd.decodeUint(8))
- case reflect.Uint64:
- rv.SetUint(dd.decodeUint(64))
- case reflect.Uint:
- rv.SetUint(dd.decodeUint(uintBitsize))
- case reflect.Uint32:
- rv.SetUint(dd.decodeUint(32))
- case reflect.Uint16:
- rv.SetUint(dd.decodeUint(16))
- case reflect.Ptr:
- if rv.IsNil() {
- if wasNilIntf {
- rv = reflect.New(rt.Elem())
- } else {
- rv.Set(reflect.New(rt.Elem()))
- }
- }
- d.decodeValue(rv.Elem())
- case reflect.Interface:
- d.decodeValue(rv.Elem())
- case reflect.Struct:
- containerLen := dd.readMapLen()
-
- if containerLen == 0 {
- break
- }
-
- sfi := getStructFieldInfos(rt)
- for j := 0; j < containerLen; j++ {
- // var rvkencname string
- // ddecode(&rvkencname)
- dd.initReadNext()
- rvkencname := dd.decodeString()
- // rvksi := sfi.getForEncName(rvkencname)
- if k := sfi.indexForEncName(rvkencname); k > -1 {
- sfik := sfi[k]
- if sfik.i > -1 {
- d.decodeValue(rv.Field(int(sfik.i)))
- } else {
- d.decodeValue(rv.FieldByIndex(sfik.is))
- }
- // d.decodeValue(sfi.field(k, rv))
- } else {
- if d.h.errorIfNoField() {
- decErr("No matching struct field found when decoding stream map with key: %v", rvkencname)
- } else {
- var nilintf0 interface{}
- d.decodeValue(reflect.ValueOf(&nilintf0).Elem())
- }
- }
- }
- case reflect.Slice:
- // Be more careful calling Set() here, because a reflect.Value from an array
- // 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.
-
- if rt == byteSliceTyp { // rawbytes
- if bs2, changed2 := dd.decodeBytes(rv.Bytes()); changed2 {
- rv.SetBytes(bs2)
- }
- if wasNilIntf && rv.IsNil() {
- rv.SetBytes([]byte{})
- }
- break
- }
-
- containerLen := dd.readArrayLen()
- if wasNilIntf {
- rv = reflect.MakeSlice(rt, containerLen, containerLen)
- }
- if containerLen == 0 {
- break
- }
-
- if rv.IsNil() {
- // wasNilIntf only applies if rv is nil (since that's what we did earlier)
- if containerLen > 0 {
- rv.Set(reflect.MakeSlice(rt, containerLen, containerLen))
- }
- } else {
- // 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
- if rvcap, rvlen := rv.Len(), rv.Cap(); containerLen > rvcap {
- if rv.CanSet() {
- rvn := reflect.MakeSlice(rt, containerLen, containerLen)
- if rvlen > 0 {
- reflect.Copy(rvn, rv)
- }
- rv.Set(rvn)
- } else {
- decErr("Cannot reset slice with less cap: %v that stream contents: %v", rvcap, containerLen)
- }
- } else if containerLen > rvlen {
- rv.SetLen(containerLen)
- }
- }
- for j := 0; j < containerLen; j++ {
- d.decodeValue(rv.Index(j))
- }
- case reflect.Array:
- d.decodeValue(rv.Slice(0, rv.Len()))
- case reflect.Map:
- containerLen := dd.readMapLen()
-
- if containerLen == 0 {
- break
- }
- if rv.IsNil() {
- rv.Set(reflect.MakeMap(rt))
- }
- ktype, vtype := rt.Key(), rt.Elem()
- for j := 0; j < containerLen; j++ {
- rvk := reflect.New(ktype).Elem()
- d.decodeValue(rvk)
-
- if ktype == intfTyp {
- rvk = rvk.Elem()
- if rvk.Type() == byteSliceTyp {
- rvk = reflect.ValueOf(string(rvk.Bytes()))
- }
- }
- rvv := rv.MapIndex(rvk)
- if !rvv.IsValid() {
- rvv = reflect.New(vtype).Elem()
- }
-
- d.decodeValue(rvv)
- rv.SetMapIndex(rvk, rvv)
- }
- default:
- decErr("Unhandled value for kind: %v: %s", rk, msgBadDesc)
- }
-
- if wasNilIntf {
- rvOrig.Set(rv)
- }
- return
- }
- func (d *Decoder) chkPtrValue(rv reflect.Value) {
- // We cannot marshal into a non-pointer or a nil pointer
- // (at least pass a nil interface so we can marshal into it)
- if rv.Kind() != reflect.Ptr || rv.IsNil() {
- var rvi interface{} = rv
- if rv.IsValid() && rv.CanInterface() {
- rvi = rv.Interface()
- }
- decErr("Decode: Expecting valid pointer to decode into. Got: %v, %T, %v",
- rv.Kind(), rvi, rvi)
- }
- }
- // ------------------------------------
- func (z *ioDecReader) readn(n int) (bs []byte) {
- bs = make([]byte, n)
- if _, err := io.ReadFull(z.r, bs); err != nil {
- panic(err)
- }
- return
- }
- func (z *ioDecReader) readb(bs []byte) {
- if _, err := io.ReadFull(z.r, bs); err != nil {
- panic(err)
- }
- }
- func (z *ioDecReader) readn1() uint8 {
- 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)
- }
- if n > z.a {
- doPanic(msgTagDec, "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])
- }
- // ----------------------------------------
- func decErr(format string, params ...interface{}) {
- doPanic(msgTagDec, format, params...)
- }
- // DecodeTimeExt decodes a []byte into a time.Time,
- // and sets into passed reflectValue.
- func decodeTime(bs []byte) (tt time.Time, err error) {
- var (
- tsec int64
- tnsec int32
- tz uint16
- )
- switch len(bs) {
- case 4:
- tsec = int64(int32(bigen.Uint32(bs)))
- case 6:
- tsec = int64(int32(bigen.Uint32(bs)))
- tz = (bigen.Uint16(bs[4:]))
- case 8:
- tsec = int64(int32(bigen.Uint32(bs)))
- tnsec = int32(bigen.Uint32(bs[4:]))
- case 10:
- tsec = int64(int32(bigen.Uint32(bs)))
- tnsec = int32(bigen.Uint32(bs[4:]))
- tz = (bigen.Uint16(bs[8:]))
- case 9:
- tsec = int64(bigen.Uint64(bs))
- case 11:
- tsec = int64(bigen.Uint64(bs))
- tz = (bigen.Uint16(bs[8:]))
- case 12:
- tsec = int64(bigen.Uint64(bs))
- tnsec = int32(bigen.Uint32(bs[8:]))
- case 14:
- tsec = int64(bigen.Uint64(bs))
- tnsec = int32(bigen.Uint32(bs[8:]))
- tz = (bigen.Uint16(bs[12:]))
- default:
- err = fmt.Errorf("Error decoding bytes: %v as time.Time. Invalid length: %v", bs, len(bs))
- return
- }
- if tz == 0 {
- tt = time.Unix(tsec, int64(tnsec)).UTC()
- } else {
- // In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name.
- // However, we need name here, so it can be shown when time is printed.
- // Zone name is in form: UTC-08:00.
- // Note that Go Libs do not give access to dst flag, so we only check for sign bit
- tzneg := tz & (1 << 15) != 0 //check if negative sign
- tz = tz & 0x1fff //clear 3 MSBs: sign and dst bits
- tzoff := int(tz) * 60
- var tzname = []byte("UTC+00:00")
- if tzneg {
- tzoff = -tzoff
- tzname[3] = '-'
- }
- //tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf. inline below.
- //tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first
- tzhr, tzmin := int(tz/60), int(tz%60)
- tzname[4] = digits[tzhr/10]
- tzname[5] = digits[tzhr%10]
- tzname[7] = digits[tzmin/10]
- tzname[8] = digits[tzmin%10]
-
- //fmt.Printf(">>>>> DEC: tzname: %s, tzoff: %v\n", tzname, tzoff)
- tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone(string(tzname), tzoff))
- }
- return
- }
|