mirror of https://github.com/certusone/wasmd.git
80 lines
2.4 KiB
Go
80 lines
2.4 KiB
Go
package codec
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
|
"github.com/gogo/protobuf/jsonpb"
|
|
"github.com/gogo/protobuf/proto"
|
|
)
|
|
|
|
var _ codec.Codec = (*ProtoCodec)(nil)
|
|
|
|
// ProtoCodec that omits empty values.
|
|
// This Marshaler can be used globally when setting up the client context or individually
|
|
// for each command via `clientCtx.WithJSONMarshaler(myMarshaler)`.
|
|
type ProtoCodec struct {
|
|
codec.Codec
|
|
interfaceRegistry types.InterfaceRegistry
|
|
}
|
|
|
|
func NewProtoCodec(marshaler codec.Codec, registry types.InterfaceRegistry) *ProtoCodec {
|
|
return &ProtoCodec{Codec: marshaler, interfaceRegistry: registry}
|
|
}
|
|
|
|
// MarshalJSON implements JSONMarshaler.MarshalJSON method,
|
|
// it marshals to JSON using proto codec.
|
|
func (pc *ProtoCodec) MarshalJSON(o proto.Message) ([]byte, error) {
|
|
m, ok := o.(codec.ProtoMarshaler)
|
|
if !ok {
|
|
return nil, fmt.Errorf("cannot protobuf JSON encode unsupported type: %T", o)
|
|
}
|
|
return ProtoMarshalJSON(m, pc.interfaceRegistry)
|
|
}
|
|
|
|
// MustMarshalJSON implements JSONMarshaler.MustMarshalJSON method,
|
|
// it executes MarshalJSON except it panics upon failure.
|
|
func (pc *ProtoCodec) MustMarshalJSON(o proto.Message) []byte {
|
|
bz, err := pc.MarshalJSON(o)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return bz
|
|
}
|
|
|
|
// MarshalInterfaceJSON is a convenience function for proto marshalling interfaces. It
|
|
// packs the provided value in an Any and then marshals it to bytes.
|
|
// NOTE: to marshal a concrete type, you should use MarshalJSON instead
|
|
func (pc *ProtoCodec) MarshalInterfaceJSON(x proto.Message) ([]byte, error) {
|
|
any, err := types.NewAnyWithValue(x)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return pc.MarshalJSON(any)
|
|
}
|
|
|
|
// ProtoMarshalJSON provides an auxiliary function to return Proto3 JSON encoded
|
|
// bytes of a message.
|
|
func ProtoMarshalJSON(msg proto.Message, resolver jsonpb.AnyResolver) ([]byte, error) {
|
|
// method copied from sdk codec/json.go with EmitDefaults set to `false`
|
|
// so that empty fields are not rendered
|
|
|
|
// We use the OrigName because camel casing fields just doesn't make sense.
|
|
// EmitDefaults is also often the more expected behavior for CLI users
|
|
jm := &jsonpb.Marshaler{OrigName: true, EmitDefaults: false, AnyResolver: resolver}
|
|
err := types.UnpackInterfaces(msg, types.ProtoJSONPacker{JSONPBMarshaler: jm})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
if err := jm.Marshal(buf, msg); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|