github.com/cosmos/cosmos-sdk@v0.50.10/types/collections.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"cosmossdk.io/collections"
     8  	collcodec "cosmossdk.io/collections/codec"
     9  	"cosmossdk.io/math"
    10  )
    11  
    12  var (
    13  	// AccAddressKey follows the same semantics of collections.BytesKey.
    14  	// It just uses humanized format for the String() and EncodeJSON().
    15  	AccAddressKey collcodec.KeyCodec[AccAddress] = genericAddressKey[AccAddress]{
    16  		stringDecoder: AccAddressFromBech32,
    17  		keyType:       "sdk.AccAddress",
    18  	}
    19  
    20  	// ValAddressKey follows the same semantics as AccAddressKey.
    21  	ValAddressKey collcodec.KeyCodec[ValAddress] = genericAddressKey[ValAddress]{
    22  		stringDecoder: ValAddressFromBech32,
    23  		keyType:       "sdk.ValAddress",
    24  	}
    25  
    26  	// ConsAddressKey follows the same semantics as ConsAddressKey.
    27  	ConsAddressKey collcodec.KeyCodec[ConsAddress] = genericAddressKey[ConsAddress]{
    28  		stringDecoder: ConsAddressFromBech32,
    29  		keyType:       "sdk.ConsAddress",
    30  	}
    31  
    32  	// IntValue represents a collections.ValueCodec to work with Int.
    33  	IntValue collcodec.ValueCodec[math.Int] = intValueCodec{}
    34  
    35  	// LegacyDecValue represents a collections.ValueCodec to work with LegacyDec.
    36  	LegacyDecValue collcodec.ValueCodec[math.LegacyDec] = legacyDecValueCodec{}
    37  
    38  	// TimeKey represents a collections.KeyCodec to work with time.Time
    39  	// Deprecated: exists only for state compatibility reasons, should not
    40  	// be used for new storage keys using time. Please use the time KeyCodec
    41  	// provided in the collections package.
    42  	TimeKey collcodec.KeyCodec[time.Time] = timeKeyCodec{}
    43  )
    44  
    45  const (
    46  	LegacyDec string = "math.LegacyDec"
    47  )
    48  
    49  type addressUnion interface {
    50  	AccAddress | ValAddress | ConsAddress
    51  	String() string
    52  }
    53  
    54  type genericAddressKey[T addressUnion] struct {
    55  	stringDecoder func(string) (T, error)
    56  	keyType       string
    57  }
    58  
    59  func (a genericAddressKey[T]) Encode(buffer []byte, key T) (int, error) {
    60  	return collections.BytesKey.Encode(buffer, key)
    61  }
    62  
    63  func (a genericAddressKey[T]) Decode(buffer []byte) (int, T, error) {
    64  	return collections.BytesKey.Decode(buffer)
    65  }
    66  
    67  func (a genericAddressKey[T]) Size(key T) int {
    68  	return collections.BytesKey.Size(key)
    69  }
    70  
    71  func (a genericAddressKey[T]) EncodeJSON(value T) ([]byte, error) {
    72  	return collections.StringKey.EncodeJSON(value.String())
    73  }
    74  
    75  func (a genericAddressKey[T]) DecodeJSON(b []byte) (v T, err error) {
    76  	s, err := collections.StringKey.DecodeJSON(b)
    77  	if err != nil {
    78  		return
    79  	}
    80  	v, err = a.stringDecoder(s)
    81  	return
    82  }
    83  
    84  func (a genericAddressKey[T]) Stringify(key T) string {
    85  	return key.String()
    86  }
    87  
    88  func (a genericAddressKey[T]) KeyType() string {
    89  	return a.keyType
    90  }
    91  
    92  func (a genericAddressKey[T]) EncodeNonTerminal(buffer []byte, key T) (int, error) {
    93  	return collections.BytesKey.EncodeNonTerminal(buffer, key)
    94  }
    95  
    96  func (a genericAddressKey[T]) DecodeNonTerminal(buffer []byte) (int, T, error) {
    97  	return collections.BytesKey.DecodeNonTerminal(buffer)
    98  }
    99  
   100  func (a genericAddressKey[T]) SizeNonTerminal(key T) int {
   101  	return collections.BytesKey.SizeNonTerminal(key)
   102  }
   103  
   104  // Deprecated: lengthPrefixedAddressKey is a special key codec used to retain state backwards compatibility
   105  // when a generic address key (be: AccAddress, ValAddress, ConsAddress), is used as an index key.
   106  // More docs can be found in the LengthPrefixedAddressKey function.
   107  type lengthPrefixedAddressKey[T addressUnion] struct {
   108  	collcodec.KeyCodec[T]
   109  }
   110  
   111  func (g lengthPrefixedAddressKey[T]) Encode(buffer []byte, key T) (int, error) {
   112  	return g.EncodeNonTerminal(buffer, key)
   113  }
   114  
   115  func (g lengthPrefixedAddressKey[T]) Decode(buffer []byte) (int, T, error) {
   116  	return g.DecodeNonTerminal(buffer)
   117  }
   118  
   119  func (g lengthPrefixedAddressKey[T]) Size(key T) int { return g.SizeNonTerminal(key) }
   120  
   121  func (g lengthPrefixedAddressKey[T]) KeyType() string { return "index_key/" + g.KeyCodec.KeyType() }
   122  
   123  // Deprecated: LengthPrefixedAddressKey implements an SDK backwards compatible indexing key encoder
   124  // for addresses.
   125  // The status quo in the SDK is that address keys are length prefixed even when they're the
   126  // last part of a composite key. This should never be used unless to retain state compatibility.
   127  // For example, a composite key composed of `[string, address]` in theory would need you only to
   128  // define a way to understand when the string part finishes, we usually do this by appending a null
   129  // byte to the string, then when you know when the string part finishes, it's logical that the
   130  // part which remains is the address key. In the SDK instead we prepend to the address key its
   131  // length too.
   132  func LengthPrefixedAddressKey[T addressUnion](keyCodec collcodec.KeyCodec[T]) collcodec.KeyCodec[T] {
   133  	return lengthPrefixedAddressKey[T]{
   134  		keyCodec,
   135  	}
   136  }
   137  
   138  // Collection Codecs
   139  
   140  type intValueCodec struct{}
   141  
   142  func (i intValueCodec) Encode(value math.Int) ([]byte, error) {
   143  	return value.Marshal()
   144  }
   145  
   146  func (i intValueCodec) Decode(b []byte) (math.Int, error) {
   147  	v := new(math.Int)
   148  	err := v.Unmarshal(b)
   149  	if err != nil {
   150  		return math.Int{}, err
   151  	}
   152  	return *v, nil
   153  }
   154  
   155  func (i intValueCodec) EncodeJSON(value math.Int) ([]byte, error) {
   156  	return value.MarshalJSON()
   157  }
   158  
   159  func (i intValueCodec) DecodeJSON(b []byte) (math.Int, error) {
   160  	v := new(math.Int)
   161  	err := v.UnmarshalJSON(b)
   162  	if err != nil {
   163  		return math.Int{}, err
   164  	}
   165  	return *v, nil
   166  }
   167  
   168  func (i intValueCodec) Stringify(value math.Int) string {
   169  	return value.String()
   170  }
   171  
   172  func (i intValueCodec) ValueType() string {
   173  	return "math.Int"
   174  }
   175  
   176  type legacyDecValueCodec struct{}
   177  
   178  func (i legacyDecValueCodec) Encode(value math.LegacyDec) ([]byte, error) {
   179  	return value.Marshal()
   180  }
   181  
   182  func (i legacyDecValueCodec) Decode(b []byte) (math.LegacyDec, error) {
   183  	v := new(math.LegacyDec)
   184  	err := v.Unmarshal(b)
   185  	if err != nil {
   186  		return math.LegacyDec{}, err
   187  	}
   188  	return *v, nil
   189  }
   190  
   191  func (i legacyDecValueCodec) EncodeJSON(value math.LegacyDec) ([]byte, error) {
   192  	return value.MarshalJSON()
   193  }
   194  
   195  func (i legacyDecValueCodec) DecodeJSON(b []byte) (math.LegacyDec, error) {
   196  	v := new(math.LegacyDec)
   197  	err := v.UnmarshalJSON(b)
   198  	if err != nil {
   199  		return math.LegacyDec{}, err
   200  	}
   201  	return *v, nil
   202  }
   203  
   204  func (i legacyDecValueCodec) Stringify(value math.LegacyDec) string {
   205  	return value.String()
   206  }
   207  
   208  func (i legacyDecValueCodec) ValueType() string {
   209  	return LegacyDec
   210  }
   211  
   212  type timeKeyCodec struct{}
   213  
   214  func (timeKeyCodec) Encode(buffer []byte, key time.Time) (int, error) {
   215  	return copy(buffer, FormatTimeBytes(key)), nil
   216  }
   217  
   218  var timeSize = len(FormatTimeBytes(time.Time{}))
   219  
   220  func (timeKeyCodec) Decode(buffer []byte) (int, time.Time, error) {
   221  	if len(buffer) != timeSize {
   222  		return 0, time.Time{}, fmt.Errorf("invalid time buffer buffer size")
   223  	}
   224  	t, err := ParseTimeBytes(buffer)
   225  	if err != nil {
   226  		return 0, time.Time{}, err
   227  	}
   228  	return timeSize, t, nil
   229  }
   230  
   231  func (timeKeyCodec) Size(key time.Time) int { return timeSize }
   232  
   233  func (timeKeyCodec) EncodeJSON(value time.Time) ([]byte, error) { return value.MarshalJSON() }
   234  
   235  func (timeKeyCodec) DecodeJSON(b []byte) (time.Time, error) {
   236  	t := time.Time{}
   237  	err := t.UnmarshalJSON(b)
   238  	return t, err
   239  }
   240  
   241  func (timeKeyCodec) Stringify(key time.Time) string { return key.String() }
   242  func (timeKeyCodec) KeyType() string                { return "sdk/time.Time" }
   243  func (t timeKeyCodec) EncodeNonTerminal(buffer []byte, key time.Time) (int, error) {
   244  	return t.Encode(buffer, key)
   245  }
   246  
   247  func (t timeKeyCodec) DecodeNonTerminal(buffer []byte) (int, time.Time, error) {
   248  	if len(buffer) < timeSize {
   249  		return 0, time.Time{}, fmt.Errorf("invalid time buffer size, wanted: %d at least, got: %d", timeSize, len(buffer))
   250  	}
   251  	return t.Decode(buffer[:timeSize])
   252  }
   253  func (t timeKeyCodec) SizeNonTerminal(key time.Time) int { return t.Size(key) }