Skip to content

Commit

Permalink
feat: support google.golang.org/protobuf (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronc authored Apr 4, 2024
1 parent e84bfa2 commit 3dec704
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Improvements

- [#119](https://github.com/cosmos/gogoproto/pull/119) The functions `proto.Marshal`, `proto.Unmarshal`, and `proto.MessageName`, as well as the `jsonpb` marshaling and unmarshaling methods now all support official `google.golang.org/protobuf` types. This allows users to gradually start using these types instead of gogo proto without needing to refactor all of their code with type switch statements.

## [v1.4.12](https://github.com/cosmos/gogoproto/releases/tag/v1.4.12) - 2024-03-20

### Improvements
Expand Down
21 changes: 21 additions & 0 deletions jsonpb/jsonpb.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ import (
"strings"
"time"

"google.golang.org/protobuf/encoding/protojson"
protov2 "google.golang.org/protobuf/proto"

"github.com/cosmos/gogoproto/proto"
"github.com/cosmos/gogoproto/types"
)
Expand Down Expand Up @@ -128,6 +131,19 @@ type JSONPBUnmarshaler interface {

// Marshal marshals a protocol buffer into JSON.
func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error {
if msgV2, ok := pb.(protov2.Message); ok {
bz, err := protojson.MarshalOptions{
Indent: m.Indent,
UseProtoNames: m.OrigName,
UseEnumNumbers: m.EnumsAsInts,
EmitUnpopulated: m.EmitDefaults,
}.Marshal(msgV2)
if err != nil {
return err
}
_, err = out.Write(bz)
return err
}
v := reflect.ValueOf(pb)
if pb == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
return errors.New("Marshal called with nil")
Expand Down Expand Up @@ -771,6 +787,11 @@ func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
if err := dec.Decode(&inputValue); err != nil {
return err
}
if msgV2, ok := pb.(protov2.Message); ok {
return protojson.UnmarshalOptions{
AllowPartial: u.AllowUnknownFields,
}.Unmarshal(inputValue, msgV2)
}
if err := u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil); err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions proto/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import (
"errors"
"fmt"
"io"

protov2 "google.golang.org/protobuf/proto"
)

// errOverflow is returned when an integer is too large to be represented.
Expand Down Expand Up @@ -339,6 +341,9 @@ func Unmarshal(buf []byte, pb Message) error {
if u, ok := pb.(Unmarshaler); ok {
return u.Unmarshal(buf)
}
if m, ok := pb.(protov2.Message); ok {
return protov2.Unmarshal(buf, m)
}
return NewBuffer(buf).Unmarshal(pb)
}

Expand Down
3 changes: 3 additions & 0 deletions proto/properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,9 @@ func MessageName(x Message) string {
if m, ok := x.(xname); ok {
return m.XXX_MessageName()
}
if m, ok := x.(protov2.Message); ok {
return string(m.ProtoReflect().Descriptor().FullName())
}
return revProtoTypes[reflect.TypeOf(x)]
}

Expand Down
5 changes: 5 additions & 0 deletions proto/table_marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import (
"sync"
"sync/atomic"
"unicode/utf8"

protov2 "google.golang.org/protobuf/proto"
)

// a sizer takes a pointer to a field and the size of its tag, computes the size of
Expand Down Expand Up @@ -2944,6 +2946,9 @@ func Marshal(pb Message) ([]byte, error) {
// NOTE: This is not efficient.
return m.Marshal()
}
if m, ok := pb.(protov2.Message); ok {
return protov2.MarshalOptions{Deterministic: true}.Marshal(m)
}
// in case somehow we didn't generate the wrapper
if pb == nil {
return nil, ErrNil
Expand Down
44 changes: 44 additions & 0 deletions proto/v2_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package proto_test

import (
"testing"

"github.com/golang/protobuf/jsonpb"

"github.com/cosmos/gogoproto/proto"
descriptorpb "github.com/cosmos/gogoproto/protoc-gen-gogo/descriptor"
)

// This tests for compatibility with google.golang.org types.
func TestV2Support(t *testing.T) {
// Test that we can marshal and unmarshal a timestamp.
fd := &descriptorpb.FieldDescriptorProto{
Name: proto.String("test"),
Number: proto.Int32(1),
}
bz, err := proto.Marshal(fd)
if err != nil {
t.Fatalf("unexpected error marshaling: %v", err)
}

fd2 := &descriptorpb.FieldDescriptorProto{}
if err := proto.Unmarshal(bz, fd2); err != nil {
t.Fatalf("unexpected error unmarshaling: %v", err)
}

// Test json marshaling
str, err := (&jsonpb.Marshaler{}).MarshalToString(fd)
if err != nil {
t.Fatalf("unexpected error marshaling to json: %v", err)
}

fd3 := &descriptorpb.FieldDescriptorProto{}
if err := jsonpb.UnmarshalString(str, fd3); err != nil {
t.Fatalf("unexpected error unmarshaling from json: %v", err)
}

// Test that we get the right message name
if proto.MessageName(fd) != "google.protobuf.FieldDescriptorProto" {
t.Fatalf("unexpected message name: %v", proto.MessageName(fd))
}
}

0 comments on commit 3dec704

Please sign in to comment.