@@ -27,6 +27,49 @@ import (
2727 gogotypes "github.com/gogo/protobuf/types"
2828)
2929
30+ // cosmossdk.io/math/proto.go
31+ // ref: https://github.com/cosmos/gogoproto/blob/master/custom_types.md
32+ type customProtobufType interface {
33+ Marshal () ([]byte , error )
34+ MarshalTo (data []byte ) (n int , err error )
35+ Unmarshal (data []byte ) error
36+ Size () int
37+ }
38+
39+ type GetV [T any ] interface {
40+ customProtobufType
41+ * T
42+ }
43+
44+ func GetValue [m GetV [T ], T any ](store sdk.KVStore , key []byte , errField string ) m {
45+ if bz := store .Get (key ); len (bz ) > 0 {
46+ var c m = new (T )
47+ if err := c .Unmarshal (bz ); err != nil {
48+ panic (fmt .Sprintf ("error unmarshaling %s into %T: %s" , errField , c , err ))
49+ }
50+ return c
51+ }
52+
53+ return nil
54+ }
55+
56+ type SetV [T any ] interface {
57+ customProtobufType
58+ * T
59+ }
60+
61+ func SetValue [s SetV [T ], T any ](store sdk.KVStore , key []byte , value T , errField string ) error {
62+ var c s = & value
63+ bz , err := c .Marshal ()
64+ if err != nil {
65+ return fmt .Errorf ("error while setting %s: %s" , errField , err )
66+ }
67+
68+ store .Set (key , bz )
69+
70+ return nil
71+ }
72+
3073// GetObject gets and unmarshals a structure from KVstore. Panics on failure to decode, and returns a boolean
3174// indicating whether any data was found. If the return is false, the object might not be initialized with
3275// valid zero values for its type.
@@ -56,11 +99,17 @@ func SetObject(store sdk.KVStore, cdc codec.Codec, key []byte, object codec.Prot
5699// It panics if a stored value fails to unmarshal or is negative.
57100// Accepts an additional string which should describe the field being retrieved in custom error messages.
58101func GetInt (store sdk.KVStore , key []byte , errField string ) sdkmath.Int {
59- if bz := store .Get (key ); len (bz ) > 0 {
60- return Int (bz , errField )
102+ val := GetValue [* sdkmath.Int ](store , key , errField )
103+ if val == nil {
104+ // No stored bytes at key: return zero
105+ return sdk .ZeroInt ()
61106 }
62- // No stored bytes at key: return zero
63- return sdk .ZeroInt ()
107+
108+ if val .IsNegative () {
109+ panic (fmt .Sprintf ("%s: retrieved negative %s" , val , errField ))
110+ }
111+
112+ return * val
64113}
65114
66115// SetInt stores an sdkmath.Int in a KVStore, or clears if setting to zero or nil.
@@ -74,23 +123,25 @@ func SetInt(store sdk.KVStore, key []byte, val sdkmath.Int, errField string) err
74123 if val .IsNegative () {
75124 return fmt .Errorf ("%s: cannot set negative %s" , val , errField )
76125 }
77- bz , err := val .Marshal ()
78- if err != nil {
79- return fmt .Errorf ("error while setting %s: %s" , errField , err )
80- }
81- store .Set (key , bz )
82- return nil
126+
127+ return SetValue (store , key , val , errField )
83128}
84129
85130// GetDec retrieves an sdk.Dec from a KVStore, or returns zero if no value is stored.
86131// It panics if a stored value fails to unmarshal or is negative.
87132// Accepts an additional string which should describe the field being retrieved in custom error messages.
88133func GetDec (store sdk.KVStore , key []byte , errField string ) sdk.Dec {
89- if bz := store .Get (key ); len (bz ) > 0 {
90- return Dec (bz , errField )
134+ val := GetValue [* sdk.Dec ](store , key , errField )
135+ if val == nil {
136+ // No stored bytes at key: return zero
137+ return sdk .ZeroDec ()
138+ }
139+
140+ if val .IsNegative () {
141+ panic (fmt .Sprintf ("%s: retrieved negative %s" , val , errField ))
91142 }
92- // No stored bytes at key: return zero
93- return sdk . ZeroDec ()
143+
144+ return * val
94145}
95146
96147// SetDec stores an sdk.Dec in a KVStore, or clears if setting to zero or nil.
@@ -104,23 +155,21 @@ func SetDec(store sdk.KVStore, key []byte, val sdk.Dec, errField string) error {
104155 if val .IsNegative () {
105156 return fmt .Errorf ("%s: cannot set negative %s" , val , errField )
106157 }
107- bz , err := val .Marshal ()
108- if err != nil {
109- return fmt .Errorf ("error while setting %s: %s" , errField , err )
110- }
111- store .Set (key , bz )
112- return nil
158+
159+ return SetValue (store , key , val , errField )
113160}
114161
115162// GetUint32 retrieves a uint32 from a KVStore, or returns zero if no value is stored.
116163// Uses gogoproto Uint32Value for unmarshaling, and panics if a stored value fails to unmarshal.
117164// Accepts an additional string which should describe the field being retrieved in custom error messages.
118165func GetUint32 (store sdk.KVStore , key []byte , errField string ) uint32 {
119- if bz := store .Get (key ); len (bz ) > 0 {
120- return Uint32 (bz , errField )
166+ v := GetValue [* gogotypes.UInt32Value ](store , key , errField )
167+ if v == nil {
168+ // No stored bytes at key: return zero
169+ return 0
121170 }
122- // No stored bytes at key: return zero
123- return 0
171+
172+ return v . Value
124173}
125174
126175// SetUint32 stores a uint32 in a KVStore, or clears if setting to zero.
@@ -130,12 +179,8 @@ func SetUint32(store sdk.KVStore, key []byte, val uint32, errField string) error
130179 if val == 0 {
131180 store .Delete (key )
132181 } else {
133- v := & gogotypes.UInt32Value {Value : val }
134- bz , err := v .Marshal ()
135- if err != nil {
136- return fmt .Errorf ("error while setting %s: %s" , errField , err )
137- }
138- store .Set (key , bz )
182+ v := gogotypes.UInt32Value {Value : val }
183+ return SetValue (store , key , v , errField )
139184 }
140185 return nil
141186}
@@ -144,11 +189,13 @@ func SetUint32(store sdk.KVStore, key []byte, val uint32, errField string) error
144189// Uses gogoproto Uint64Value for unmarshaling, and panics if a stored value fails to unmarshal.
145190// Accepts an additional string which should describe the field being retrieved in custom error messages.
146191func GetUint64 (store sdk.KVStore , key []byte , errField string ) uint64 {
147- if bz := store .Get (key ); len (bz ) > 0 {
148- return Uint64 (bz , errField )
192+ v := GetValue [* gogotypes.UInt64Value ](store , key , errField )
193+ if v == nil {
194+ // No stored bytes at key: return zero
195+ return 0
149196 }
150- // No stored bytes at key: return zero
151- return 0
197+
198+ return v . Value
152199}
153200
154201// SetUint64 stores a uint64 in a KVStore, or clears if setting to zero.
@@ -158,12 +205,8 @@ func SetUint64(store sdk.KVStore, key []byte, val uint64, errField string) error
158205 if val == 0 {
159206 store .Delete (key )
160207 } else {
161- v := & gogotypes.UInt64Value {Value : val }
162- bz , err := v .Marshal ()
163- if err != nil {
164- return fmt .Errorf ("error while setting %s: %s" , errField , err )
165- }
166- store .Set (key , bz )
208+ v := gogotypes.UInt64Value {Value : val }
209+ return SetValue (store , key , v , errField )
167210 }
168211 return nil
169212}
@@ -173,11 +216,13 @@ func SetUint64(store sdk.KVStore, key []byte, val uint64, errField string) error
173216// Accepts an additional string which should describe the field being retrieved in custom error messages.
174217// Allows negative values.
175218func GetInt64 (store sdk.KVStore , key []byte , errField string ) int64 {
176- if bz := store .Get (key ); len (bz ) > 0 {
177- return Int64 (bz , errField )
219+ v := GetValue [* gogotypes.Int64Value ](store , key , errField )
220+ if v == nil {
221+ // No stored bytes at key: return zero
222+ return 0
178223 }
179- // No stored bytes at key: return zero
180- return 0
224+
225+ return v . Value
181226}
182227
183228// SetInt64 stores an int64 in a KVStore, or clears if setting to zero.
@@ -188,12 +233,8 @@ func SetInt64(store sdk.KVStore, key []byte, val int64, errField string) error {
188233 if val == 0 {
189234 store .Delete (key )
190235 } else {
191- v := & gogotypes.Int64Value {Value : val }
192- bz , err := v .Marshal ()
193- if err != nil {
194- return fmt .Errorf ("error while setting %s: %s" , errField , err )
195- }
196- store .Set (key , bz )
236+ v := gogotypes.Int64Value {Value : val }
237+ return SetValue (store , key , v , errField )
197238 }
198239 return nil
199240}
0 commit comments