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  }