cosmos-sdk/collections/codec/string.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}
}