2020-05-05 07:28:20 -07:00
|
|
|
package types
|
|
|
|
|
|
|
|
import (
|
2021-03-12 04:24:07 -08:00
|
|
|
fmt "fmt"
|
|
|
|
|
2020-05-05 07:28:20 -07:00
|
|
|
"github.com/gogo/protobuf/proto"
|
2020-12-02 05:50:50 -08:00
|
|
|
|
|
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
2020-05-05 07:28:20 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
type Any struct {
|
|
|
|
// A URL/resource name that uniquely identifies the type of the serialized
|
|
|
|
// protocol buffer message. This string must contain at least
|
|
|
|
// one "/" character. The last segment of the URL's path must represent
|
|
|
|
// the fully qualified name of the type (as in
|
|
|
|
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
|
|
|
// (e.g., leading "." is not accepted).
|
|
|
|
//
|
|
|
|
// In practice, teams usually precompile into the binary all types that they
|
|
|
|
// expect it to use in the context of Any. However, for URLs which use the
|
|
|
|
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
|
|
|
// server that maps type URLs to message definitions as follows:
|
|
|
|
//
|
|
|
|
// * If no scheme is provided, `https` is assumed.
|
|
|
|
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
|
|
|
// value in binary format, or produce an error.
|
|
|
|
// * Applications are allowed to cache lookup results based on the
|
|
|
|
// URL, or have them precompiled into a binary to avoid any
|
|
|
|
// lookup. Therefore, binary compatibility needs to be preserved
|
|
|
|
// on changes to types. (Use versioned type names to manage
|
|
|
|
// breaking changes.)
|
|
|
|
//
|
|
|
|
// Note: this functionality is not currently available in the official
|
|
|
|
// protobuf release, and it is not used for type URLs beginning with
|
|
|
|
// type.googleapis.com.
|
|
|
|
//
|
|
|
|
// Schemes other than `http`, `https` (or the empty scheme) might be
|
|
|
|
// used with implementation specific semantics.
|
|
|
|
|
|
|
|
// nolint
|
|
|
|
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`
|
|
|
|
// Must be a valid serialized protocol buffer of the above specified type.
|
|
|
|
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
|
|
|
|
|
|
|
// nolint
|
|
|
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
|
|
|
|
|
|
// nolint
|
|
|
|
XXX_unrecognized []byte `json:"-"`
|
|
|
|
|
|
|
|
// nolint
|
|
|
|
XXX_sizecache int32 `json:"-"`
|
|
|
|
|
|
|
|
cachedValue interface{}
|
2020-05-06 13:47:03 -07:00
|
|
|
|
2020-06-05 07:20:41 -07:00
|
|
|
compat *anyCompat
|
2020-05-05 07:28:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewAnyWithValue constructs a new Any packed with the value provided or
|
|
|
|
// returns an error if that value couldn't be packed. This also caches
|
|
|
|
// the packed value so that it can be retrieved from GetCachedValue without
|
|
|
|
// unmarshaling
|
2020-12-18 06:55:25 -08:00
|
|
|
func NewAnyWithValue(v proto.Message) (*Any, error) {
|
|
|
|
if v == nil {
|
|
|
|
return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, "Expecting non nil value to create a new Any")
|
2020-05-05 07:28:20 -07:00
|
|
|
}
|
|
|
|
|
2020-12-14 13:44:15 -08:00
|
|
|
bz, err := proto.Marshal(v)
|
2021-02-17 02:13:00 -08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-04-30 04:00:47 -07:00
|
|
|
|
2020-12-14 13:44:15 -08:00
|
|
|
return &Any{
|
2021-04-30 04:00:47 -07:00
|
|
|
TypeUrl: "/" + proto.MessageName(v),
|
2020-12-14 13:44:15 -08:00
|
|
|
Value: bz,
|
|
|
|
cachedValue: v,
|
2021-02-17 02:13:00 -08:00
|
|
|
}, nil
|
2020-12-14 13:44:15 -08:00
|
|
|
}
|
|
|
|
|
2020-07-17 10:17:21 -07:00
|
|
|
// UnsafePackAny packs the value x in the Any and instead of returning the error
|
|
|
|
// in the case of a packing failure, keeps the cached value. This should only
|
|
|
|
// be used in situations where compatibility is needed with amino. Amino-only
|
|
|
|
// values can safely be packed using this method when they will only be
|
2020-07-18 10:56:41 -07:00
|
|
|
// marshaled with amino and not protobuf.
|
2020-07-17 10:17:21 -07:00
|
|
|
func UnsafePackAny(x interface{}) *Any {
|
|
|
|
if msg, ok := x.(proto.Message); ok {
|
|
|
|
any, err := NewAnyWithValue(msg)
|
2020-09-10 11:26:47 -07:00
|
|
|
if err == nil {
|
2020-07-17 10:17:21 -07:00
|
|
|
return any
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &Any{cachedValue: x}
|
|
|
|
}
|
|
|
|
|
2020-12-18 06:55:25 -08:00
|
|
|
// pack packs the value x in the Any or returns an error. This also caches
|
|
|
|
// the packed value so that it can be retrieved from GetCachedValue without
|
|
|
|
// unmarshaling
|
|
|
|
func (any *Any) pack(x proto.Message) error {
|
|
|
|
any.TypeUrl = "/" + proto.MessageName(x)
|
|
|
|
bz, err := proto.Marshal(x)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2020-10-19 06:04:55 -07:00
|
|
|
}
|
2020-12-18 06:55:25 -08:00
|
|
|
|
|
|
|
any.Value = bz
|
|
|
|
any.cachedValue = x
|
|
|
|
|
|
|
|
return nil
|
2020-10-19 06:04:55 -07:00
|
|
|
}
|
|
|
|
|
2020-05-05 07:28:20 -07:00
|
|
|
// GetCachedValue returns the cached value from the Any if present
|
|
|
|
func (any *Any) GetCachedValue() interface{} {
|
|
|
|
return any.cachedValue
|
|
|
|
}
|
2021-03-12 04:24:07 -08:00
|
|
|
|
|
|
|
// GoString returns a string representing valid go code to reproduce the current state of
|
|
|
|
// the struct.
|
|
|
|
func (any *Any) GoString() string {
|
|
|
|
if any == nil {
|
|
|
|
return "nil"
|
|
|
|
}
|
|
|
|
extra := ""
|
|
|
|
if any.XXX_unrecognized != nil {
|
|
|
|
extra = fmt.Sprintf(",\n XXX_unrecognized: %#v,\n", any.XXX_unrecognized)
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("&Any{TypeUrl: %#v,\n Value: %#v%s\n}",
|
|
|
|
any.TypeUrl, any.Value, extra)
|
|
|
|
}
|
|
|
|
|
|
|
|
// String implements the stringer interface
|
|
|
|
func (any *Any) String() string {
|
|
|
|
if any == nil {
|
|
|
|
return "nil"
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("&Any{TypeUrl:%v,Value:%v,XXX_unrecognized:%v}",
|
|
|
|
any.TypeUrl, any.Value, any.XXX_unrecognized)
|
|
|
|
}
|