1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642 |
- // Copyright (c) Faye Amacker. All rights reserved.
- // Licensed under the MIT License. See LICENSE in the project root for license information.
-
- package cbor
-
- import (
- "encoding"
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "math"
- "reflect"
- "strconv"
- "strings"
- "time"
- "unicode/utf8"
-
- "github.com/x448/float16"
- )
-
- // Unmarshal parses the CBOR-encoded data and stores the result in the value
- // pointed to by v using the default decoding options. If v is nil or not a
- // pointer, Unmarshal returns an error.
- //
- // Unmarshal uses the inverse of the encodings that Marshal uses, allocating
- // maps, slices, and pointers as necessary, with the following additional rules:
- //
- // To unmarshal CBOR into a pointer, Unmarshal first handles the case of the
- // CBOR being the CBOR literal null. In that case, Unmarshal sets the pointer
- // to nil. Otherwise, Unmarshal unmarshals the CBOR into the value pointed at
- // by the pointer. If the pointer is nil, Unmarshal allocates a new value for
- // it to point to.
- //
- // To unmarshal CBOR into an interface value, Unmarshal stores one of these in
- // the interface value:
- //
- // bool, for CBOR booleans
- // uint64, for CBOR positive integers
- // int64, for CBOR negative integers
- // float64, for CBOR floating points
- // []byte, for CBOR byte strings
- // string, for CBOR text strings
- // []interface{}, for CBOR arrays
- // map[interface{}]interface{}, for CBOR maps
- // nil, for CBOR null
- //
- // To unmarshal a CBOR array into a slice, Unmarshal allocates a new slice only
- // if the CBOR array is empty or slice capacity is less than CBOR array length.
- // Otherwise Unmarshal reuses the existing slice, overwriting existing elements.
- // Unmarshal sets the slice length to CBOR array length.
- //
- // To ummarshal a CBOR array into a Go array, Unmarshal decodes CBOR array
- // elements into corresponding Go array elements. If the Go array is smaller
- // than the CBOR array, the additional CBOR array elements are discarded. If
- // the CBOR array is smaller than the Go array, the additional Go array elements
- // are set to zero values.
- //
- // To unmarshal a CBOR map into a map, Unmarshal allocates a new map only if the
- // map is nil. Otherwise Unmarshal reuses the existing map, keeping existing
- // entries. Unmarshal stores key-value pairs from the CBOR map into Go map.
- //
- // To unmarshal a CBOR map into a struct, Unmarshal matches CBOR map keys to the
- // keys in the following priority:
- //
- // 1. "cbor" key in struct field tag,
- // 2. "json" key in struct field tag,
- // 3. struct field name.
- //
- // Unmarshal prefers an exact match but also accepts a case-insensitive match.
- // Map keys which don't have a corresponding struct field are ignored.
- //
- // To unmarshal a CBOR text string into a time.Time value, Unmarshal parses text
- // string formatted in RFC3339. To unmarshal a CBOR integer/float into a
- // time.Time value, Unmarshal creates an unix time with integer/float as seconds
- // and fractional seconds since January 1, 1970 UTC.
- //
- // To unmarshal CBOR into a value implementing the Unmarshaler interface,
- // Unmarshal calls that value's UnmarshalCBOR method.
- //
- // Unmarshal decodes a CBOR byte string into a value implementing
- // encoding.BinaryUnmarshaler.
- //
- // If a CBOR value is not appropriate for a given Go type, or if a CBOR number
- // overflows the Go type, Unmarshal skips that field and completes the
- // unmarshalling as best as it can. If no more serious errors are encountered,
- // unmarshal returns an UnmarshalTypeError describing the earliest such error.
- // In any case, it's not guaranteed that all the remaining fields following the
- // problematic one will be unmarshaled into the target object.
- //
- // The CBOR null value unmarshals into a slice/map/pointer/interface by setting
- // that Go value to nil. Because null is often used to mean "not present",
- // unmarshalling a CBOR null into any other Go type has no effect on the value
- // produces no error.
- //
- // Unmarshal ignores CBOR tag data and parses tagged data following CBOR tag.
- func Unmarshal(data []byte, v interface{}) error {
- return defaultDecMode.Unmarshal(data, v)
- }
-
- // Unmarshaler is the interface implemented by types that can unmarshal a CBOR
- // representation of themselves. The input can be assumed to be a valid encoding
- // of a CBOR value. UnmarshalCBOR must copy the CBOR data if it wishes to retain
- // the data after returning.
- type Unmarshaler interface {
- UnmarshalCBOR([]byte) error
- }
-
- // InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
- type InvalidUnmarshalError struct {
- Type reflect.Type
- }
-
- func (e *InvalidUnmarshalError) Error() string {
- if e.Type == nil {
- return "cbor: Unmarshal(nil)"
- }
- if e.Type.Kind() != reflect.Ptr {
- return "cbor: Unmarshal(non-pointer " + e.Type.String() + ")"
- }
- return "cbor: Unmarshal(nil " + e.Type.String() + ")"
- }
-
- // UnmarshalTypeError describes a CBOR value that was not appropriate for a Go type.
- type UnmarshalTypeError struct {
- Value string // description of CBOR value
- Type reflect.Type // type of Go value it could not be assigned to
- Struct string // struct type containing the field
- Field string // name of the field holding the Go value
- errMsg string // additional error message (optional)
- }
-
- func (e *UnmarshalTypeError) Error() string {
- var s string
- if e.Struct != "" || e.Field != "" {
- s = "cbor: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String()
- } else {
- s = "cbor: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
- }
- if e.errMsg != "" {
- s += " (" + e.errMsg + ")"
- }
- return s
- }
-
- // DupMapKeyError describes detected duplicate map key in CBOR map.
- type DupMapKeyError struct {
- Key interface{}
- Index int
- }
-
- func (e *DupMapKeyError) Error() string {
- return fmt.Sprintf("cbor: found duplicate map key \"%v\" at map element index %d", e.Key, e.Index)
- }
-
- // DupMapKeyMode specifies how to enforce duplicate map key.
- type DupMapKeyMode int
-
- const (
- // DupMapKeyQuiet doesn't enforce duplicate map key. Decoder quietly (no error)
- // uses faster of "keep first" or "keep last" depending on Go data type and other factors.
- DupMapKeyQuiet DupMapKeyMode = iota
-
- // DupMapKeyEnforcedAPF enforces detection and rejection of duplicate map keys.
- // APF means "Allow Partial Fill" and the destination map or struct can be partially filled.
- // If a duplicate map key is detected, DupMapKeyError is returned without further decoding
- // of the map. It's the caller's responsibility to respond to DupMapKeyError by
- // discarding the partially filled result if their protocol requires it.
- // WARNING: using DupMapKeyEnforcedAPF will decrease performance and increase memory use.
- DupMapKeyEnforcedAPF
-
- maxDupMapKeyMode
- )
-
- func (dmkm DupMapKeyMode) valid() bool {
- return dmkm < maxDupMapKeyMode
- }
-
- // IndefLengthMode specifies whether to allow indefinite length items.
- type IndefLengthMode int
-
- const (
- // IndefLengthAllowed allows indefinite length items.
- IndefLengthAllowed IndefLengthMode = iota
-
- // IndefLengthForbidden disallows indefinite length items.
- IndefLengthForbidden
-
- maxIndefLengthMode
- )
-
- func (m IndefLengthMode) valid() bool {
- return m < maxIndefLengthMode
- }
-
- // TagsMode specifies whether to allow CBOR tags.
- type TagsMode int
-
- const (
- // TagsAllowed allows CBOR tags.
- TagsAllowed TagsMode = iota
-
- // TagsForbidden disallows CBOR tags.
- TagsForbidden
-
- maxTagsMode
- )
-
- func (tm TagsMode) valid() bool {
- return tm < maxTagsMode
- }
-
- // DecOptions specifies decoding options.
- type DecOptions struct {
- // DupMapKey specifies whether to enforce duplicate map key.
- DupMapKey DupMapKeyMode
-
- // TimeTag specifies whether to check validity of time.Time (e.g. valid tag number and tag content type).
- // For now, valid tag number means 0 or 1 as specified in RFC 7049 if the Go type is time.Time.
- TimeTag DecTagMode
-
- // MaxNestedLevels specifies the max nested levels allowed for any combination of CBOR array, maps, and tags.
- // Default is 32 levels and it can be set to [4, 256].
- MaxNestedLevels int
-
- // MaxArrayElements specifies the max number of elements for CBOR arrays.
- // Default is 128*1024=131072 and it can be set to [16, 134217728]
- MaxArrayElements int
-
- // MaxMapPairs specifies the max number of key-value pairs for CBOR maps.
- // Default is 128*1024=131072 and it can be set to [16, 134217728]
- MaxMapPairs int
-
- // IndefLength specifies whether to allow indefinite length CBOR items.
- IndefLength IndefLengthMode
-
- // TagsMd specifies whether to allow CBOR tags (major type 6).
- TagsMd TagsMode
- }
-
- // DecMode returns DecMode with immutable options and no tags (safe for concurrency).
- func (opts DecOptions) DecMode() (DecMode, error) {
- return opts.decMode()
- }
-
- // DecModeWithTags returns DecMode with options and tags that are both immutable (safe for concurrency).
- func (opts DecOptions) DecModeWithTags(tags TagSet) (DecMode, error) {
- if opts.TagsMd == TagsForbidden {
- return nil, errors.New("cbor: cannot create DecMode with TagSet when TagsMd is TagsForbidden")
- }
- if tags == nil {
- return nil, errors.New("cbor: cannot create DecMode with nil value as TagSet")
- }
-
- dm, err := opts.decMode()
- if err != nil {
- return nil, err
- }
-
- // Copy tags
- ts := tagSet(make(map[reflect.Type]*tagItem))
- syncTags := tags.(*syncTagSet)
- syncTags.RLock()
- for contentType, tag := range syncTags.t {
- if tag.opts.DecTag != DecTagIgnored {
- ts[contentType] = tag
- }
- }
- syncTags.RUnlock()
-
- if len(ts) > 0 {
- dm.tags = ts
- }
-
- return dm, nil
- }
-
- // DecModeWithSharedTags returns DecMode with immutable options and mutable shared tags (safe for concurrency).
- func (opts DecOptions) DecModeWithSharedTags(tags TagSet) (DecMode, error) {
- if opts.TagsMd == TagsForbidden {
- return nil, errors.New("cbor: cannot create DecMode with TagSet when TagsMd is TagsForbidden")
- }
- if tags == nil {
- return nil, errors.New("cbor: cannot create DecMode with nil value as TagSet")
- }
- dm, err := opts.decMode()
- if err != nil {
- return nil, err
- }
- dm.tags = tags
- return dm, nil
- }
-
- const (
- defaultMaxArrayElements = 131072
- minMaxArrayElements = 16
- maxMaxArrayElements = 134217728
-
- defaultMaxMapPairs = 131072
- minMaxMapPairs = 16
- maxMaxMapPairs = 134217728
- )
-
- func (opts DecOptions) decMode() (*decMode, error) {
- if !opts.DupMapKey.valid() {
- return nil, errors.New("cbor: invalid DupMapKey " + strconv.Itoa(int(opts.DupMapKey)))
- }
- if !opts.TimeTag.valid() {
- return nil, errors.New("cbor: invalid TimeTag " + strconv.Itoa(int(opts.TimeTag)))
- }
- if !opts.IndefLength.valid() {
- return nil, errors.New("cbor: invalid IndefLength " + strconv.Itoa(int(opts.IndefLength)))
- }
- if !opts.TagsMd.valid() {
- return nil, errors.New("cbor: invalid TagsMd " + strconv.Itoa(int(opts.TagsMd)))
- }
- if opts.MaxNestedLevels == 0 {
- opts.MaxNestedLevels = 32
- } else if opts.MaxNestedLevels < 4 || opts.MaxNestedLevels > 256 {
- return nil, errors.New("cbor: invalid MaxNestedLevels " + strconv.Itoa(opts.MaxNestedLevels) + " (range is [4, 256])")
- }
- if opts.MaxArrayElements == 0 {
- opts.MaxArrayElements = defaultMaxArrayElements
- } else if opts.MaxArrayElements < minMaxArrayElements || opts.MaxArrayElements > maxMaxArrayElements {
- return nil, errors.New("cbor: invalid MaxArrayElements " + strconv.Itoa(opts.MaxArrayElements) + " (range is [" + strconv.Itoa(minMaxArrayElements) + ", " + strconv.Itoa(maxMaxArrayElements) + "])")
- }
- if opts.MaxMapPairs == 0 {
- opts.MaxMapPairs = defaultMaxMapPairs
- } else if opts.MaxMapPairs < minMaxMapPairs || opts.MaxMapPairs > maxMaxMapPairs {
- return nil, errors.New("cbor: invalid MaxMapPairs " + strconv.Itoa(opts.MaxMapPairs) + " (range is [" + strconv.Itoa(minMaxMapPairs) + ", " + strconv.Itoa(maxMaxMapPairs) + "])")
- }
- dm := decMode{
- dupMapKey: opts.DupMapKey,
- timeTag: opts.TimeTag,
- maxNestedLevels: opts.MaxNestedLevels,
- maxArrayElements: opts.MaxArrayElements,
- maxMapPairs: opts.MaxMapPairs,
- indefLength: opts.IndefLength,
- tagsMd: opts.TagsMd,
- }
- return &dm, nil
- }
-
- // DecMode is the main interface for CBOR decoding.
- type DecMode interface {
- Unmarshal(data []byte, v interface{}) error
- NewDecoder(r io.Reader) *Decoder
- DecOptions() DecOptions
- }
-
- type decMode struct {
- tags tagProvider
- dupMapKey DupMapKeyMode
- timeTag DecTagMode
- maxNestedLevels int
- maxArrayElements int
- maxMapPairs int
- indefLength IndefLengthMode
- tagsMd TagsMode
- }
-
- var defaultDecMode, _ = DecOptions{}.decMode()
-
- // DecOptions returns user specified options used to create this DecMode.
- func (dm *decMode) DecOptions() DecOptions {
- return DecOptions{
- DupMapKey: dm.dupMapKey,
- TimeTag: dm.timeTag,
- MaxNestedLevels: dm.maxNestedLevels,
- MaxArrayElements: dm.maxArrayElements,
- MaxMapPairs: dm.maxMapPairs,
- IndefLength: dm.indefLength,
- TagsMd: dm.tagsMd,
- }
- }
-
- // Unmarshal parses the CBOR-encoded data and stores the result in the value
- // pointed to by v using dm DecMode. If v is nil or not a pointer, Unmarshal
- // returns an error.
- //
- // See the documentation for Unmarshal for details.
- func (dm *decMode) Unmarshal(data []byte, v interface{}) error {
- d := decodeState{data: data, dm: dm}
- return d.value(v)
- }
-
- // NewDecoder returns a new decoder that reads from r using dm DecMode.
- func (dm *decMode) NewDecoder(r io.Reader) *Decoder {
- return &Decoder{r: r, d: decodeState{dm: dm}}
- }
-
- type decodeState struct {
- data []byte
- off int // next read offset in data
- dm *decMode
- }
-
- func (d *decodeState) value(v interface{}) error {
- rv := reflect.ValueOf(v)
- if rv.Kind() != reflect.Ptr || rv.IsNil() {
- return &InvalidUnmarshalError{reflect.TypeOf(v)}
- }
-
- off := d.off // Save offset before data validation
- err := d.valid()
- d.off = off // Restore offset
- if err != nil {
- return err
- }
-
- rv = rv.Elem()
-
- if rv.Kind() == reflect.Interface && rv.NumMethod() == 0 {
- // Fast path to decode to empty interface without retrieving typeInfo.
- iv, err := d.parse()
- if iv != nil {
- rv.Set(reflect.ValueOf(iv))
- }
- return err
- }
-
- return d.parseToValue(rv, getTypeInfo(rv.Type()))
- }
-
- type cborType uint8
-
- const (
- cborTypePositiveInt cborType = 0x00
- cborTypeNegativeInt cborType = 0x20
- cborTypeByteString cborType = 0x40
- cborTypeTextString cborType = 0x60
- cborTypeArray cborType = 0x80
- cborTypeMap cborType = 0xa0
- cborTypeTag cborType = 0xc0
- cborTypePrimitives cborType = 0xe0
- )
-
- func (t cborType) String() string {
- switch t {
- case cborTypePositiveInt:
- return "positive integer"
- case cborTypeNegativeInt:
- return "negative integer"
- case cborTypeByteString:
- return "byte string"
- case cborTypeTextString:
- return "UTF-8 text string"
- case cborTypeArray:
- return "array"
- case cborTypeMap:
- return "map"
- case cborTypeTag:
- return "tag"
- case cborTypePrimitives:
- return "primitives"
- default:
- return "Invalid type " + strconv.Itoa(int(t))
- }
- }
-
- // parseToValue assumes data is well-formed, and does not perform bounds checking.
- // This function is complicated because it's the main function that decodes CBOR data to reflect.Value.
- func (d *decodeState) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo
- // Create new value for the pointer v to point to if CBOR value is not nil/undefined.
- if !d.nextCBORNil() {
- for v.Kind() == reflect.Ptr {
- if v.IsNil() {
- if !v.CanSet() {
- d.skip()
- return errors.New("cbor: cannot set new value for " + v.Type().String())
- }
- v.Set(reflect.New(v.Type().Elem()))
- }
- v = v.Elem()
- }
- }
-
- if tInfo.spclType != specialTypeNone {
- switch tInfo.spclType {
- case specialTypeEmptyIface:
- iv, err := d.parse()
- if iv != nil {
- v.Set(reflect.ValueOf(iv))
- }
- return err
- case specialTypeTag:
- return d.parseToTag(v)
- case specialTypeTime:
- return d.parseToTime(v)
- case specialTypeUnmarshalerIface:
- return d.parseToUnmarshaler(v)
- }
- }
-
- // Check registered tag number
- if tagItem := d.getRegisteredTagItem(tInfo.nonPtrType); tagItem != nil {
- t := d.nextCBORType()
- if t != cborTypeTag {
- if tagItem.opts.DecTag == DecTagRequired {
- d.skip() // Required tag number is absent, skip entire tag
- return &UnmarshalTypeError{Value: t.String(), Type: tInfo.typ, errMsg: "expect CBOR tag value"}
- }
- } else if err := d.validRegisteredTagNums(tInfo.nonPtrType, tagItem.num); err != nil {
- d.skip() // Skip tag content
- return err
- }
- }
-
- t := d.nextCBORType()
-
- // Skip tag number(s) here to avoid recursion
- if t == cborTypeTag {
- d.getHead()
- t = d.nextCBORType()
- for t == cborTypeTag {
- d.getHead()
- t = d.nextCBORType()
- }
- }
-
- switch t {
- case cborTypePositiveInt:
- _, _, val := d.getHead()
- return fillPositiveInt(t, val, v)
- case cborTypeNegativeInt:
- _, _, val := d.getHead()
- if val > math.MaxInt64 {
- return &UnmarshalTypeError{
- Value: t.String(),
- Type: tInfo.nonPtrType,
- errMsg: "-1-" + strconv.FormatUint(val, 10) + " overflows Go's int64",
- }
- }
- nValue := int64(-1) ^ int64(val)
- return fillNegativeInt(t, nValue, v)
- case cborTypeByteString:
- b := d.parseByteString()
- return fillByteString(t, b, v)
- case cborTypeTextString:
- b, err := d.parseTextString()
- if err != nil {
- return err
- }
- return fillTextString(t, b, v)
- case cborTypePrimitives:
- _, ai, val := d.getHead()
- if ai < 20 || ai == 24 {
- return fillPositiveInt(t, val, v)
- }
- switch ai {
- case 20, 21:
- return fillBool(t, ai == 21, v)
- case 22, 23:
- return fillNil(t, v)
- case 25:
- f := float64(float16.Frombits(uint16(val)).Float32())
- return fillFloat(t, f, v)
- case 26:
- f := float64(math.Float32frombits(uint32(val)))
- return fillFloat(t, f, v)
- case 27:
- f := math.Float64frombits(val)
- return fillFloat(t, f, v)
- }
- case cborTypeArray:
- if tInfo.nonPtrKind == reflect.Slice {
- return d.parseArrayToSlice(v, tInfo)
- } else if tInfo.nonPtrKind == reflect.Array {
- return d.parseArrayToArray(v, tInfo)
- } else if tInfo.nonPtrKind == reflect.Struct {
- return d.parseArrayToStruct(v, tInfo)
- }
- d.skip()
- return &UnmarshalTypeError{Value: t.String(), Type: tInfo.nonPtrType}
- case cborTypeMap:
- if tInfo.nonPtrKind == reflect.Struct {
- return d.parseMapToStruct(v, tInfo)
- } else if tInfo.nonPtrKind == reflect.Map {
- return d.parseMapToMap(v, tInfo)
- }
- d.skip()
- return &UnmarshalTypeError{Value: t.String(), Type: tInfo.nonPtrType}
- }
- return nil
- }
-
- func (d *decodeState) parseToTag(v reflect.Value) error {
- t := d.nextCBORType()
- if t != cborTypeTag {
- d.skip()
- return &UnmarshalTypeError{Value: t.String(), Type: typeTag}
- }
-
- // Unmarshal tag number
- _, _, num := d.getHead()
-
- // Unmarshal tag content
- content, err := d.parse()
- if err != nil {
- return err
- }
-
- v.Set(reflect.ValueOf(Tag{num, content}))
- return nil
- }
-
- func (d *decodeState) parseToTime(v reflect.Value) error {
- t := d.nextCBORType()
-
- // Verify that tag number or absent of tag number is acceptable to specified timeTag.
- if t == cborTypeTag {
- if d.dm.timeTag == DecTagIgnored {
- // Skip tag number
- d.getHead()
- t = d.nextCBORType()
- for t == cborTypeTag {
- d.getHead()
- t = d.nextCBORType()
- }
- } else {
- // Read tag number
- _, _, tagNum := d.getHead()
-
- // Verify tag number (0 or 1) is followed by appropriate tag content type.
- t = d.nextCBORType()
- switch tagNum {
- case 0:
- // Tag content (date/time text string in RFC 3339 format) must be string type.
- if t != cborTypeTextString {
- d.skip()
- return errors.New("cbor: tag number 0 must be followed by text string, got " + t.String())
- }
- case 1:
- // Tag content (epoch date/time) must be uint, int, or float type.
- if t != cborTypePositiveInt && t != cborTypeNegativeInt && (d.data[d.off] < 0xf9 || d.data[d.off] > 0xfb) {
- d.skip()
- return errors.New("cbor: tag number 1 must be followed by integer or floating-point number, got " + t.String())
- }
- default:
- d.skip()
- return errors.New("cbor: wrong tag number for time.Time, got " + strconv.Itoa(int(tagNum)) + ", expect 0 or 1")
- }
- }
- } else {
- if d.dm.timeTag == DecTagRequired {
- d.skip()
- return &UnmarshalTypeError{Value: t.String(), Type: typeTime, errMsg: "expect CBOR tag value"}
- }
- }
-
- switch t {
- case cborTypePositiveInt:
- _, _, val := d.getHead()
- tm := time.Unix(int64(val), 0)
- v.Set(reflect.ValueOf(tm))
- return nil
- case cborTypeNegativeInt:
- _, _, val := d.getHead()
- if val > math.MaxInt64 {
- return &UnmarshalTypeError{
- Value: t.String(),
- Type: typeTime,
- errMsg: "-1-" + strconv.FormatUint(val, 10) + " overflows Go's int64",
- }
- }
- nValue := int64(-1) ^ int64(val)
- tm := time.Unix(nValue, 0)
- v.Set(reflect.ValueOf(tm))
- return nil
- case cborTypeTextString:
- b, err := d.parseTextString()
- if err != nil {
- return err
- }
- tm, err := time.Parse(time.RFC3339, string(b))
- if err != nil {
- return errors.New("cbor: cannot set " + string(b) + " for time.Time: " + err.Error())
- }
- v.Set(reflect.ValueOf(tm))
- return nil
- case cborTypePrimitives:
- _, ai, val := d.getHead()
- var f float64
- switch ai {
- case 22, 23:
- v.Set(reflect.ValueOf(time.Time{}))
- return nil
- case 25:
- f = float64(float16.Frombits(uint16(val)).Float32())
- case 26:
- f = float64(math.Float32frombits(uint32(val)))
- case 27:
- f = math.Float64frombits(val)
- default:
- return &UnmarshalTypeError{Value: t.String(), Type: typeTime}
- }
- if math.IsNaN(f) || math.IsInf(f, 0) {
- v.Set(reflect.ValueOf(time.Time{}))
- return nil
- }
- f1, f2 := math.Modf(f)
- tm := time.Unix(int64(f1), int64(f2*1e9))
- v.Set(reflect.ValueOf(tm))
- return nil
- }
- d.skip()
- return &UnmarshalTypeError{Value: t.String(), Type: typeTime}
- }
-
- // parseToUnmarshaler assumes data is well-formed, and does not perform bounds checking.
- func (d *decodeState) parseToUnmarshaler(v reflect.Value) error {
- if d.nextCBORNil() && v.Kind() == reflect.Ptr && v.IsNil() {
- d.skip()
- return nil
- }
-
- if v.Kind() != reflect.Ptr && v.CanAddr() {
- v = v.Addr()
- }
- if u, ok := v.Interface().(Unmarshaler); ok {
- start := d.off
- d.skip()
- return u.UnmarshalCBOR(d.data[start:d.off])
- }
- d.skip()
- return errors.New("cbor: failed to assert " + v.Type().String() + " as cbor.Unmarshaler")
- }
-
- // parse assumes data is well-formed, and does not perform bounds checking.
- func (d *decodeState) parse() (interface{}, error) {
- t := d.nextCBORType()
- switch t {
- case cborTypePositiveInt:
- _, _, val := d.getHead()
- return val, nil
- case cborTypeNegativeInt:
- _, _, val := d.getHead()
- if val > math.MaxInt64 {
- return nil, &UnmarshalTypeError{
- Value: t.String(),
- Type: reflect.TypeOf([]interface{}(nil)).Elem(),
- errMsg: "-1-" + strconv.FormatUint(val, 10) + " overflows Go's int64",
- }
- }
- nValue := int64(-1) ^ int64(val)
- return nValue, nil
- case cborTypeByteString:
- return d.parseByteString(), nil
- case cborTypeTextString:
- b, err := d.parseTextString()
- if err != nil {
- return nil, err
- }
- return string(b), nil
- case cborTypeTag:
- _, _, tagNum := d.getHead()
- nt := d.nextCBORType()
- content, err := d.parse()
- if err != nil {
- return nil, err
- }
- switch tagNum {
- case 0:
- // Tag content should be date/time text string in RFC 3339 format.
- s, ok := content.(string)
- if !ok {
- return nil, errors.New("cbor: tag number 0 must be followed by text string, got " + nt.String())
- }
- tm, err := time.Parse(time.RFC3339, s)
- if err != nil {
- return nil, errors.New("cbor: cannot set " + s + " for time.Time: " + err.Error())
- }
- return tm, nil
- case 1:
- // Tag content should be epoch date/time.
- switch content := content.(type) {
- case uint64:
- return time.Unix(int64(content), 0), nil
- case int64:
- return time.Unix(content, 0), nil
- case float64:
- f1, f2 := math.Modf(content)
- return time.Unix(int64(f1), int64(f2*1e9)), nil
- default:
- return nil, errors.New("cbor: tag number 1 must be followed by integer or floating-point number, got " + nt.String())
- }
- }
- return Tag{tagNum, content}, nil
- case cborTypePrimitives:
- _, ai, val := d.getHead()
- if ai < 20 || ai == 24 {
- return val, nil
- }
- switch ai {
- case 20, 21:
- return (ai == 21), nil
- case 22, 23:
- return nil, nil
- case 25:
- f := float64(float16.Frombits(uint16(val)).Float32())
- return f, nil
- case 26:
- f := float64(math.Float32frombits(uint32(val)))
- return f, nil
- case 27:
- f := math.Float64frombits(val)
- return f, nil
- }
- case cborTypeArray:
- return d.parseArray()
- case cborTypeMap:
- return d.parseMap()
- }
- return nil, nil
- }
-
- // parseByteString parses CBOR encoded byte string. It returns a byte slice
- // pointing to a copy of parsed data.
- func (d *decodeState) parseByteString() []byte {
- _, ai, val := d.getHead()
- if ai != 31 {
- b := make([]byte, int(val))
- copy(b, d.data[d.off:d.off+int(val)])
- d.off += int(val)
- return b
- }
- // Process indefinite length string chunks.
- b := []byte{}
- for !d.foundBreak() {
- _, _, val = d.getHead()
- b = append(b, d.data[d.off:d.off+int(val)]...)
- d.off += int(val)
- }
- return b
- }
-
- // parseTextString parses CBOR encoded text string. It does not return a string
- // to prevent creating an extra copy of string. Caller should wrap returned
- // byte slice as string when needed.
- //
- // parseStruct() uses parseTextString() to improve memory and performance,
- // compared with using parse(reflect.Value). parse(reflect.Value) sets
- // reflect.Value with parsed string, while parseTextString() returns zero-copy []byte.
- func (d *decodeState) parseTextString() ([]byte, error) {
- _, ai, val := d.getHead()
- if ai != 31 {
- b := d.data[d.off : d.off+int(val)]
- d.off += int(val)
- if !utf8.Valid(b) {
- return nil, &SemanticError{"cbor: invalid UTF-8 string"}
- }
- return b, nil
- }
- // Process indefinite length string chunks.
- b := []byte{}
- for !d.foundBreak() {
- _, _, val = d.getHead()
- x := d.data[d.off : d.off+int(val)]
- d.off += int(val)
- if !utf8.Valid(x) {
- for !d.foundBreak() {
- d.skip() // Skip remaining chunk on error
- }
- return nil, &SemanticError{"cbor: invalid UTF-8 string"}
- }
- b = append(b, x...)
- }
- return b, nil
- }
-
- func (d *decodeState) parseArray() ([]interface{}, error) {
- _, ai, val := d.getHead()
- hasSize := (ai != 31)
- count := int(val)
- if !hasSize {
- count = d.numOfItemsUntilBreak() // peek ahead to get array size to preallocate slice for better performance
- }
- v := make([]interface{}, count)
- var e interface{}
- var err, lastErr error
- for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ {
- if e, lastErr = d.parse(); lastErr != nil {
- if err == nil {
- err = lastErr
- }
- continue
- }
- v[i] = e
- }
- return v, err
- }
-
- func (d *decodeState) parseArrayToSlice(v reflect.Value, tInfo *typeInfo) error {
- _, ai, val := d.getHead()
- hasSize := (ai != 31)
- count := int(val)
- if !hasSize {
- count = d.numOfItemsUntilBreak() // peek ahead to get array size to preallocate slice for better performance
- }
- if count == 0 {
- v.Set(reflect.MakeSlice(tInfo.nonPtrType, 0, 0))
- }
- if v.IsNil() || v.Cap() < count {
- v.Set(reflect.MakeSlice(tInfo.nonPtrType, count, count))
- }
- v.SetLen(count)
- var err error
- for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ {
- if lastErr := d.parseToValue(v.Index(i), tInfo.elemTypeInfo); lastErr != nil {
- if err == nil {
- err = lastErr
- }
- }
- }
- return err
- }
-
- func (d *decodeState) parseArrayToArray(v reflect.Value, tInfo *typeInfo) error {
- _, ai, val := d.getHead()
- hasSize := (ai != 31)
- count := int(val)
- gi := 0
- vLen := v.Len()
- var err error
- for ci := 0; (hasSize && ci < count) || (!hasSize && !d.foundBreak()); ci++ {
- if gi < vLen {
- // Read CBOR array element and set array element
- if lastErr := d.parseToValue(v.Index(gi), tInfo.elemTypeInfo); lastErr != nil {
- if err == nil {
- err = lastErr
- }
- }
- gi++
- } else {
- d.skip() // Skip remaining CBOR array element
- }
- }
- // Set remaining Go array elements to zero values.
- if gi < vLen {
- zeroV := reflect.Zero(tInfo.elemTypeInfo.typ)
- for ; gi < vLen; gi++ {
- v.Index(gi).Set(zeroV)
- }
- }
- return err
- }
-
- func (d *decodeState) parseMap() (map[interface{}]interface{}, error) {
- _, ai, val := d.getHead()
- hasSize := (ai != 31)
- count := int(val)
- m := make(map[interface{}]interface{})
- var k, e interface{}
- var err, lastErr error
- keyCount := 0
- for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ {
- // Parse CBOR map key.
- if k, lastErr = d.parse(); lastErr != nil {
- if err == nil {
- err = lastErr
- }
- d.skip()
- continue
- }
-
- // Detect if CBOR map key can be used as Go map key.
- kkind := reflect.ValueOf(k).Kind()
- if tag, ok := k.(Tag); ok {
- kkind = tag.contentKind()
- }
- if !isHashableKind(kkind) {
- if err == nil {
- err = errors.New("cbor: invalid map key type: " + kkind.String())
- }
- d.skip()
- continue
- }
-
- // Parse CBOR map value.
- if e, lastErr = d.parse(); lastErr != nil {
- if err == nil {
- err = lastErr
- }
- continue
- }
-
- // Add key-value pair to Go map.
- m[k] = e
-
- // Detect duplicate map key.
- if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
- newKeyCount := len(m)
- if newKeyCount == keyCount {
- m[k] = nil
- err = &DupMapKeyError{k, i}
- i++
- // skip the rest of the map
- for ; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ {
- d.skip() // Skip map key
- d.skip() // Skip map value
- }
- return m, err
- }
- keyCount = newKeyCount
- }
- }
- return m, err
- }
-
- func (d *decodeState) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo
- _, ai, val := d.getHead()
- hasSize := (ai != 31)
- count := int(val)
- if v.IsNil() {
- mapsize := count
- if !hasSize {
- mapsize = 0
- }
- v.Set(reflect.MakeMapWithSize(tInfo.nonPtrType, mapsize))
- }
- keyType, eleType := tInfo.keyTypeInfo.typ, tInfo.elemTypeInfo.typ
- reuseKey, reuseEle := isImmutableKind(tInfo.keyTypeInfo.kind), isImmutableKind(tInfo.elemTypeInfo.kind)
- var keyValue, eleValue, zeroKeyValue, zeroEleValue reflect.Value
- keyIsInterfaceType := keyType == typeIntf // If key type is interface{}, need to check if key value is hashable.
- var err, lastErr error
- keyCount := v.Len()
- var existingKeys map[interface{}]bool // Store existing map keys, used for detecting duplicate map key.
- if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
- existingKeys = make(map[interface{}]bool, keyCount)
- if keyCount > 0 {
- vKeys := v.MapKeys()
- for i := 0; i < len(vKeys); i++ {
- existingKeys[vKeys[i].Interface()] = true
- }
- }
- }
- for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ {
- // Parse CBOR map key.
- if !keyValue.IsValid() {
- keyValue = reflect.New(keyType).Elem()
- } else if !reuseKey {
- if !zeroKeyValue.IsValid() {
- zeroKeyValue = reflect.Zero(keyType)
- }
- keyValue.Set(zeroKeyValue)
- }
- if lastErr = d.parseToValue(keyValue, tInfo.keyTypeInfo); lastErr != nil {
- if err == nil {
- err = lastErr
- }
- d.skip()
- continue
- }
-
- // Detect if CBOR map key can be used as Go map key.
- if keyIsInterfaceType {
- kkind := keyValue.Elem().Kind()
- if keyValue.Elem().IsValid() {
- if tag, ok := keyValue.Elem().Interface().(Tag); ok {
- kkind = tag.contentKind()
- }
- }
- if !isHashableKind(kkind) {
- if err == nil {
- err = errors.New("cbor: invalid map key type: " + kkind.String())
- }
- d.skip()
- continue
- }
- }
-
- // Parse CBOR map value.
- if !eleValue.IsValid() {
- eleValue = reflect.New(eleType).Elem()
- } else if !reuseEle {
- if !zeroEleValue.IsValid() {
- zeroEleValue = reflect.Zero(eleType)
- }
- eleValue.Set(zeroEleValue)
- }
- if lastErr := d.parseToValue(eleValue, tInfo.elemTypeInfo); lastErr != nil {
- if err == nil {
- err = lastErr
- }
- continue
- }
-
- // Add key-value pair to Go map.
- v.SetMapIndex(keyValue, eleValue)
-
- // Detect duplicate map key.
- if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
- newKeyCount := v.Len()
- if newKeyCount == keyCount {
- kvi := keyValue.Interface()
- if !existingKeys[kvi] {
- v.SetMapIndex(keyValue, reflect.New(eleType).Elem())
- err = &DupMapKeyError{kvi, i}
- i++
- // skip the rest of the map
- for ; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ {
- d.skip() // skip map key
- d.skip() // skip map value
- }
- return err
- }
- delete(existingKeys, kvi)
- }
- keyCount = newKeyCount
- }
- }
- return err
- }
-
- func (d *decodeState) parseArrayToStruct(v reflect.Value, tInfo *typeInfo) error {
- structType := getDecodingStructType(tInfo.nonPtrType)
- if structType.err != nil {
- return structType.err
- }
-
- if !structType.toArray {
- t := d.nextCBORType()
- d.skip()
- return &UnmarshalTypeError{
- Value: t.String(),
- Type: tInfo.nonPtrType,
- errMsg: "cannot decode CBOR array to struct without toarray option",
- }
- }
-
- start := d.off
- t, ai, val := d.getHead()
- hasSize := (ai != 31)
- count := int(val)
- if !hasSize {
- count = d.numOfItemsUntilBreak() // peek ahead to get array size
- }
- if count != len(structType.fields) {
- d.off = start
- d.skip()
- return &UnmarshalTypeError{
- Value: t.String(),
- Type: tInfo.typ,
- errMsg: "cannot decode CBOR array to struct with different number of elements",
- }
- }
- var err error
- for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ {
- f := structType.fields[i]
- fv, lastErr := fieldByIndex(v, f.idx)
- if lastErr != nil {
- if err == nil {
- err = lastErr
- }
- d.skip()
- continue
- }
- if lastErr := d.parseToValue(fv, f.typInfo); lastErr != nil {
- if err == nil {
- if typeError, ok := lastErr.(*UnmarshalTypeError); ok {
- typeError.Struct = tInfo.typ.String()
- typeError.Field = f.name
- err = typeError
- } else {
- err = lastErr
- }
- }
- }
- }
- return err
- }
-
- // parseMapToStruct needs to be fast so gocyclo can be ignored for now.
- func (d *decodeState) parseMapToStruct(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo
- structType := getDecodingStructType(tInfo.nonPtrType)
- if structType.err != nil {
- return structType.err
- }
-
- if structType.toArray {
- t := d.nextCBORType()
- d.skip()
- return &UnmarshalTypeError{
- Value: t.String(),
- Type: tInfo.nonPtrType,
- errMsg: "cannot decode CBOR map to struct with toarray option",
- }
- }
-
- foundFldIdx := make([]bool, len(structType.fields))
- _, ai, val := d.getHead()
- hasSize := (ai != 31)
- count := int(val)
- var err, lastErr error
- keyCount := 0
- var mapKeys map[interface{}]struct{} // Store map keys, used for detecting duplicate map key.
- if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
- mapKeys = make(map[interface{}]struct{}, len(structType.fields))
- }
- for j := 0; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ {
- var f *field
- var k interface{} // Used by duplicate map key detection
-
- t := d.nextCBORType()
- if t == cborTypeTextString {
- var keyBytes []byte
- keyBytes, lastErr = d.parseTextString()
- if lastErr != nil {
- if err == nil {
- err = lastErr
- }
- d.skip() // skip value
- continue
- }
-
- keyLen := len(keyBytes)
- // Find field with exact match
- for i := 0; i < len(structType.fields); i++ {
- fld := structType.fields[i]
- if !foundFldIdx[i] && len(fld.name) == keyLen && fld.name == string(keyBytes) {
- f = fld
- foundFldIdx[i] = true
- break
- }
- }
- // Find field with case-insensitive match
- if f == nil {
- keyString := string(keyBytes)
- for i := 0; i < len(structType.fields); i++ {
- fld := structType.fields[i]
- if !foundFldIdx[i] && len(fld.name) == keyLen && strings.EqualFold(fld.name, keyString) {
- f = fld
- foundFldIdx[i] = true
- break
- }
- }
- }
-
- if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
- k = string(keyBytes)
- }
- } else if t <= cborTypeNegativeInt { // uint/int
- var nameAsInt int64
-
- if t == cborTypePositiveInt {
- _, _, val := d.getHead()
- nameAsInt = int64(val)
- } else {
- _, _, val := d.getHead()
- if val > math.MaxInt64 {
- if err == nil {
- err = &UnmarshalTypeError{
- Value: t.String(),
- Type: reflect.TypeOf(int64(0)),
- errMsg: "-1-" + strconv.FormatUint(val, 10) + " overflows Go's int64",
- }
- }
- d.skip() // skip value
- continue
- }
- nameAsInt = int64(-1) ^ int64(val)
- }
-
- // Find field
- for i := 0; i < len(structType.fields); i++ {
- fld := structType.fields[i]
- if !foundFldIdx[i] && fld.keyAsInt && fld.nameAsInt == nameAsInt {
- f = fld
- foundFldIdx[i] = true
- break
- }
- }
-
- if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
- k = nameAsInt
- }
- } else {
- if err == nil {
- err = &UnmarshalTypeError{
- Value: t.String(),
- Type: reflect.TypeOf(""),
- errMsg: "map key is of type " + t.String() + " and cannot be used to match struct field name",
- }
- }
- if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
- // parse key
- k, lastErr = d.parse()
- if lastErr != nil {
- d.skip() // skip value
- continue
- }
- // Detect if CBOR map key can be used as Go map key.
- kkind := reflect.ValueOf(k).Kind()
- if tag, ok := k.(Tag); ok {
- kkind = tag.contentKind()
- }
- if !isHashableKind(kkind) {
- d.skip() // skip value
- continue
- }
- } else {
- d.skip() // skip key
- }
- }
-
- if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
- mapKeys[k] = struct{}{}
- newKeyCount := len(mapKeys)
- if newKeyCount == keyCount {
- err = &DupMapKeyError{k, j}
- d.skip() // skip value
- j++
- // skip the rest of the map
- for ; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ {
- d.skip()
- d.skip()
- }
- return err
- }
- keyCount = newKeyCount
- }
-
- if f == nil {
- d.skip() // Skip value
- continue
- }
- // reflect.Value.FieldByIndex() panics at nil pointer to unexported
- // anonymous field. fieldByIndex() returns error.
- fv, lastErr := fieldByIndex(v, f.idx)
- if lastErr != nil {
- if err == nil {
- err = lastErr
- }
- d.skip()
- continue
- }
- if lastErr = d.parseToValue(fv, f.typInfo); lastErr != nil {
- if err == nil {
- if typeError, ok := lastErr.(*UnmarshalTypeError); ok {
- typeError.Struct = tInfo.nonPtrType.String()
- typeError.Field = f.name
- err = typeError
- } else {
- err = lastErr
- }
- }
- }
- }
- return err
- }
-
- // validRegisteredTagNums verifies that tag numbers match registered tag numbers of type t.
- // validRegisteredTagNums assumes next CBOR data type is tag. It scans all tag numbers, and stops at tag content.
- func (d *decodeState) validRegisteredTagNums(t reflect.Type, registeredTagNums []uint64) error {
- // Scan until next cbor data is tag content.
- tagNums := make([]uint64, 0, 2)
- for d.nextCBORType() == cborTypeTag {
- _, _, val := d.getHead()
- tagNums = append(tagNums, val)
- }
-
- // Verify that tag numbers match registered tag numbers of type t
- if len(tagNums) != len(registeredTagNums) {
- return &WrongTagError{t, registeredTagNums, tagNums}
- }
- for i, n := range registeredTagNums {
- if n != tagNums[i] {
- return &WrongTagError{t, registeredTagNums, tagNums}
- }
- }
- return nil
- }
-
- func (d *decodeState) getRegisteredTagItem(vt reflect.Type) *tagItem {
- if d.dm.tags != nil {
- return d.dm.tags.get(vt)
- }
- return nil
- }
-
- // skip moves data offset to the next item. skip assumes data is well-formed,
- // and does not perform bounds checking.
- func (d *decodeState) skip() {
- t, ai, val := d.getHead()
-
- if ai == 31 {
- switch t {
- case cborTypeByteString, cborTypeTextString, cborTypeArray, cborTypeMap:
- for {
- if d.data[d.off] == 0xff {
- d.off++
- return
- }
- d.skip()
- }
- }
- }
-
- switch t {
- case cborTypeByteString, cborTypeTextString:
- d.off += int(val)
- case cborTypeArray:
- for i := 0; i < int(val); i++ {
- d.skip()
- }
- case cborTypeMap:
- for i := 0; i < int(val)*2; i++ {
- d.skip()
- }
- case cborTypeTag:
- d.skip()
- }
- }
-
- // getHead assumes data is well-formed, and does not perform bounds checking.
- func (d *decodeState) getHead() (t cborType, ai byte, val uint64) {
- t = cborType(d.data[d.off] & 0xe0)
- ai = d.data[d.off] & 0x1f
- val = uint64(ai)
- d.off++
-
- if ai < 24 {
- return
- }
- if ai == 24 {
- val = uint64(d.data[d.off])
- d.off++
- return
- }
- if ai == 25 {
- val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+2]))
- d.off += 2
- return
- }
- if ai == 26 {
- val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+4]))
- d.off += 4
- return
- }
- if ai == 27 {
- val = binary.BigEndian.Uint64(d.data[d.off : d.off+8])
- d.off += 8
- return
- }
- return
- }
-
- func (d *decodeState) numOfItemsUntilBreak() int {
- savedOff := d.off
- i := 0
- for !d.foundBreak() {
- d.skip()
- i++
- }
- d.off = savedOff
- return i
- }
-
- // foundBreak assumes data is well-formed, and does not perform bounds checking.
- func (d *decodeState) foundBreak() bool {
- if d.data[d.off] == 0xff {
- d.off++
- return true
- }
- return false
- }
-
- func (d *decodeState) reset(data []byte) {
- d.data = data
- d.off = 0
- }
-
- func (d *decodeState) nextCBORType() cborType {
- return cborType(d.data[d.off] & 0xe0)
- }
-
- func (d *decodeState) nextCBORNil() bool {
- return d.data[d.off] == 0xf6 || d.data[d.off] == 0xf7
- }
-
- var (
- typeIntf = reflect.TypeOf([]interface{}(nil)).Elem()
- typeTime = reflect.TypeOf(time.Time{})
- typeUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
- typeBinaryUnmarshaler = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
- )
-
- func fillNil(t cborType, v reflect.Value) error {
- switch v.Kind() {
- case reflect.Slice, reflect.Map, reflect.Interface, reflect.Ptr:
- v.Set(reflect.Zero(v.Type()))
- return nil
- }
- return nil
- }
-
- func fillPositiveInt(t cborType, val uint64, v reflect.Value) error {
- switch v.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- if val > math.MaxInt64 {
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type(), errMsg: strconv.FormatUint(val, 10) + " overflows " + v.Type().String()}
- }
- if v.OverflowInt(int64(val)) {
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type(), errMsg: strconv.FormatUint(val, 10) + " overflows " + v.Type().String()}
- }
- v.SetInt(int64(val))
- return nil
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- if v.OverflowUint(val) {
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type(), errMsg: strconv.FormatUint(val, 10) + " overflows " + v.Type().String()}
- }
- v.SetUint(val)
- return nil
- case reflect.Float32, reflect.Float64:
- f := float64(val)
- v.SetFloat(f)
- return nil
- }
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type()}
- }
-
- func fillNegativeInt(t cborType, val int64, v reflect.Value) error {
- switch v.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- if v.OverflowInt(val) {
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type(), errMsg: strconv.FormatInt(val, 10) + " overflows " + v.Type().String()}
- }
- v.SetInt(val)
- return nil
- case reflect.Float32, reflect.Float64:
- f := float64(val)
- v.SetFloat(f)
- return nil
- }
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type()}
- }
-
- func fillBool(t cborType, val bool, v reflect.Value) error {
- if v.Kind() == reflect.Bool {
- v.SetBool(val)
- return nil
- }
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type()}
- }
-
- func fillFloat(t cborType, val float64, v reflect.Value) error {
- switch v.Kind() {
- case reflect.Float32, reflect.Float64:
- if v.OverflowFloat(val) {
- return &UnmarshalTypeError{
- Value: t.String(),
- Type: v.Type(),
- errMsg: strconv.FormatFloat(val, 'E', -1, 64) + " overflows " + v.Type().String(),
- }
- }
- v.SetFloat(val)
- return nil
- }
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type()}
- }
-
- func fillByteString(t cborType, val []byte, v reflect.Value) error {
- if reflect.PtrTo(v.Type()).Implements(typeBinaryUnmarshaler) {
- if v.CanAddr() {
- v = v.Addr()
- if u, ok := v.Interface().(encoding.BinaryUnmarshaler); ok {
- return u.UnmarshalBinary(val)
- }
- }
- return errors.New("cbor: cannot set new value for " + v.Type().String())
- }
- if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 {
- v.SetBytes(val)
- return nil
- }
- if v.Kind() == reflect.Array && v.Type().Elem().Kind() == reflect.Uint8 {
- vLen := v.Len()
- i := 0
- for ; i < vLen && i < len(val); i++ {
- v.Index(i).SetUint(uint64(val[i]))
- }
- // Set remaining Go array elements to zero values.
- if i < vLen {
- zeroV := reflect.Zero(reflect.TypeOf(byte(0)))
- for ; i < vLen; i++ {
- v.Index(i).Set(zeroV)
- }
- }
- return nil
- }
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type()}
- }
-
- func fillTextString(t cborType, val []byte, v reflect.Value) error {
- if v.Kind() == reflect.String {
- v.SetString(string(val))
- return nil
- }
- return &UnmarshalTypeError{Value: t.String(), Type: v.Type()}
- }
-
- func isImmutableKind(k reflect.Kind) bool {
- switch k {
- case reflect.Bool,
- reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
- reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
- reflect.Float32, reflect.Float64,
- reflect.String:
- return true
- default:
- return false
- }
- }
-
- func isHashableKind(k reflect.Kind) bool {
- switch k {
- case reflect.Slice, reflect.Map, reflect.Func:
- return false
- default:
- return true
- }
- }
-
- // fieldByIndex returns the nested field corresponding to the index. It
- // allocates pointer to struct field if it is nil and settable.
- // reflect.Value.FieldByIndex() panics at nil pointer to unexported anonymous
- // field. This function returns error.
- func fieldByIndex(v reflect.Value, index []int) (reflect.Value, error) {
- for _, i := range index {
- if v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct {
- if v.IsNil() {
- if !v.CanSet() {
- return reflect.Value{}, errors.New("cbor: cannot set embedded pointer to unexported struct: " + v.Type().String())
- }
- v.Set(reflect.New(v.Type().Elem()))
- }
- v = v.Elem()
- }
- v = v.Field(i)
- }
- return v, nil
- }
|