github.com/Finschia/finschia-sdk@v0.48.1/codec/types/compat.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "reflect" 6 "runtime/debug" 7 8 "github.com/gogo/protobuf/jsonpb" 9 "github.com/gogo/protobuf/proto" 10 11 amino "github.com/tendermint/go-amino" 12 ) 13 14 type anyCompat struct { 15 aminoBz []byte 16 jsonBz []byte 17 err error 18 } 19 20 var Debug = true 21 22 func anyCompatError(errType string, x interface{}) error { 23 if Debug { 24 debug.PrintStack() 25 } 26 return fmt.Errorf( 27 "%s marshaling error for %+v, this is likely because "+ 28 "amino is being used directly (instead of codec.LegacyAmino which is preferred) "+ 29 "or UnpackInterfacesMessage is not defined for some type which contains "+ 30 "a protobuf Any either directly or via one of its members. To see a "+ 31 "stacktrace of where the error is coming from, set the var Debug = true "+ 32 "in codec/types/compat.go", 33 errType, x, 34 ) 35 } 36 37 func (any Any) MarshalAmino() ([]byte, error) { 38 ac := any.compat 39 if ac == nil { 40 return nil, anyCompatError("amino binary marshal", any) 41 } 42 return ac.aminoBz, ac.err 43 } 44 45 func (any *Any) UnmarshalAmino(bz []byte) error { 46 any.compat = &anyCompat{ 47 aminoBz: bz, 48 err: nil, 49 } 50 return nil 51 } 52 53 func (any *Any) MarshalJSON() ([]byte, error) { 54 ac := any.compat 55 if ac == nil { 56 return nil, anyCompatError("JSON marshal", any) 57 } 58 return ac.jsonBz, ac.err 59 } 60 61 func (any *Any) UnmarshalJSON(bz []byte) error { 62 any.compat = &anyCompat{ 63 jsonBz: bz, 64 err: nil, 65 } 66 return nil 67 } 68 69 // AminoUnpacker is an AnyUnpacker provided for backwards compatibility with 70 // amino for the binary un-marshaling phase 71 type AminoUnpacker struct { 72 Cdc *amino.Codec 73 } 74 75 var _ AnyUnpacker = AminoUnpacker{} 76 77 func (a AminoUnpacker) UnpackAny(any *Any, iface interface{}) error { 78 ac := any.compat 79 if ac == nil { 80 return anyCompatError("amino binary unmarshal", reflect.TypeOf(iface)) 81 } 82 err := a.Cdc.UnmarshalBinaryBare(ac.aminoBz, iface) 83 if err != nil { 84 return err 85 } 86 val := reflect.ValueOf(iface).Elem().Interface() 87 err = UnpackInterfaces(val, a) 88 if err != nil { 89 return err 90 } 91 if m, ok := val.(proto.Message); ok { 92 if err = any.pack(m); err != nil { 93 return err 94 } 95 } else { 96 any.cachedValue = val 97 } 98 99 // this is necessary for tests that use reflect.DeepEqual and compare 100 // proto vs amino marshaled values 101 any.compat = nil 102 103 return nil 104 } 105 106 // AminoUnpacker is an AnyUnpacker provided for backwards compatibility with 107 // amino for the binary marshaling phase 108 type AminoPacker struct { 109 Cdc *amino.Codec 110 } 111 112 var _ AnyUnpacker = AminoPacker{} 113 114 func (a AminoPacker) UnpackAny(any *Any, _ interface{}) error { 115 err := UnpackInterfaces(any.cachedValue, a) 116 if err != nil { 117 return err 118 } 119 bz, err := a.Cdc.MarshalBinaryBare(any.cachedValue) 120 any.compat = &anyCompat{ 121 aminoBz: bz, 122 err: err, 123 } 124 return err 125 } 126 127 // AminoUnpacker is an AnyUnpacker provided for backwards compatibility with 128 // amino for the JSON marshaling phase 129 type AminoJSONUnpacker struct { 130 Cdc *amino.Codec 131 } 132 133 var _ AnyUnpacker = AminoJSONUnpacker{} 134 135 func (a AminoJSONUnpacker) UnpackAny(any *Any, iface interface{}) error { 136 ac := any.compat 137 if ac == nil { 138 return anyCompatError("JSON unmarshal", reflect.TypeOf(iface)) 139 } 140 err := a.Cdc.UnmarshalJSON(ac.jsonBz, iface) 141 if err != nil { 142 return err 143 } 144 val := reflect.ValueOf(iface).Elem().Interface() 145 err = UnpackInterfaces(val, a) 146 if err != nil { 147 return err 148 } 149 if m, ok := val.(proto.Message); ok { 150 if err = any.pack(m); err != nil { 151 return err 152 } 153 } else { 154 any.cachedValue = val 155 } 156 157 // this is necessary for tests that use reflect.DeepEqual and compare 158 // proto vs amino marshaled values 159 any.compat = nil 160 161 return nil 162 } 163 164 // AminoUnpacker is an AnyUnpacker provided for backwards compatibility with 165 // amino for the JSON un-marshaling phase 166 type AminoJSONPacker struct { 167 Cdc *amino.Codec 168 } 169 170 var _ AnyUnpacker = AminoJSONPacker{} 171 172 func (a AminoJSONPacker) UnpackAny(any *Any, _ interface{}) error { 173 err := UnpackInterfaces(any.cachedValue, a) 174 if err != nil { 175 return err 176 } 177 bz, err := a.Cdc.MarshalJSON(any.cachedValue) 178 any.compat = &anyCompat{ 179 jsonBz: bz, 180 err: err, 181 } 182 return err 183 } 184 185 // ProtoJSONPacker is an AnyUnpacker provided for compatibility with jsonpb 186 type ProtoJSONPacker struct { 187 JSONPBMarshaler *jsonpb.Marshaler 188 } 189 190 var _ AnyUnpacker = ProtoJSONPacker{} 191 192 func (a ProtoJSONPacker) UnpackAny(any *Any, _ interface{}) error { 193 if any == nil { 194 return nil 195 } 196 197 if any.cachedValue != nil { 198 err := UnpackInterfaces(any.cachedValue, a) 199 if err != nil { 200 return err 201 } 202 } 203 204 bz, err := a.JSONPBMarshaler.MarshalToString(any) 205 any.compat = &anyCompat{ 206 jsonBz: []byte(bz), 207 err: err, 208 } 209 210 return err 211 }