internal/value: expose Converter.{MessageType,EnumType}
Rather than having the Converter carry a NewMessage method, have the struct
simply expose the MessageType or EnumType since they carry more information
and are retrieved anyways as part of the functionality of NewConverter.
While changing Converter, export the fields and remove all the methods.
Also, add an IsLegacy boolean, which is useful for the later implementation
of the extension fields.
Add a wrapLegacyEnum function which is used to wrap v1 enums as v2 enums.
We use this functionality in NewLegacyConverter to detrive the EnumType.
Additionally, modify wrapLegacyMessage to return a protoreflect.ProtoMessage
to be consistent with wrapLegacyEnum which must return a protoreflect.ProtoEnum.
Change-Id: Idc8989d07e4895d30de4ebc22c9ffa7357815cad
Reviewed-on: https://go-review.googlesource.com/c/148827
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/internal/impl/legacy_message.go b/internal/impl/legacy_message.go
index 66a71c6..3c43bfa 100644
--- a/internal/impl/legacy_message.go
+++ b/internal/impl/legacy_message.go
@@ -14,26 +14,55 @@
protoV1 "github.com/golang/protobuf/proto"
descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
ptag "github.com/golang/protobuf/v2/internal/encoding/tag"
+ pvalue "github.com/golang/protobuf/v2/internal/value"
pref "github.com/golang/protobuf/v2/reflect/protoreflect"
ptype "github.com/golang/protobuf/v2/reflect/prototype"
)
var messageTypeCache sync.Map // map[reflect.Type]*MessageType
-// wrapLegacyMessage wraps v as a protoreflect.Message, where v must be
-// a *struct kind and not implement the v2 API already.
-func wrapLegacyMessage(v reflect.Value) pref.Message {
+// wrapLegacyMessage wraps v as a protoreflect.ProtoMessage,
+// where v must be a *struct kind and not implement the v2 API already.
+func wrapLegacyMessage(v reflect.Value) pref.ProtoMessage {
// Fast-path: check if a MessageType is cached for this concrete type.
if mt, ok := messageTypeCache.Load(v.Type()); ok {
- return mt.(*MessageType).MessageOf(v.Interface())
+ return mt.(*MessageType).MessageOf(v.Interface()).Interface()
}
// Slow-path: derive message descriptor and initialize MessageType.
mt := &MessageType{Desc: loadMessageDesc(v.Type())}
messageTypeCache.Store(v.Type(), mt)
- return mt.MessageOf(v.Interface())
+ return mt.MessageOf(v.Interface()).Interface()
}
+type legacyMessageWrapper messageDataType
+
+func (m *legacyMessageWrapper) Type() pref.MessageType {
+ return m.mi.pbType
+}
+func (m *legacyMessageWrapper) KnownFields() pref.KnownFields {
+ return (*knownFields)(m)
+}
+func (m *legacyMessageWrapper) UnknownFields() pref.UnknownFields {
+ return m.mi.unknownFields((*messageDataType)(m))
+}
+func (m *legacyMessageWrapper) Unwrap() interface{} {
+ return m.p.asType(m.mi.goType.Elem()).Interface()
+}
+func (m *legacyMessageWrapper) Interface() pref.ProtoMessage {
+ return m
+}
+func (m *legacyMessageWrapper) ProtoReflect() pref.Message {
+ return m
+}
+func (m *legacyMessageWrapper) ProtoMutable() {}
+
+var (
+ _ pref.Message = (*legacyMessageWrapper)(nil)
+ _ pref.ProtoMessage = (*legacyMessageWrapper)(nil)
+ _ pvalue.Unwrapper = (*legacyMessageWrapper)(nil)
+)
+
var messageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor
// loadMessageDesc returns an MessageDescriptor derived from the Go type,
@@ -85,8 +114,8 @@
}
// Slow-path: Walk over the struct fields to derive the message descriptor.
- if t.Kind() != reflect.Ptr && t.Elem().Kind() != reflect.Struct {
- panic(fmt.Sprintf("got %v, want *struct kind", t))
+ if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct || t.Elem().PkgPath() == "" {
+ panic(fmt.Sprintf("got %v, want named *struct kind", t))
}
// Derive name and syntax from the raw descriptor.