package tdjson

import (
	
	

	
	

	
)

// Decoder is a simple wrapper around jx.Decoder to conform TL type system.
type Decoder struct {
	*jx.Decoder
}

// Obj calls f for every key in object, using byte slice as key.
//
// The key value is valid only until f is not returned.
func ( Decoder) ( func( Decoder,  []byte) error) error {
	return .Decoder.ObjBytes(func( *jx.Decoder,  []byte) error {
		return (Decoder{Decoder: }, )
	})
}

// Arr decodes array and invokes callback on each array element.
func ( Decoder) ( func( Decoder) error) error {
	return .Decoder.Arr(func( *jx.Decoder) error {
		return (Decoder{Decoder: })
	})
}

// ID deserializes given typeID.
func ( Decoder) () (string, error) {
	return .Decoder.Str()
}

// FindTypeID tries to find @type field or returns error.
func ( Decoder) () (string, error) {
	var (
		 bool
		   string
	)
	if  := .Decoder.Capture(func( *jx.Decoder) error {
		return .ObjBytes(func( *jx.Decoder,  []byte) error {
			if  || string() != TypeField {
				return .Skip()
			}

			,  := .Str()
			if  != nil {
				return 
			}
			 = 
			 = true
			return nil
		})
	});  != nil {
		return "", 
	}
	if ! {
		return "", ErrTypeIDNotFound
	}
	return , nil
}

// ConsumeID deserializes given typeID.
func ( Decoder) ( string) error {
	,  := .Decoder.Str()
	if  != nil {
		return 
	}
	if  !=  {
		return NewUnexpectedID()
	}
	return nil
}

// Int deserializes signed 32-bit integer.
func ( Decoder) () (int, error) {
	return .Decoder.Int()
}

// Bool deserializes boolean.
func ( Decoder) () (bool, error) {
	return .Decoder.Bool()
}

// Uint16 deserializes unsigned 16-bit integer.
func ( Decoder) () (uint16, error) {
	,  := .Decoder.UInt32()
	if  != nil {
		return 0, 
	}
	return uint16(), nil
}

// Int32 deserializes signed 32-bit integer.
func ( Decoder) () (int32, error) {
	return .Decoder.Int32()
}

// Uint32 deserializes unsigned 32-bit integer.
func ( Decoder) () (uint32, error) {
	return .Decoder.UInt32()
}

// Int53 deserializes int53.
func ( Decoder) () (int64, error) {
	return .Decoder.Int64()
}

// Long deserializes int64.
func ( Decoder) () (int64, error) {
	,  := .Decoder.Num()
	if  != nil {
		return 0, 
	}
	return .Int64()
}

// Uint64 deserializes unsigned 64-bit integer.
func ( Decoder) () (uint64, error) {
	return .Decoder.UInt64()
}

// Double deserializes 64-bit floating point.
func ( Decoder) () (float64, error) {
	return .Decoder.Float64()
}

// Int128 deserializes 128-bit signed integer.
func ( Decoder) () (bin.Int128, error) {
	// FIXME(tdakkota): neither TDLib API not Telegram API has no Int128/Int256 fields
	// 	so this encoding may incorrect.
	,  := .Decoder.Str()
	if  != nil {
		return bin.Int128{}, 
	}

	var  bin.Int128
	if  := hex.DecodedLen(len());  != len() {
		return bin.Int128{}, errors.Wrapf(, "invalid length %d", )
	}

	if ,  := hex.Decode([:], []byte());  != nil {
		return bin.Int128{}, 
	}

	return , nil
}

// Int256 deserializes 256-bit signed integer.
func ( Decoder) () (bin.Int256, error) {
	// FIXME(tdakkota): neither TDLib API not Telegram API has no Int128/Int256 fields
	// 	so this encoding may incorrect.
	,  := .Decoder.StrBytes()
	if  != nil {
		return bin.Int256{}, 
	}

	var  bin.Int256
	if  := hex.DecodedLen(len());  != len() {
		return bin.Int256{}, errors.Wrapf(, "invalid length %d", )
	}

	if ,  := hex.Decode([:], );  != nil {
		return bin.Int256{}, 
	}

	return , nil
}

// String deserializes bare string.
func ( Decoder) () (string, error) {
	return .Decoder.Str()
}

// Bytes deserializes bare byte string.
func ( Decoder) () ([]byte, error) {
	// See https://core.telegram.org/tdlib/docs/td__json__client_8h.html
	//
	// ... fields of bytes type are base64 encoded and then stored as String ...
	 := base64.RawStdEncoding

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

	 := make([]byte, .DecodedLen(len()))
	if ,  := .Decode(, );  != nil {
		return nil, 
	}

	return , nil
}