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  }