package codec import ( "encoding/binary" "encoding/json" "fmt" "strconv" ) func NewInt64Key[T ~int64]() NameableKeyCodec[T] { return int64Key[T]{} } type int64Key[T ~int64] struct{} func (i int64Key[T]) Encode(buffer []byte, key T) (int, error) { binary.BigEndian.PutUint64(buffer, (uint64)(key)) buffer[0] ^= 0x80 return 8, nil } func (i int64Key[T]) Decode(buffer []byte) (int, T, error) { if len(buffer) < 8 { return 0, 0, fmt.Errorf("%w: invalid buffer size, wanted: 8", ErrEncoding) } u := uint64(buffer[7]) | uint64(buffer[6])<<8 | uint64(buffer[5])<<16 | uint64(buffer[4])<<24 | uint64(buffer[3])<<32 | uint64(buffer[2])<<40 | uint64(buffer[1])<<48 | uint64(buffer[0]^0x80)<<56 return 8, (T)(u), nil } func (i int64Key[T]) Size(_ T) int { return 8 } func (i int64Key[T]) EncodeJSON(value T) ([]byte, error) { return []byte(`"` + strconv.FormatInt((int64)(value), 10) + `"`), nil } func (i int64Key[T]) DecodeJSON(b []byte) (T, error) { var s string err := json.Unmarshal(b, &s) if err != nil { return 0, err } k, err := strconv.ParseInt(s, 10, 64) if err != nil { return 0, err } return (T)(k), nil } func (i int64Key[T]) Stringify(key T) string { return strconv.FormatInt((int64)(key), 10) } func (i int64Key[T]) KeyType() string { return "int64" } func (i int64Key[T]) EncodeNonTerminal(buffer []byte, key T) (int, error) { return i.Encode(buffer, key) } func (i int64Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { return i.Decode(buffer) } func (i int64Key[T]) SizeNonTerminal(_ T) int { return 8 } func (i int64Key[T]) WithName(name string) KeyCodec[T] { return NamedKeyCodec[T]{KeyCodec: i, Name: name} } func NewInt32Key[T ~int32]() NameableKeyCodec[T] { return int32Key[T]{} } type int32Key[T ~int32] struct{} func (i int32Key[T]) Encode(buffer []byte, key T) (int, error) { binary.BigEndian.PutUint32(buffer, (uint32)(key)) buffer[0] ^= 0x80 return 4, nil } func (i int32Key[T]) Decode(buffer []byte) (int, T, error) { if len(buffer) < 4 { return 0, 0, fmt.Errorf("%w: invalid buffer size, wanted: 4", ErrEncoding) } u := uint32(buffer[3]) | uint32(buffer[2])<<8 | uint32(buffer[1])<<16 | uint32(buffer[0]^0x80)<<24 return 4, (T)(u), nil } func (i int32Key[T]) Size(_ T) int { return 4 } func (i int32Key[T]) EncodeJSON(value T) ([]byte, error) { return []byte(`"` + strconv.FormatInt((int64)(value), 10) + `"`), nil } func (i int32Key[T]) DecodeJSON(b []byte) (T, error) { var s string err := json.Unmarshal(b, &s) if err != nil { return 0, err } k, err := strconv.ParseInt(s, 10, 32) if err != nil { return 0, err } return (T)(k), nil } func (i int32Key[T]) Stringify(key T) string { return strconv.FormatInt((int64)(key), 10) } func (i int32Key[T]) KeyType() string { return "int32" } func (i int32Key[T]) EncodeNonTerminal(buffer []byte, key T) (int, error) { return i.Encode(buffer, key) } func (i int32Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { return i.Decode(buffer) } func (i int32Key[T]) SizeNonTerminal(_ T) int { return 4 } func (i int32Key[T]) WithName(name string) KeyCodec[T] { return NamedKeyCodec[T]{KeyCodec: i, Name: name} }