github.com/Finschia/finschia-sdk@v0.48.1/codec/types/any.go (about) 1 package types 2 3 import ( 4 fmt "fmt" 5 6 "github.com/gogo/protobuf/proto" 7 8 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 9 ) 10 11 //nolint:golint 12 type Any struct { 13 // A URL/resource name that uniquely identifies the type of the serialized 14 // protocol buffer message. This string must contain at least 15 // one "/" character. The last segment of the URL's path must represent 16 // the fully qualified name of the type (as in 17 // `path/google.protobuf.Duration`). The name should be in a canonical form 18 // (e.g., leading "." is not accepted). 19 // 20 // In practice, teams usually precompile into the binary all types that they 21 // expect it to use in the context of Any. However, for URLs which use the 22 // scheme `http`, `https`, or no scheme, one can optionally set up a type 23 // server that maps type URLs to message definitions as follows: 24 // 25 // * If no scheme is provided, `https` is assumed. 26 // * An HTTP GET on the URL must yield a [google.protobuf.Type][] 27 // value in binary format, or produce an error. 28 // * Applications are allowed to cache lookup results based on the 29 // URL, or have them precompiled into a binary to avoid any 30 // lookup. Therefore, binary compatibility needs to be preserved 31 // on changes to types. (Use versioned type names to manage 32 // breaking changes.) 33 // 34 // Note: this functionality is not currently available in the official 35 // protobuf release, and it is not used for type URLs beginning with 36 // type.googleapis.com. 37 // 38 // Schemes other than `http`, `https` (or the empty scheme) might be 39 // used with implementation specific semantics. 40 41 TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` 42 // Must be a valid serialized protocol buffer of the above specified type. 43 Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` 44 45 // If you change XXX_ to XXX, an error occurs in the part referring to google/protobuf/any.proto, so add the nolint flag. 46 XXX_NoUnkeyedLiteral struct{} `json:"-"` 47 XXX_unrecognized []byte `json:"-"` 48 XXX_sizecache int32 `json:"-"` 49 50 cachedValue interface{} 51 52 compat *anyCompat 53 } 54 55 // NewAnyWithValue constructs a new Any packed with the value provided or 56 // returns an error if that value couldn't be packed. This also caches 57 // the packed value so that it can be retrieved from GetCachedValue without 58 // unmarshaling 59 func NewAnyWithValue(v proto.Message) (*Any, error) { 60 if v == nil { 61 return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, "Expecting non nil value to create a new Any") 62 } 63 64 bz, err := proto.Marshal(v) 65 if err != nil { 66 return nil, err 67 } 68 69 return &Any{ 70 TypeUrl: "/" + proto.MessageName(v), 71 Value: bz, 72 cachedValue: v, 73 }, nil 74 } 75 76 // UnsafePackAny packs the value x in the Any and instead of returning the error 77 // in the case of a packing failure, keeps the cached value. This should only 78 // be used in situations where compatibility is needed with amino. Amino-only 79 // values can safely be packed using this method when they will only be 80 // marshaled with amino and not protobuf. 81 func UnsafePackAny(x interface{}) *Any { 82 if msg, ok := x.(proto.Message); ok { 83 any, err := NewAnyWithValue(msg) 84 if err == nil { 85 return any 86 } 87 } 88 return &Any{cachedValue: x} 89 } 90 91 // pack packs the value x in the Any or returns an error. This also caches 92 // the packed value so that it can be retrieved from GetCachedValue without 93 // unmarshaling 94 func (any *Any) pack(x proto.Message) error { 95 any.TypeUrl = "/" + proto.MessageName(x) 96 bz, err := proto.Marshal(x) 97 if err != nil { 98 return err 99 } 100 101 any.Value = bz 102 any.cachedValue = x 103 104 return nil 105 } 106 107 // GetCachedValue returns the cached value from the Any if present 108 func (any *Any) GetCachedValue() interface{} { 109 return any.cachedValue 110 } 111 112 // GoString returns a string representing valid go code to reproduce the current state of 113 // the struct. 114 func (any *Any) GoString() string { 115 if any == nil { 116 return "nil" 117 } 118 extra := "" 119 if any.XXX_unrecognized != nil { 120 extra = fmt.Sprintf(",\n XXX_unrecognized: %#v,\n", any.XXX_unrecognized) 121 } 122 return fmt.Sprintf("&Any{TypeUrl: %#v,\n Value: %#v%s\n}", 123 any.TypeUrl, any.Value, extra) 124 } 125 126 // String implements the stringer interface 127 func (any *Any) String() string { 128 if any == nil { 129 return "nil" 130 } 131 return fmt.Sprintf("&Any{TypeUrl:%v,Value:%v,XXX_unrecognized:%v}", 132 any.TypeUrl, any.Value, any.XXX_unrecognized) 133 }