package msgpack

import (
	
	
	
	
)

var (
	interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
	stringType    = reflect.TypeOf((*string)(nil)).Elem()
)

var valueDecoders []decoderFunc

//nolint:gochecknoinits
func () {
	valueDecoders = []decoderFunc{
		reflect.Bool:          decodeBoolValue,
		reflect.Int:           decodeInt64Value,
		reflect.Int8:          decodeInt64Value,
		reflect.Int16:         decodeInt64Value,
		reflect.Int32:         decodeInt64Value,
		reflect.Int64:         decodeInt64Value,
		reflect.Uint:          decodeUint64Value,
		reflect.Uint8:         decodeUint64Value,
		reflect.Uint16:        decodeUint64Value,
		reflect.Uint32:        decodeUint64Value,
		reflect.Uint64:        decodeUint64Value,
		reflect.Float32:       decodeFloat32Value,
		reflect.Float64:       decodeFloat64Value,
		reflect.Complex64:     decodeUnsupportedValue,
		reflect.Complex128:    decodeUnsupportedValue,
		reflect.Array:         decodeArrayValue,
		reflect.Chan:          decodeUnsupportedValue,
		reflect.Func:          decodeUnsupportedValue,
		reflect.Interface:     decodeInterfaceValue,
		reflect.Map:           decodeMapValue,
		reflect.Ptr:           decodeUnsupportedValue,
		reflect.Slice:         decodeSliceValue,
		reflect.String:        decodeStringValue,
		reflect.Struct:        decodeStructValue,
		reflect.UnsafePointer: decodeUnsupportedValue,
	}
}

func ( reflect.Type) decoderFunc {
	if ,  := typeDecMap.Load();  {
		return .(decoderFunc)
	}
	 := _getDecoder()
	typeDecMap.Store(, )
	return 
}

func ( reflect.Type) decoderFunc {
	 := .Kind()

	if  == reflect.Ptr {
		if ,  := typeDecMap.Load(.Elem());  {
			return ptrValueDecoder()
		}
	}

	if .Implements(customDecoderType) {
		return nilAwareDecoder(, decodeCustomValue)
	}
	if .Implements(unmarshalerType) {
		return nilAwareDecoder(, unmarshalValue)
	}
	if .Implements(binaryUnmarshalerType) {
		return nilAwareDecoder(, unmarshalBinaryValue)
	}
	if .Implements(textUnmarshalerType) {
		return nilAwareDecoder(, unmarshalTextValue)
	}

	// Addressable struct field value.
	if  != reflect.Ptr {
		 := reflect.PtrTo()
		if .Implements(customDecoderType) {
			return addrDecoder(nilAwareDecoder(, decodeCustomValue))
		}
		if .Implements(unmarshalerType) {
			return addrDecoder(nilAwareDecoder(, unmarshalValue))
		}
		if .Implements(binaryUnmarshalerType) {
			return addrDecoder(nilAwareDecoder(, unmarshalBinaryValue))
		}
		if .Implements(textUnmarshalerType) {
			return addrDecoder(nilAwareDecoder(, unmarshalTextValue))
		}
	}

	switch  {
	case reflect.Ptr:
		return ptrValueDecoder()
	case reflect.Slice:
		 := .Elem()
		if .Kind() == reflect.Uint8 {
			return decodeBytesValue
		}
		if  == stringType {
			return decodeStringSliceValue
		}
	case reflect.Array:
		if .Elem().Kind() == reflect.Uint8 {
			return decodeByteArrayValue
		}
	case reflect.Map:
		if .Key() == stringType {
			switch .Elem() {
			case stringType:
				return decodeMapStringStringValue
			case interfaceType:
				return decodeMapStringInterfaceValue
			}
		}
	}

	return valueDecoders[]
}

func ( reflect.Type) decoderFunc {
	 := getDecoder(.Elem())
	return func( *Decoder,  reflect.Value) error {
		if .hasNilCode() {
			if !.IsNil() {
				.Set(reflect.Zero(.Type()))
			}
			return .DecodeNil()
		}
		if .IsNil() {
			.Set(reflect.New(.Type().Elem()))
		}
		return (, .Elem())
	}
}

func ( decoderFunc) decoderFunc {
	return func( *Decoder,  reflect.Value) error {
		if !.CanAddr() {
			return fmt.Errorf("msgpack: Decode(nonaddressable %T)", .Interface())
		}
		return (, .Addr())
	}
}

func ( reflect.Type,  decoderFunc) decoderFunc {
	if nilable(.Kind()) {
		return func( *Decoder,  reflect.Value) error {
			if .hasNilCode() {
				return .decodeNilValue()
			}
			if .IsNil() {
				.Set(reflect.New(.Type().Elem()))
			}
			return (, )
		}
	}

	return func( *Decoder,  reflect.Value) error {
		if .hasNilCode() {
			return .decodeNilValue()
		}
		return (, )
	}
}

func ( *Decoder,  reflect.Value) error {
	,  := .DecodeBool()
	if  != nil {
		return 
	}
	.SetBool()
	return nil
}

func ( *Decoder,  reflect.Value) error {
	if .IsNil() {
		return .interfaceValue()
	}
	return .DecodeValue(.Elem())
}

func ( *Decoder) ( reflect.Value) error {
	,  := .decodeInterfaceCond()
	if  != nil {
		return 
	}

	if  != nil {
		if .Type() == errorType {
			if ,  := .(string);  {
				.Set(reflect.ValueOf(errors.New()))
				return nil
			}
		}

		.Set(reflect.ValueOf())
	}

	return nil
}

func ( *Decoder,  reflect.Value) error {
	return fmt.Errorf("msgpack: Decode(unsupported %s)", .Type())
}

//------------------------------------------------------------------------------

func ( *Decoder,  reflect.Value) error {
	 := .Interface().(CustomDecoder)
	return .DecodeMsgpack()
}

func ( *Decoder,  reflect.Value) error {
	var  []byte

	.rec = make([]byte, 0, 64)
	if  := .Skip();  != nil {
		return 
	}
	 = .rec
	.rec = nil

	 := .Interface().(Unmarshaler)
	return .UnmarshalMsgpack()
}

func ( *Decoder,  reflect.Value) error {
	,  := .DecodeBytes()
	if  != nil {
		return 
	}

	 := .Interface().(encoding.BinaryUnmarshaler)
	return .UnmarshalBinary()
}

func ( *Decoder,  reflect.Value) error {
	,  := .DecodeBytes()
	if  != nil {
		return 
	}

	 := .Interface().(encoding.TextUnmarshaler)
	return .UnmarshalText()
}