Skip to content

Commit 0fd14f9

Browse files
committed
proto: add MessageV1, MessageV2, and MessageReflect
The MessageV1 and MessageV2 functions convert to/from the v1 and v2 message interfaces. The MessageReflect function provides a reflective view over message. These functions do not have an "Of" suffix to be consistent with the existing MessageName and MessageType functions. Furthermore, we drop the "Of" suffix from functions in the descriptor package to be consistent. This is a safe change since none of those functions have seen a stable release. We move the descriptor.GeneratedXXX types to the proto package for documentation purposes. Fixes #956 Change-Id: I566b74367798e2e3399db9902b58ffeb673199ca Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/219137 Reviewed-by: Damien Neil <[email protected]>
1 parent f5a698d commit 0fd14f9

File tree

3 files changed

+69
-31
lines changed

3 files changed

+69
-31
lines changed

descriptor/descriptor.go

+20-20
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ import (
2525
)
2626

2727
// Message is proto.Message with a method to return its descriptor.
28-
// Not every message is guaranteed to implement this interface.
28+
//
29+
// Deprecated: The Descriptor method may not be generated by future
30+
// versions of protoc-gen-go, meaning that this interface may not
31+
// be implemented by many concrete message types.
2932
type Message interface {
3033
proto.Message
3134
Descriptor() ([]byte, []int)
@@ -34,18 +37,15 @@ type Message interface {
3437
// ForMessage returns the file descriptor proto containing
3538
// the message and the message descriptor proto for the message itself.
3639
// The returned proto messages must not be mutated.
40+
//
41+
// Deprecated: Not all concrete message types satisfy the Message interface.
42+
// Use MessageDescriptorProto instead. If possible, the calling code should
43+
// be rewritten to use protobuf reflection instead.
44+
// See package "google.golang.org/protobuf/reflect/protoreflect" for details.
3745
func ForMessage(m Message) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) {
38-
return MessageDescriptorProtoOf(m)
46+
return MessageDescriptorProto(m)
3947
}
4048

41-
// GeneratedEnum is any enum type generated by protoc-gen-go
42-
// which is a named int32 kind.
43-
type GeneratedEnum interface{}
44-
45-
// GeneratedMessage is any message type generated by protoc-gen-go
46-
// which is a pointer to a named struct kind.
47-
type GeneratedMessage interface{}
48-
4949
type rawDesc struct {
5050
fileDesc []byte
5151
indexes []int
@@ -99,21 +99,21 @@ func deriveRawDescriptor(d protoreflect.Descriptor) ([]byte, []int) {
9999
return file, idxs
100100
}
101101

102-
// EnumRawDescriptorOf returns the GZIP'd raw file descriptor containing the
102+
// EnumRawDescriptor returns the GZIP'd raw file descriptor containing the
103103
// enum and the index path to reach the enum declaration.
104104
// The returned slices must not be mutated.
105-
func EnumRawDescriptorOf(e GeneratedEnum) ([]byte, []int) {
105+
func EnumRawDescriptor(e proto.GeneratedEnum) ([]byte, []int) {
106106
if ev, ok := e.(interface{ EnumDescriptor() ([]byte, []int) }); ok {
107107
return ev.EnumDescriptor()
108108
}
109109
ed := protoimpl.X.EnumTypeOf(e)
110110
return deriveRawDescriptor(ed.Descriptor())
111111
}
112112

113-
// MessageRawDescriptorOf returns the GZIP'd raw file descriptor containing
113+
// MessageRawDescriptor returns the GZIP'd raw file descriptor containing
114114
// the message and the index path to reach the message declaration.
115115
// The returned slices must not be mutated.
116-
func MessageRawDescriptorOf(m GeneratedMessage) ([]byte, []int) {
116+
func MessageRawDescriptor(m proto.GeneratedMessage) ([]byte, []int) {
117117
if mv, ok := m.(interface{ Descriptor() ([]byte, []int) }); ok {
118118
return mv.Descriptor()
119119
}
@@ -148,11 +148,11 @@ func deriveFileDescriptor(rawDesc []byte) *descriptorpb.FileDescriptorProto {
148148
return fd
149149
}
150150

151-
// EnumDescriptorProtoOf returns the file descriptor proto containing
151+
// EnumDescriptorProto returns the file descriptor proto containing
152152
// the enum and the enum descriptor proto for the enum itself.
153153
// The returned proto messages must not be mutated.
154-
func EnumDescriptorProtoOf(e GeneratedEnum) (*descriptorpb.FileDescriptorProto, *descriptorpb.EnumDescriptorProto) {
155-
rawDesc, idxs := EnumRawDescriptorOf(e)
154+
func EnumDescriptorProto(e proto.GeneratedEnum) (*descriptorpb.FileDescriptorProto, *descriptorpb.EnumDescriptorProto) {
155+
rawDesc, idxs := EnumRawDescriptor(e)
156156
if rawDesc == nil || idxs == nil {
157157
return nil, nil
158158
}
@@ -168,11 +168,11 @@ func EnumDescriptorProtoOf(e GeneratedEnum) (*descriptorpb.FileDescriptorProto,
168168
return fd, ed
169169
}
170170

171-
// MessageDescriptorProtoOf returns the file descriptor proto containing
171+
// MessageDescriptorProto returns the file descriptor proto containing
172172
// the message and the message descriptor proto for the message itself.
173173
// The returned proto messages must not be mutated.
174-
func MessageDescriptorProtoOf(m GeneratedMessage) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) {
175-
rawDesc, idxs := MessageRawDescriptorOf(m)
174+
func MessageDescriptorProto(m proto.GeneratedMessage) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) {
175+
rawDesc, idxs := MessageRawDescriptor(m)
176176
if rawDesc == nil || idxs == nil {
177177
return nil, nil
178178
}

descriptor/descriptor_test.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
1414
)
1515

16-
func TestEnumDescriptorOf(t *testing.T) {
16+
func TestEnumDescriptor(t *testing.T) {
1717
tests := []struct {
1818
enum protoreflect.Enum
1919
idxs []int
@@ -37,19 +37,19 @@ func TestEnumDescriptorOf(t *testing.T) {
3737
for _, tt := range tests {
3838
e := struct{ protoreflect.Enum }{tt.enum} // v2-only enum
3939

40-
_, idxs := EnumRawDescriptorOf(e)
40+
_, idxs := EnumRawDescriptor(e)
4141
if diff := cmp.Diff(tt.idxs, idxs); diff != "" {
4242
t.Errorf("path index mismatch (-want +got):\n%v", diff)
4343
}
4444

45-
_, ed := EnumDescriptorProtoOf(e)
45+
_, ed := EnumDescriptorProto(e)
4646
if ed.GetName() != tt.name {
4747
t.Errorf("mismatching enum name: got %v, want %v", ed.GetName(), tt.name)
4848
}
4949
}
5050
}
5151

52-
func TestMessageDescriptorOf(t *testing.T) {
52+
func TestMessageDescriptor(t *testing.T) {
5353
tests := []struct {
5454
message protoreflect.ProtoMessage
5555
idxs []int
@@ -72,12 +72,12 @@ func TestMessageDescriptorOf(t *testing.T) {
7272
for _, tt := range tests {
7373
m := struct{ protoreflect.ProtoMessage }{tt.message} // v2-only message
7474

75-
_, idxs := MessageRawDescriptorOf(m)
75+
_, idxs := MessageRawDescriptor(m)
7676
if diff := cmp.Diff(tt.idxs, idxs); diff != "" {
7777
t.Errorf("path index mismatch (-want +got):\n%v", diff)
7878
}
7979

80-
_, md := MessageDescriptorProtoOf(m)
80+
_, md := MessageDescriptorProto(m)
8181
if md.GetName() != tt.name {
8282
t.Errorf("mismatching message name: got %v, want %v", md.GetName(), tt.name)
8383
}

proto/proto.go

+43-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
package proto
1414

1515
import (
16-
"google.golang.org/protobuf/proto"
16+
protoV2 "google.golang.org/protobuf/proto"
1717
"google.golang.org/protobuf/reflect/protoreflect"
1818
"google.golang.org/protobuf/runtime/protoiface"
1919
"google.golang.org/protobuf/runtime/protoimpl"
@@ -26,9 +26,47 @@ const (
2626
ProtoPackageIsVersion4 = true
2727
)
2828

29+
// GeneratedEnum is any enum type generated by protoc-gen-go
30+
// which is a named int32 kind.
31+
// This type exists for documentation purposes.
32+
type GeneratedEnum interface{}
33+
34+
// GeneratedMessage is any message type generated by protoc-gen-go
35+
// which is a pointer to a named struct kind.
36+
// This type exists for documentation purposes.
37+
type GeneratedMessage interface{}
38+
2939
// Message is a protocol buffer message.
40+
//
41+
// This is the v1 version of the message interface and is marginally better
42+
// than an empty interface as it lacks any method to programatically interact
43+
// with the contents of the message.
44+
//
45+
// A v2 message is declared in "google.golang.org/protobuf/proto".Message and
46+
// exposes protobuf reflection as a first-class feature of the interface.
47+
//
48+
// To convert a v1 message to a v2 message, use the MessageV2 function.
49+
// To convert a v2 message to a v1 message, use the MessageV1 function.
3050
type Message = protoiface.MessageV1
3151

52+
// MessageV1 converts either a v1 or v2 message to a v1 message.
53+
// It returns nil if m is nil.
54+
func MessageV1(m GeneratedMessage) protoiface.MessageV1 {
55+
return protoimpl.X.ProtoMessageV1Of(m)
56+
}
57+
58+
// MessageV2 converts either a v1 or v2 message to a v2 message.
59+
// It returns nil if m is nil.
60+
func MessageV2(m GeneratedMessage) protoV2.Message {
61+
return protoimpl.X.ProtoMessageV2Of(m)
62+
}
63+
64+
// MessageReflect returns a reflective view for a message.
65+
// It returns nil if m is nil.
66+
func MessageReflect(m Message) protoreflect.Message {
67+
return protoimpl.X.MessageOf(m)
68+
}
69+
3270
// Marshaler is implemented by messages that can marshal themselves.
3371
// This interface is used by the following functions: Size, Marshal,
3472
// Buffer.Marshal, and Buffer.EncodeMessage.
@@ -80,8 +118,8 @@ func (e *RequiredNotSetError) RequiredNotSet() bool {
80118
return true
81119
}
82120

83-
func checkRequiredNotSet(m proto.Message) error {
84-
if err := proto.IsInitialized(m); err != nil {
121+
func checkRequiredNotSet(m protoV2.Message) error {
122+
if err := protoV2.IsInitialized(m); err != nil {
85123
return &RequiredNotSetError{err: err}
86124
}
87125
return nil
@@ -113,7 +151,7 @@ func Merge(dst, src Message) {
113151
m.Merge(src)
114152
return
115153
}
116-
proto.Merge(
154+
protoV2.Merge(
117155
protoimpl.X.ProtoMessageV2Of(dst),
118156
protoimpl.X.ProtoMessageV2Of(src),
119157
)
@@ -135,7 +173,7 @@ func Merge(dst, src Message) {
135173
// Maps are equal if they have the same set of keys, where the pair of values
136174
// for each key is also equal.
137175
func Equal(x, y Message) bool {
138-
return proto.Equal(
176+
return protoV2.Equal(
139177
protoimpl.X.ProtoMessageV2Of(x),
140178
protoimpl.X.ProtoMessageV2Of(y),
141179
)

0 commit comments

Comments
 (0)