73 lines
1.7 KiB
Go
73 lines
1.7 KiB
Go
package codec
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
func NewStringKeyCodec[T ~string]() NameableKeyCodec[T] { return stringKey[T]{} }
|
|
|
|
const (
|
|
// StringDelimiter defines the delimiter of a string key when used in non-terminal encodings.
|
|
StringDelimiter uint8 = 0x0
|
|
)
|
|
|
|
type stringKey[T ~string] struct{}
|
|
|
|
func (stringKey[T]) Encode(buffer []byte, key T) (int, error) {
|
|
return copy(buffer, key), nil
|
|
}
|
|
|
|
func (stringKey[T]) Decode(buffer []byte) (int, T, error) {
|
|
return len(buffer), T(buffer), nil
|
|
}
|
|
|
|
func (stringKey[T]) EncodeJSON(value T) ([]byte, error) {
|
|
return json.Marshal(value)
|
|
}
|
|
|
|
func (stringKey[T]) DecodeJSON(b []byte) (T, error) {
|
|
var value T
|
|
err := json.Unmarshal(b, &value)
|
|
return value, err
|
|
}
|
|
|
|
func (stringKey[T]) Size(key T) int {
|
|
return len(key)
|
|
}
|
|
|
|
func (stringKey[T]) EncodeNonTerminal(buffer []byte, key T) (int, error) {
|
|
for i := range key {
|
|
c := key[i]
|
|
if c == StringDelimiter {
|
|
return 0, fmt.Errorf("%w: string is not allowed to have the string delimiter (%c) in non terminal encodings of strings", ErrEncoding, StringDelimiter)
|
|
}
|
|
buffer[i] = c
|
|
}
|
|
|
|
return len(key) + 1, nil
|
|
}
|
|
|
|
func (stringKey[T]) DecodeNonTerminal(buffer []byte) (int, T, error) {
|
|
i := bytes.IndexByte(buffer, StringDelimiter)
|
|
if i == -1 {
|
|
return 0, "", fmt.Errorf("%w: not a valid non terminal buffer, no instances of the string delimiter %c found", ErrEncoding, StringDelimiter)
|
|
}
|
|
return i + 1, T(buffer[:i]), nil
|
|
}
|
|
|
|
func (stringKey[T]) SizeNonTerminal(key T) int { return len(key) + 1 }
|
|
|
|
func (stringKey[T]) Stringify(key T) string {
|
|
return (string)(key)
|
|
}
|
|
|
|
func (stringKey[T]) KeyType() string {
|
|
return "string"
|
|
}
|
|
|
|
func (s stringKey[T]) WithName(name string) KeyCodec[T] {
|
|
return NamedKeyCodec[T]{KeyCodec: s, Name: name}
|
|
}
|