types/dynamicpb: add NewEnumType
Add support for creating dynamic EnumTypes.
Change-Id: Ic9f5b73630734848b29cc436f6c179549a8ea74a
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/237219
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Reviewed-by: Joe Tsai <joetsai@google.com>
diff --git a/testing/prototest/enum.go b/testing/prototest/enum.go
new file mode 100644
index 0000000..9ee422e
--- /dev/null
+++ b/testing/prototest/enum.go
@@ -0,0 +1,33 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package prototest
+
+import (
+ "testing"
+
+ pref "google.golang.org/protobuf/reflect/protoreflect"
+)
+
+// Enum tests an EnumType implementation.
+type Enum struct{}
+
+func (test Enum) Test(t testing.TB, et pref.EnumType) {
+ ed := et.Descriptor()
+ values := ed.Values()
+ for i := 0; i < values.Len(); i++ {
+ evd := values.Get(i)
+ num := evd.Number()
+ e := et.New(num)
+ if e.Descriptor() != ed {
+ t.Errorf("enumType.New(%v).Descriptor() != enumType.Descriptor(), should match", num)
+ }
+ if e.Type() != et {
+ t.Errorf("enumType.New(%v).Type() != enumType, should match", num)
+ }
+ if got, want := e.Number(), num; got != want {
+ t.Errorf("enumType.New(%v).Number() = %v, want %v", num, got, want)
+ }
+ }
+}
diff --git a/types/dynamicpb/dynamic.go b/types/dynamicpb/dynamic.go
index 7046ef2..7db6e55 100644
--- a/types/dynamicpb/dynamic.go
+++ b/types/dynamicpb/dynamic.go
@@ -14,6 +14,39 @@
"google.golang.org/protobuf/runtime/protoimpl"
)
+// enum is a dynamic protoreflect.Enum.
+type enum struct {
+ num pref.EnumNumber
+ typ pref.EnumType
+}
+
+func (e enum) Descriptor() pref.EnumDescriptor { return e.typ.Descriptor() }
+func (e enum) Type() pref.EnumType { return e.typ }
+func (e enum) Number() pref.EnumNumber { return e.num }
+
+// enumType is a dynamic protoreflect.EnumType.
+type enumType struct {
+ desc pref.EnumDescriptor
+}
+
+// NewEnumType creates a new EnumType with the provided descriptor.
+//
+// EnumTypes created by this package are equal if their descriptors are equal.
+// That is, if ed1 == ed2, then NewEnumType(ed1) == NewEnumType(ed2).
+//
+// Enum values created by the EnumType are equal if their numbers are equal.
+func NewEnumType(desc pref.EnumDescriptor) pref.EnumType {
+ return enumType{desc}
+}
+
+func (et enumType) New(n pref.EnumNumber) pref.Enum { return enum{n, et} }
+func (et enumType) Descriptor() pref.EnumDescriptor { return et.desc }
+
+// extensionType is a dynamic protoreflect.ExtensionType.
+type extensionType struct {
+ desc extensionTypeDescriptor
+}
+
// A Message is a dynamically constructed protocol buffer message.
//
// Message implements the proto.Message interface, and may be used with all
@@ -577,11 +610,6 @@
panic(errors.New("%v: unknown kind %v", fd.FullName(), fd.Kind()))
}
-// extensionType is a dynamic protoreflect.ExtensionType.
-type extensionType struct {
- desc extensionTypeDescriptor
-}
-
// NewExtensionType creates a new ExtensionType with the provided descriptor.
//
// Dynamic ExtensionTypes with the same descriptor compare as equal. That is,
diff --git a/types/dynamicpb/dynamic_test.go b/types/dynamicpb/dynamic_test.go
index 78e93bb..6835d3e 100644
--- a/types/dynamicpb/dynamic_test.go
+++ b/types/dynamicpb/dynamic_test.go
@@ -39,6 +39,16 @@
}
}
+func TestDynamicEnums(t *testing.T) {
+ for _, enum := range []pref.Enum{
+ testpb.TestAllTypes_FOO,
+ test3pb.TestAllTypes_FOO,
+ } {
+ et := dynamicpb.NewEnumType(enum.Descriptor())
+ prototest.Enum{}.Test(t, et)
+ }
+}
+
type extResolver struct{}
func (extResolver) FindExtensionByName(field pref.FullName) (pref.ExtensionType, error) {