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 }