cosmos-sdk/collections/codec/alternative_value.go
testinginprod 309ed1a4bc
feat(collections): add alternative value codec (#16773)
Co-authored-by: unknown unknown <unknown@unknown>
2023-07-04 12:40:20 +00:00

48 lines
2.1 KiB
Go

package codec
// NewAltValueCodec returns a new AltValueCodec. canonicalValueCodec is the codec that you want the value
// to be encoded and decoded as, alternativeDecoder is a function that will attempt to decode the value
// in case the canonicalValueCodec fails to decode it.
func NewAltValueCodec[V any](canonicalValueCodec ValueCodec[V], alternativeDecoder func([]byte) (V, error)) ValueCodec[V] {
return AltValueCodec[V]{
canonicalValueCodec: canonicalValueCodec,
alternativeDecoder: alternativeDecoder,
}
}
// AltValueCodec is a codec that can decode a value from state in an alternative format.
// This is useful for migrating data from one format to another. For example, in x/bank
// balances were initially encoded as sdk.Coin, now they are encoded as math.Int.
// The AltValueCodec will be trying to decode the value as math.Int, and if that fails,
// it will attempt to decode it as sdk.Coin.
// NOTE: if the canonical format can also decode the alternative format, then this codec
// will produce undefined and undesirable behavior.
type AltValueCodec[V any] struct {
canonicalValueCodec ValueCodec[V]
alternativeDecoder func([]byte) (V, error)
}
// Decode will attempt to decode the value from state using the canonical value codec.
// If it fails to decode, it will attempt to decode the value using the alternative decoder.
func (a AltValueCodec[V]) Decode(b []byte) (V, error) {
v, err := a.canonicalValueCodec.Decode(b)
if err != nil {
return a.alternativeDecoder(b)
}
return v, nil
}
// Below there is the implementation of ValueCodec relying on the canonical value codec.
func (a AltValueCodec[V]) Encode(value V) ([]byte, error) { return a.canonicalValueCodec.Encode(value) }
func (a AltValueCodec[V]) EncodeJSON(value V) ([]byte, error) {
return a.canonicalValueCodec.EncodeJSON(value)
}
func (a AltValueCodec[V]) DecodeJSON(b []byte) (V, error) { return a.canonicalValueCodec.DecodeJSON(b) }
func (a AltValueCodec[V]) Stringify(value V) string { return a.canonicalValueCodec.Stringify(value) }
func (a AltValueCodec[V]) ValueType() string { return a.canonicalValueCodec.ValueType() }