package msgpack

import (
	
	
	

	
)

type extInfo struct {
	Type    reflect.Type
	Decoder func(d *Decoder, v reflect.Value, extLen int) error
}

var extTypes = make(map[int8]*extInfo)

type MarshalerUnmarshaler interface {
	Marshaler
	Unmarshaler
}

func ( int8,  MarshalerUnmarshaler) {
	RegisterExtEncoder(, , func( *Encoder,  reflect.Value) ([]byte, error) {
		 := .Interface().(Marshaler)
		return .MarshalMsgpack()
	})
	RegisterExtDecoder(, , func( *Decoder,  reflect.Value,  int) error {
		,  := .readN()
		if  != nil {
			return 
		}
		return .Interface().(Unmarshaler).UnmarshalMsgpack()
	})
}

func ( int8) {
	unregisterExtEncoder()
	unregisterExtDecoder()
}

func (
	 int8,
	 interface{},
	 func( *Encoder,  reflect.Value) ([]byte, error),
) {
	unregisterExtEncoder()

	 := reflect.TypeOf()
	 := makeExtEncoder(, , )
	typeEncMap.Store(, )
	typeEncMap.Store(, )
	if .Kind() == reflect.Ptr {
		typeEncMap.Store(.Elem(), makeExtEncoderAddr())
	}
}

func ( int8) {
	,  := typeEncMap.Load()
	if ! {
		return
	}
	typeEncMap.Delete()
	 := .(reflect.Type)
	typeEncMap.Delete()
	if .Kind() == reflect.Ptr {
		typeEncMap.Delete(.Elem())
	}
}

func (
	 int8,
	 reflect.Type,
	 func( *Encoder,  reflect.Value) ([]byte, error),
) encoderFunc {
	 := .Kind() == reflect.Ptr

	return func( *Encoder,  reflect.Value) error {
		if  && .IsNil() {
			return .EncodeNil()
		}

		,  := (, )
		if  != nil {
			return 
		}

		if  := .EncodeExtHeader(, len());  != nil {
			return 
		}

		return .write()
	}
}

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

func (
	 int8,
	 interface{},
	 func( *Decoder,  reflect.Value,  int) error,
) {
	unregisterExtDecoder()

	 := reflect.TypeOf()
	 := makeExtDecoder(, , )
	extTypes[] = &extInfo{
		Type:    ,
		Decoder: ,
	}

	typeDecMap.Store(, )
	typeDecMap.Store(, )
	if .Kind() == reflect.Ptr {
		typeDecMap.Store(.Elem(), makeExtDecoderAddr())
	}
}

func ( int8) {
	,  := typeDecMap.Load()
	if ! {
		return
	}
	typeDecMap.Delete()
	delete(extTypes, )
	 := .(reflect.Type)
	typeDecMap.Delete()
	if .Kind() == reflect.Ptr {
		typeDecMap.Delete(.Elem())
	}
}

func (
	 int8,
	 reflect.Type,
	 func( *Decoder,  reflect.Value,  int) error,
) decoderFunc {
	return nilAwareDecoder(, func( *Decoder,  reflect.Value) error {
		, ,  := .DecodeExtHeader()
		if  != nil {
			return 
		}
		if  !=  {
			return fmt.Errorf("msgpack: got ext type=%d, wanted %d", , )
		}
		return (, , )
	})
}

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

func ( *Encoder) ( int8,  int) error {
	if  := .encodeExtLen();  != nil {
		return 
	}
	if  := .w.WriteByte(byte());  != nil {
		return 
	}
	return nil
}

func ( *Encoder) ( int) error {
	switch  {
	case 1:
		return .writeCode(msgpcode.FixExt1)
	case 2:
		return .writeCode(msgpcode.FixExt2)
	case 4:
		return .writeCode(msgpcode.FixExt4)
	case 8:
		return .writeCode(msgpcode.FixExt8)
	case 16:
		return .writeCode(msgpcode.FixExt16)
	}
	if  <= math.MaxUint8 {
		return .write1(msgpcode.Ext8, uint8())
	}
	if  <= math.MaxUint16 {
		return .write2(msgpcode.Ext16, uint16())
	}
	return .write4(msgpcode.Ext32, uint32())
}

func ( *Decoder) () ( int8,  int,  error) {
	,  := .readCode()
	if  != nil {
		return
	}
	return .extHeader()
}

func ( *Decoder) ( byte) (int8, int, error) {
	,  := .parseExtLen()
	if  != nil {
		return 0, 0, 
	}

	,  := .readCode()
	if  != nil {
		return 0, 0, 
	}

	return int8(), , nil
}

func ( *Decoder) ( byte) (int, error) {
	switch  {
	case msgpcode.FixExt1:
		return 1, nil
	case msgpcode.FixExt2:
		return 2, nil
	case msgpcode.FixExt4:
		return 4, nil
	case msgpcode.FixExt8:
		return 8, nil
	case msgpcode.FixExt16:
		return 16, nil
	case msgpcode.Ext8:
		,  := .uint8()
		return int(), 
	case msgpcode.Ext16:
		,  := .uint16()
		return int(), 
	case msgpcode.Ext32:
		,  := .uint32()
		return int(), 
	default:
		return 0, fmt.Errorf("msgpack: invalid code=%x decoding ext len", )
	}
}

func ( *Decoder) ( byte) (interface{}, error) {
	, ,  := .extHeader()
	if  != nil {
		return nil, 
	}

	,  := extTypes[]
	if ! {
		return nil, fmt.Errorf("msgpack: unknown ext id=%d", )
	}

	 := reflect.New(.Type).Elem()
	if nilable(.Kind()) && .IsNil() {
		.Set(reflect.New(.Type.Elem()))
	}

	if  := .Decoder(, , );  != nil {
		return nil, 
	}

	return .Interface(), nil
}

func ( *Decoder) ( byte) error {
	,  := .parseExtLen()
	if  != nil {
		return 
	}
	return .skipN( + 1)
}

func ( *Decoder) ( byte) error {
	// Read ext type.
	,  := .readCode()
	if  != nil {
		return 
	}
	// Read ext body len.
	for  := 0;  < extHeaderLen(); ++ {
		,  := .readCode()
		if  != nil {
			return 
		}
	}
	return nil
}

func ( byte) int {
	switch  {
	case msgpcode.Ext8:
		return 1
	case msgpcode.Ext16:
		return 2
	case msgpcode.Ext32:
		return 4
	}
	return 0
}