163 lines
4.2 KiB
Go
163 lines
4.2 KiB
Go
package codec
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
)
|
|
|
|
func NewUint64Key[T ~uint64]() NameableKeyCodec[T] { return uint64Key[T]{} }
|
|
|
|
type uint64Key[T ~uint64] struct{}
|
|
|
|
func (uint64Key[T]) Encode(buffer []byte, key T) (int, error) {
|
|
binary.BigEndian.PutUint64(buffer, (uint64)(key))
|
|
return 8, nil
|
|
}
|
|
|
|
func (uint64Key[T]) Decode(buffer []byte) (int, T, error) {
|
|
if size := len(buffer); size < 8 {
|
|
return 0, 0, fmt.Errorf("%w: wanted at least 8, got: %d", ErrEncoding, size)
|
|
}
|
|
return 8, (T)(binary.BigEndian.Uint64(buffer)), nil
|
|
}
|
|
|
|
func (uint64Key[T]) EncodeJSON(value T) ([]byte, error) { return uintEncodeJSON((uint64)(value)) }
|
|
|
|
func (uint64Key[T]) DecodeJSON(b []byte) (T, error) {
|
|
u, err := uintDecodeJSON(b, 64)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return (T)(u), nil
|
|
}
|
|
|
|
func (uint64Key[T]) Size(_ T) int { return 8 }
|
|
|
|
func (u uint64Key[T]) EncodeNonTerminal(buffer []byte, key T) (int, error) {
|
|
return u.Encode(buffer, key)
|
|
}
|
|
|
|
func (u uint64Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) {
|
|
return u.Decode(buffer)
|
|
}
|
|
|
|
func (u uint64Key[T]) SizeNonTerminal(key T) int {
|
|
return u.Size(key)
|
|
}
|
|
|
|
func (uint64Key[T]) Stringify(key T) string {
|
|
return strconv.FormatUint((uint64)(key), 10)
|
|
}
|
|
|
|
func (uint64Key[T]) KeyType() string {
|
|
return "uint64"
|
|
}
|
|
|
|
func (u uint64Key[T]) WithName(name string) KeyCodec[T] {
|
|
return NamedKeyCodec[T]{KeyCodec: u, Name: name}
|
|
}
|
|
|
|
func NewUint32Key[T ~uint32]() NameableKeyCodec[T] { return uint32Key[T]{} }
|
|
|
|
type uint32Key[T ~uint32] struct{}
|
|
|
|
func (uint32Key[T]) Encode(buffer []byte, key T) (int, error) {
|
|
binary.BigEndian.PutUint32(buffer, (uint32)(key))
|
|
return 4, nil
|
|
}
|
|
|
|
func (uint32Key[T]) Decode(buffer []byte) (int, T, error) {
|
|
if len(buffer) < 4 {
|
|
return 0, 0, fmt.Errorf("%w: expected buffer of size 4", ErrEncoding)
|
|
}
|
|
return 4, (T)(binary.BigEndian.Uint32(buffer)), nil
|
|
}
|
|
|
|
func (uint32Key[T]) Size(_ T) int { return 4 }
|
|
|
|
func (uint32Key[T]) EncodeJSON(value T) ([]byte, error) { return uintEncodeJSON((uint64)(value)) }
|
|
|
|
func (uint32Key[T]) DecodeJSON(b []byte) (T, error) {
|
|
u, err := uintDecodeJSON(b, 32)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return (T)(u), nil
|
|
}
|
|
|
|
func (uint32Key[T]) Stringify(key T) string { return strconv.FormatUint(uint64(key), 10) }
|
|
|
|
func (uint32Key[T]) KeyType() string { return "uint32" }
|
|
|
|
func (u uint32Key[T]) EncodeNonTerminal(buffer []byte, key T) (int, error) {
|
|
return u.Encode(buffer, key)
|
|
}
|
|
|
|
func (u uint32Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { return u.Decode(buffer) }
|
|
|
|
func (uint32Key[T]) SizeNonTerminal(_ T) int { return 4 }
|
|
|
|
func (u uint32Key[T]) WithName(name string) KeyCodec[T] {
|
|
return NamedKeyCodec[T]{KeyCodec: u, Name: name}
|
|
}
|
|
|
|
func NewUint16Key[T ~uint16]() NameableKeyCodec[T] { return uint16Key[T]{} }
|
|
|
|
type uint16Key[T ~uint16] struct{}
|
|
|
|
func (uint16Key[T]) Encode(buffer []byte, key T) (int, error) {
|
|
binary.BigEndian.PutUint16(buffer, (uint16)(key))
|
|
return 2, nil
|
|
}
|
|
|
|
func (uint16Key[T]) Decode(buffer []byte) (int, T, error) {
|
|
if len(buffer) < 2 {
|
|
return 0, 0, fmt.Errorf("%w: invalid buffer size, wanted at least 2", ErrEncoding)
|
|
}
|
|
return 2, (T)(binary.BigEndian.Uint16(buffer)), nil
|
|
}
|
|
|
|
func (uint16Key[T]) Size(key T) int { return 2 }
|
|
|
|
func (uint16Key[T]) EncodeJSON(value T) ([]byte, error) { return uintEncodeJSON((uint64)(value)) }
|
|
|
|
func (uint16Key[T]) DecodeJSON(b []byte) (T, error) {
|
|
u, err := uintDecodeJSON(b, 16)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return (T)(u), nil
|
|
}
|
|
|
|
func (uint16Key[T]) Stringify(key T) string { return strconv.FormatUint((uint64)(key), 10) }
|
|
|
|
func (uint16Key[T]) KeyType() string { return "uint16" }
|
|
|
|
func (u uint16Key[T]) EncodeNonTerminal(buffer []byte, key T) (int, error) {
|
|
return u.Encode(buffer, key)
|
|
}
|
|
|
|
func (u uint16Key[T]) DecodeNonTerminal(buffer []byte) (int, T, error) { return u.Decode(buffer) }
|
|
|
|
func (u uint16Key[T]) SizeNonTerminal(key T) int { return u.Size(key) }
|
|
|
|
func (u uint16Key[T]) WithName(name string) KeyCodec[T] {
|
|
return NamedKeyCodec[T]{KeyCodec: u, Name: name}
|
|
}
|
|
|
|
func uintEncodeJSON(value uint64) ([]byte, error) {
|
|
str := `"` + strconv.FormatUint(value, 10) + `"`
|
|
return []byte(str), nil
|
|
}
|
|
|
|
func uintDecodeJSON(b []byte, bitSize int) (uint64, error) {
|
|
var str string
|
|
err := json.Unmarshal(b, &str)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return strconv.ParseUint(str, 10, bitSize)
|
|
}
|