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

     1  package codec
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/cosmos/gogoproto/proto"
     8  	gogotypes "github.com/cosmos/gogoproto/types"
     9  	"google.golang.org/protobuf/encoding/protojson"
    10  	protov2 "google.golang.org/protobuf/proto"
    11  
    12  	"cosmossdk.io/collections"
    13  	collcodec "cosmossdk.io/collections/codec"
    14  )
    15  
    16  // BoolValue implements a ValueCodec that saves the bool value
    17  // as if it was a prototypes.BoolValue. Required for backwards
    18  // compatibility of state.
    19  var BoolValue collcodec.ValueCodec[bool] = boolValue{}
    20  
    21  type boolValue struct{}
    22  
    23  func (boolValue) Encode(value bool) ([]byte, error) {
    24  	return (&gogotypes.BoolValue{Value: value}).Marshal()
    25  }
    26  
    27  func (boolValue) Decode(b []byte) (bool, error) {
    28  	v := new(gogotypes.BoolValue)
    29  	err := v.Unmarshal(b)
    30  	return v.Value, err
    31  }
    32  
    33  func (boolValue) EncodeJSON(value bool) ([]byte, error) {
    34  	return collections.BoolValue.EncodeJSON(value)
    35  }
    36  
    37  func (boolValue) DecodeJSON(b []byte) (bool, error) {
    38  	return collections.BoolValue.DecodeJSON(b)
    39  }
    40  
    41  func (boolValue) Stringify(value bool) string {
    42  	return collections.BoolValue.Stringify(value)
    43  }
    44  
    45  func (boolValue) ValueType() string {
    46  	return "protobuf/bool"
    47  }
    48  
    49  type protoMessage[T any] interface {
    50  	*T
    51  	proto.Message
    52  }
    53  
    54  // CollValue inits a collections.ValueCodec for a generic gogo protobuf message.
    55  func CollValue[T any, PT protoMessage[T]](cdc BinaryCodec) collcodec.ValueCodec[T] {
    56  	return &collValue[T, PT]{cdc.(Codec), proto.MessageName(PT(new(T)))}
    57  }
    58  
    59  type collValue[T any, PT protoMessage[T]] struct {
    60  	cdc         Codec
    61  	messageName string
    62  }
    63  
    64  func (c collValue[T, PT]) Encode(value T) ([]byte, error) {
    65  	return c.cdc.Marshal(PT(&value))
    66  }
    67  
    68  func (c collValue[T, PT]) Decode(b []byte) (value T, err error) {
    69  	err = c.cdc.Unmarshal(b, PT(&value))
    70  	return value, err
    71  }
    72  
    73  func (c collValue[T, PT]) EncodeJSON(value T) ([]byte, error) {
    74  	return c.cdc.MarshalJSON(PT(&value))
    75  }
    76  
    77  func (c collValue[T, PT]) DecodeJSON(b []byte) (value T, err error) {
    78  	err = c.cdc.UnmarshalJSON(b, PT(&value))
    79  	return
    80  }
    81  
    82  func (c collValue[T, PT]) Stringify(value T) string {
    83  	return PT(&value).String()
    84  }
    85  
    86  func (c collValue[T, PT]) ValueType() string {
    87  	return "github.com/cosmos/gogoproto/" + c.messageName
    88  }
    89  
    90  type protoMessageV2[T any] interface {
    91  	*T
    92  	protov2.Message
    93  }
    94  
    95  // CollValueV2 is used for protobuf values of the newest google.golang.org/protobuf API.
    96  func CollValueV2[T any, PT protoMessageV2[T]]() collcodec.ValueCodec[PT] {
    97  	return &collValue2[T, PT]{
    98  		messageName: string(PT(new(T)).ProtoReflect().Descriptor().FullName()),
    99  	}
   100  }
   101  
   102  type collValue2[T any, PT protoMessageV2[T]] struct {
   103  	messageName string
   104  }
   105  
   106  func (c collValue2[T, PT]) Encode(value PT) ([]byte, error) {
   107  	protov2MarshalOpts := protov2.MarshalOptions{Deterministic: true}
   108  	return protov2MarshalOpts.Marshal(value)
   109  }
   110  
   111  func (c collValue2[T, PT]) Decode(b []byte) (PT, error) {
   112  	var value T
   113  	err := protov2.Unmarshal(b, PT(&value))
   114  	return &value, err
   115  }
   116  
   117  func (c collValue2[T, PT]) EncodeJSON(value PT) ([]byte, error) {
   118  	return protojson.Marshal(value)
   119  }
   120  
   121  func (c collValue2[T, PT]) DecodeJSON(b []byte) (PT, error) {
   122  	var value T
   123  	err := protojson.Unmarshal(b, PT(&value))
   124  	return &value, err
   125  }
   126  
   127  func (c collValue2[T, PT]) Stringify(value PT) string {
   128  	return fmt.Sprintf("%v", value)
   129  }
   130  
   131  func (c collValue2[T, PT]) ValueType() string {
   132  	return "google.golang.org/protobuf/" + c.messageName
   133  }
   134  
   135  // CollInterfaceValue instantiates a new collections.ValueCodec for a generic
   136  // interface value. The codec must be able to marshal and unmarshal the
   137  // interface.
   138  func CollInterfaceValue[T proto.Message](codec BinaryCodec) collcodec.ValueCodec[T] {
   139  	var x T // assertion
   140  	if reflect.TypeOf(&x).Elem().Kind() != reflect.Interface {
   141  		panic("CollInterfaceValue can only be used with interface types")
   142  	}
   143  	return collInterfaceValue[T]{codec.(Codec)}
   144  }
   145  
   146  type collInterfaceValue[T proto.Message] struct {
   147  	codec Codec
   148  }
   149  
   150  func (c collInterfaceValue[T]) Encode(value T) ([]byte, error) {
   151  	return c.codec.MarshalInterface(value)
   152  }
   153  
   154  func (c collInterfaceValue[T]) Decode(b []byte) (T, error) {
   155  	var value T
   156  	err := c.codec.UnmarshalInterface(b, &value)
   157  	return value, err
   158  }
   159  
   160  func (c collInterfaceValue[T]) EncodeJSON(value T) ([]byte, error) {
   161  	return c.codec.MarshalInterfaceJSON(value)
   162  }
   163  
   164  func (c collInterfaceValue[T]) DecodeJSON(b []byte) (T, error) {
   165  	var value T
   166  	err := c.codec.UnmarshalInterfaceJSON(b, &value)
   167  	return value, err
   168  }
   169  
   170  func (c collInterfaceValue[T]) Stringify(value T) string {
   171  	return value.String()
   172  }
   173  
   174  func (c collInterfaceValue[T]) ValueType() string {
   175  	var t T
   176  	return fmt.Sprintf("%T", t)
   177  }