tive {
				keyLen := len(keyBytes)
				keyString := string(keyBytes)
				for i := 0; i < len(structType.fields); i++ {
					fld := structType.fields[i]
					if len(fld.name) == keyLen && strings.EqualFold(fld.name, keyString) {
						if !foundFldIdx[i] {
							f = fld
							foundFldIdx[i] = true
						} else if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
							err = &DupMapKeyError{keyString, 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
						} else {
							// discard repeated match
							d.skip()
							continue MapEntryLoop
						}
						break
					}
				}
			}

			if d.dm.dupMapKey == DupMapKeyEnforcedAPF && f == nil {
				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{
							CBORType: t.String(),
							GoType:   reflect.TypeOf(int64(0)).String(),
							errorMsg: "-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 fld.keyAsInt && fld.nameAsInt == nameAsInt {
					if !foundFldIdx[i] {
						f = fld
						foundFldIdx[i] = true
					} else if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
						err = &DupMapKeyError{nameAsInt, 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
					} else {
						// discard repeated match
						d.skip()
						continue MapEntryLoop
					}
					break
				}
			}

			if d.dm.dupMapKey == DupMapKeyEnforcedAPF && f == nil {
				k = nameAsInt
			}
		} else {
			if err == nil {
				err = &UnmarshalTypeError{
					CBORType: t.String(),
					GoType:   reflect.TypeOf("").String(),
					errorMsg: "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(true)
				if lastErr != nil {
					d.skip() // skip value
					continue
				}
				// Detect if CBOR map key can be used as Go map key.
				if !isHashableValue(reflect.ValueOf(k)) {
					d.skip() // skip value
					continue
				}
			} else {
				d.skip() // skip key
			}
		}

		if f == nil {
			if errOnUnknownField {
				err = &UnknownFieldError{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
			}

			// Two map keys that match the same struct field are immediately considered
			// duplicates. This check detects duplicates between two map keys that do
			// not match a struct field. If unknown field errors are enabled, then this
			// check is never reached.
			if d.dm.dupMapKey == DupMapKeyEnforcedAPF {
				if mapKeys == nil {
					mapKeys = make(map[any]struct{}, 1)
				}
				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
			}

			d.skip() // Skip value
			continue
		}

		// Get field value by index
		var fv reflect.Value
		if len(f.idx) == 1 {
			fv = v.Field(f.idx[0])
		} else {
			fv, lastErr = getFieldValue(v, f.idx, func(v reflect.Value) (reflect.Value, error) {
				// Return a new value for embedded field null pointer to point to, or return error.
				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()))
				return v, nil
			})
			if lastErr != nil && err == nil {
				err = lastErr
			}
			if !fv.IsValid() {
				d.skip()
				continue
			}
		}

		if lastErr = d.parseToValue(fv, f.typInfo); lastErr != nil {
			if err == nil {
				if typeError, ok := lastErr.(*UnmarshalTypeError); ok {
					typeError.StructFieldName = tInfo.nonPtrType.String() + "." + 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 *decoder) validRegisteredTagNums(registeredTag *tagItem) error {
	// Scan until next cbor data is tag content.
	tagNums := make([]uint64, 0, 1)
	for d.nextCBORType() == cborTypeTag {
		_, _, val := d.getHead()
		tagNums = append(tagNums, val)
	}

	if !registeredTag.equalTagNum(tagNums) {
		return &WrongTagError{registeredTag.contentType, registeredTag.num, tagNums}
	}
	return nil
}

func (d *decoder) getRegisteredTagItem(vt reflect.Type) *tagItem {
	if d.dm.tags != nil {
		return d.dm.tags.getTagItemFromType(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 *decoder) skip() {
	t, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag()

	if indefiniteLength {
		switch t {
		case cborTypeByteString, cborTypeTextString, cborTypeArray, cborTypeMap:
			for {
				if isBreakFlag(d.data[d.off]) {
					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()
	}
}

func (d *decoder) getHeadWithIndefiniteLengthFlag() (
	t cborType,
	ai byte,
	val uint64,
	indefiniteLength bool,
) {
	t, ai, val = d.getHead()
	indefiniteLength = additionalInformation(ai).isIndefiniteLength()
	return
}

// getHead assumes data is well-formed, and does not perform bounds checking.
func (d *decoder) getHead() (t cborType, ai byte, val uint64) {
	t, ai = parseInitialByte(d.data[d.off])
	val = uint64(ai)
	d.off++

	if ai <= maxAdditionalInformationWithoutArgument {
		return
	}

	if ai == additionalInformationWith1ByteArgument {
		val = uint64(d.data[d.off])
		d.off++
		return
	}

	if ai == additionalInformationWith2ByteArgument {
		const argumentSize = 2
		val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+argumentSize]))
		d.off += argumentSize
		return
	}

	if ai == additionalInformationWith4ByteArgument {
		const argumentSize = 4
		val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+argumentSize]))
		d.off += argumentSize
		return
	}

	if ai == additionalInformationWith8ByteArgument {
		const argumentSize = 8
		val = binary.BigEndian.Uint64(d.data[d.off : d.off+argumentSize])
		d.off += argumentSize
		return
	}
	return
}

func (d *decoder) numOfItemsUntilBreak() int {
	savedOff := d.off
	i := 0
	for !d.foundBreak() {
		d.skip()
		i++
	}
	d.off = savedOff
	return i
}

// foundBreak returns true if next byte is CBOR break code and moves cursor by 1,
// otherwise it returns false.
// foundBreak assumes data is well-formed, and does not perform bounds checking.
func (d *decoder) foundBreak() bool {
	if isBreakFlag(d.data[d.off]) {
		d.off++
		return true
	}
	return false
}

func (d *decoder) reset(data []byte) {
	d.data = data
	d.off = 0
	d.expectedLaterEncodingTags = d.expectedLaterEncodingTags[:0]
}

func (d *decoder) nextCBORType() cborType {
	return getType(d.data[d.off])
}

func (d *decoder) nextCBORNil() bool {
	return d.data[d.off] == 0xf6 || d.data[d.off] == 0xf7
}

type jsonUnmarshaler interface{ UnmarshalJSON([]byte) error }

var (
	typeIntf                  = reflect.TypeOf([]any(nil)).Elem()
	typeTime                  = reflect.TypeOf(time.Time{})
	typeBigInt                = reflect.TypeOf(big.Int{})
	typeUnmarshaler           = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
	typeUnexportedUnmarshaler = reflect.TypeOf((*unmarshaler)(nil)).Elem()
	typeBinaryUnmarshaler     = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
	typeTextUnmarshaler       = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
	typeJSONUnmarshaler       = reflect.TypeOf((*jsonUnmarshaler)(nil)).Elem()
	typeString                = reflect.TypeOf("")
	typeByteSlice             = reflect.TypeOf([]byte(nil))
)

func fillNil(_ cborType, v reflect.Value) error {
	switch v.Kind() {
	case reflect.Slice, reflect.Map, reflect.Interface, reflect.Pointer:
		v.SetZero()
		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{
				CBORType: t.String(),
				GoType:   v.Type().String(),
				errorMsg: strconv.FormatUint(val, 10) + " overflows " + v.Type().String(),
			}
		}
		if v.OverflowInt(int64(val)) {
			return &UnmarshalTypeError{
				CBORType: t.String(),
				GoType:   v.Type().String(),
				errorMsg: 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{
				CBORType: t.String(),
				GoType:   v.Type().String(),
				errorMsg: 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
	}

	if v.Type() == typeBigInt {
		i := new(big.Int).SetUint64(val)
		v.Set(reflect.ValueOf(*i))
		return nil
	}
	return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()}
}

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{
				CBORType: t.String(),
				GoType:   v.Type().String(),
				errorMsg: 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
	}
	if v.Type() == typeBigInt {
		i := new(big.Int).SetInt64(val)
		v.Set(reflect.ValueOf(*i))
		return nil
	}
	return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()}
}

func fillBool(t cborType, val bool, v reflect.Value) error {
	if v.Kind() == reflect.Bool {
		v.SetBool(val)
		return nil
	}
	return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()}
}

func fillFloat(t cborType, val float64, v reflect.Value) error {
	switch v.Kind() {
	case reflect.Float32, reflect.Float64:
		if v.OverflowFloat(val) {
			return &UnmarshalTypeError{
				CBORType: t.String(),
				GoType:   v.Type().String(),
				errorMsg: strconv.FormatFloat(val, 'E', -1, 64) + " overflows " + v.Type().String(),
			}
		}
		v.SetFloat(val)
		return nil
	}
	return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()}
}

func fillByteString(t cborType, val []byte, shared bool, v reflect.Value, bsts ByteStringToStringMode, bum BinaryUnmarshalerMode, tum TextUnmarshalerMode) error {
	if bum == BinaryUnmarshalerByteString && reflect.PointerTo(v.Type()).Implements(typeBinaryUnmarshaler) {
		if v.CanAddr() {
			v = v.Addr()
			if u, ok := v.Interface().(encoding.BinaryUnmarshaler); ok {
				// The contract of BinaryUnmarshaler forbids
				// retaining the input bytes, so no copying is
				// required even if val is shared.
				return u.UnmarshalBinary(val)
			}
		}
		return errors.New("cbor: cannot set new value for " + v.Type().String())
	}
	if bsts != ByteStringToStringForbidden {
		if tum == TextUnmarshalerTextString && reflect.PointerTo(v.Type()).Implements(typeTextUnmarshaler) {
			if v.CanAddr() {
				v = v.Addr()
				if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
					// The contract of TextUnmarshaler forbids retaining the input
					// bytes, so no copying is required even if val is shared.
					if err := u.UnmarshalText(val); err != nil {
						return fmt.Errorf("cbor: cannot unmarshal text for %s: %w", v.Type(), err)
					}
					return nil
				}
			}
			return errors.New("cbor: cannot set new value for " + v.Type().String())
		}

		if v.Kind() == reflect.String {
			v.SetString(string(val))
			return nil
		}
	}
	if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 {
		src := val
		if shared {
			// SetBytes shares the underlying bytes of the source slice.
			src = make([]byte, len(val))
			copy(src, val)
		}
		v.SetBytes(src)
		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 {
			for ; i < vLen; i++ {
				v.Index(i).SetZero()
			}
		}
		return nil
	}
	return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()}
}

func fillTextString(t cborType, val []byte, v reflect.Value, tum TextUnmarshalerMode) error {
	// Check if the value implements TextUnmarshaler and the mode allows it
	if tum == TextUnmarshalerTextString && reflect.PointerTo(v.Type()).Implements(typeTextUnmarshaler) {
		if v.CanAddr() {
			v = v.Addr()
			if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
				// The contract of TextUnmarshaler forbids retaining the input
				// bytes, so no copying is required even if val is shared.
				if err := u.UnmarshalText(val); err != nil {
					return fmt.Errorf("cbor: cannot unmarshal text for %s: %w", v.Type(), err)
				}
				return nil
			}
		}
		return errors.New("cbor: cannot set new value for " + v.Type().String())
	}

	if v.Kind() == reflect.String {
		v.SetString(string(val))
		return nil
	}

	return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()}
}

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 isHashableValue(rv reflect.Value) bool {
	switch rv.Kind() {
	case reflect.Slice, reflect.Map, reflect.Func:
		return false

	case reflect.Struct:
		switch rv.Type() {
		case typeTag:
			tag := rv.Interface().(Tag)
			return isHashableValue(reflect.ValueOf(tag.Content))
		case typeBigInt:
			return false
		}
	}
	return true
}

// convertByteSliceToByteString converts []byte to ByteString if
// - v is []byte type, or
// - v is Tag type and tag content type is []byte
// This function also handles nested tags.
// CBOR data is already verified to be well-formed before this function is used,
// so the recursion won't exceed max nested levels.
func convertByteSliceToByteString(v any) (any, bool) {
	switch v := v.(type) {
	case []byte:
		return ByteString(v), true

	case Tag:
		content, converted := convertByteSliceToByteString(v.Content)
		if converted {
			return Tag{Number: v.Number, Content: content}, true
		}
	}
	return v, false
}
