blob: 9ea390066020f211e853a759ac7ec146d5f099aa [file] [log] [blame]
Joe Tsai08e00302018-11-26 22:32:06 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package impl
6
7import (
Joe Tsai0fc49f82019-05-01 12:29:25 -07008 "reflect"
Joe Tsai8e506a82019-03-16 00:05:34 -07009 "strconv"
10
Damien Neil5c5b5312019-05-14 12:44:37 -070011 "google.golang.org/protobuf/encoding/prototext"
Damien Neile89e6242019-05-13 23:55:40 -070012 pref "google.golang.org/protobuf/reflect/protoreflect"
Joe Tsai08e00302018-11-26 22:32:06 -080013)
14
15// Export is a zero-length named type that exists only to export a set of
16// functions that we do not want to appear in godoc.
17type Export struct{}
18
Joe Tsai0fc49f82019-05-01 12:29:25 -070019// enum is any enum type generated by protoc-gen-go
20// and must be a named int32 type.
21type enum = interface{}
22
Joe Tsai08e00302018-11-26 22:32:06 -080023// EnumOf returns the protoreflect.Enum interface over e.
Joe Tsai0fc49f82019-05-01 12:29:25 -070024func (Export) EnumOf(e enum) pref.Enum {
Damien Neila8593ba2019-01-08 16:18:07 -080025 if ev, ok := e.(pref.Enum); ok {
26 return ev
Joe Tsai08e00302018-11-26 22:32:06 -080027 }
28 return legacyWrapper.EnumOf(e)
29}
30
31// EnumTypeOf returns the protoreflect.EnumType for e.
Joe Tsai0fc49f82019-05-01 12:29:25 -070032func (Export) EnumTypeOf(e enum) pref.EnumType {
Damien Neila8593ba2019-01-08 16:18:07 -080033 if ev, ok := e.(pref.Enum); ok {
Joe Tsai0fc49f82019-05-01 12:29:25 -070034 return &enumType{ev.Descriptor(), reflect.TypeOf(e)}
Joe Tsai08e00302018-11-26 22:32:06 -080035 }
36 return legacyWrapper.EnumTypeOf(e)
37}
38
Joe Tsai0fc49f82019-05-01 12:29:25 -070039// TODO: This needs to be centralized in a package.
40type enumType struct {
41 // TODO: Remove me as an embedded field.
42 pref.EnumDescriptor
43 typ reflect.Type // must implement protoreflect.Enum
44}
45
46func (t *enumType) Descriptor() pref.EnumDescriptor { return t.EnumDescriptor }
47func (t *enumType) GoType() reflect.Type { return t.typ }
48func (t *enumType) New(n pref.EnumNumber) pref.Enum {
49 return reflect.ValueOf(n).Convert(t.typ).Interface().(pref.Enum)
50}
51
52// EnumDescriptorOf returns the protoreflect.EnumDescriptor for e.
53func (Export) EnumDescriptorOf(e enum) pref.EnumDescriptor {
54 if ev, ok := e.(pref.Enum); ok {
55 return ev.Descriptor()
56 }
57 return legacyWrapper.EnumDescriptorOf(e)
58}
59
Joe Tsai8e506a82019-03-16 00:05:34 -070060// EnumStringOf returns the enum value as a string, either as the name if
61// the number is resolvable, or the number formatted as a string.
62func (Export) EnumStringOf(ed pref.EnumDescriptor, n pref.EnumNumber) string {
63 ev := ed.Values().ByNumber(n)
64 if ev != nil {
65 return string(ev.Name())
66 }
67 return strconv.Itoa(int(n))
68}
69
Joe Tsai0fc49f82019-05-01 12:29:25 -070070// message is any message type generated by protoc-gen-go
71// and must be a pointer to a named struct type.
72type message = interface{}
73
Joe Tsai08e00302018-11-26 22:32:06 -080074// MessageOf returns the protoreflect.Message interface over m.
Joe Tsai0fc49f82019-05-01 12:29:25 -070075func (Export) MessageOf(m message) pref.Message {
Joe Tsai08e00302018-11-26 22:32:06 -080076 if mv, ok := m.(pref.ProtoMessage); ok {
77 return mv.ProtoReflect()
78 }
79 return legacyWrapper.MessageOf(m)
80}
81
82// MessageTypeOf returns the protoreflect.MessageType for m.
Joe Tsai0fc49f82019-05-01 12:29:25 -070083func (Export) MessageTypeOf(m message) pref.MessageType {
Joe Tsai08e00302018-11-26 22:32:06 -080084 if mv, ok := m.(pref.ProtoMessage); ok {
Joe Tsai0fc49f82019-05-01 12:29:25 -070085 return &messageType{mv.ProtoReflect().Descriptor(), reflect.TypeOf(m)}
Joe Tsai08e00302018-11-26 22:32:06 -080086 }
87 return legacyWrapper.MessageTypeOf(m)
88}
89
Joe Tsai0fc49f82019-05-01 12:29:25 -070090// TODO: This needs to be centralized in a package.
91type messageType struct {
92 // TODO: Remove me as an embedded field.
93 pref.MessageDescriptor
94 typ reflect.Type // must implement protoreflect.ProtoMessage
95}
96
97func (t *messageType) Descriptor() pref.MessageDescriptor { return t.MessageDescriptor }
98func (t *messageType) GoType() reflect.Type { return t.typ }
99func (t *messageType) New() pref.Message {
100 return reflect.New(t.typ.Elem()).Interface().(pref.ProtoMessage).ProtoReflect()
101}
102
103// MessageDescriptorOf returns the protoreflect.MessageDescriptor for m.
104func (Export) MessageDescriptorOf(m message) pref.MessageDescriptor {
105 if mv, ok := m.(pref.ProtoMessage); ok {
106 return mv.ProtoReflect().Descriptor()
Joe Tsai08e00302018-11-26 22:32:06 -0800107 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700108 return legacyWrapper.MessageDescriptorOf(m)
Joe Tsai08e00302018-11-26 22:32:06 -0800109}
Joe Tsai1321a0e2019-03-20 09:46:22 -0700110
111// MessageStringOf returns the message value as a string,
112// which is the message serialized in the protobuf text format.
113func (Export) MessageStringOf(m pref.ProtoMessage) string {
Damien Neil5c5b5312019-05-14 12:44:37 -0700114 b, _ := prototext.MarshalOptions{AllowPartial: true}.Marshal(m)
Joe Tsai1321a0e2019-03-20 09:46:22 -0700115 return string(b)
116}