-
Notifications
You must be signed in to change notification settings - Fork 168
/
wrap.go
208 lines (186 loc) · 6.65 KB
/
wrap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
package desc
import (
"fmt"
"github.com/bufbuild/protocompile/protoutil"
"google.golang.org/protobuf/reflect/protoreflect"
)
// DescriptorWrapper wraps a protoreflect.Descriptor. All of the Descriptor
// implementations in this package implement this interface. This can be
// used to recover the underlying descriptor. Each descriptor type in this
// package also provides a strongly-typed form of this method, such as the
// following method for *FileDescriptor:
//
// UnwrapFile() protoreflect.FileDescriptor
type DescriptorWrapper interface {
Unwrap() protoreflect.Descriptor
}
// WrapDescriptor wraps the given descriptor, returning a desc.Descriptor
// value that represents the same element.
func WrapDescriptor(d protoreflect.Descriptor) (Descriptor, error) {
return wrapDescriptor(d, noopCache{})
}
func wrapDescriptor(d protoreflect.Descriptor, cache descriptorCache) (Descriptor, error) {
switch d := d.(type) {
case protoreflect.FileDescriptor:
return wrapFile(d, cache)
case protoreflect.MessageDescriptor:
return wrapMessage(d, cache)
case protoreflect.FieldDescriptor:
return wrapField(d, cache)
case protoreflect.OneofDescriptor:
return wrapOneOf(d, cache)
case protoreflect.EnumDescriptor:
return wrapEnum(d, cache)
case protoreflect.EnumValueDescriptor:
return wrapEnumValue(d, cache)
case protoreflect.ServiceDescriptor:
return wrapService(d, cache)
case protoreflect.MethodDescriptor:
return wrapMethod(d, cache)
default:
return nil, fmt.Errorf("unknown descriptor type: %T", d)
}
}
// WrapFiles wraps the given file descriptors, returning a slice of *desc.FileDescriptor
// values that represent the same files.
func WrapFiles(d []protoreflect.FileDescriptor) ([]*FileDescriptor, error) {
cache := mapCache{}
results := make([]*FileDescriptor, len(d))
for i := range d {
var err error
results[i], err = wrapFile(d[i], cache)
if err != nil {
return nil, err
}
}
return results, nil
}
// WrapFile wraps the given file descriptor, returning a *desc.FileDescriptor
// value that represents the same file.
func WrapFile(d protoreflect.FileDescriptor) (*FileDescriptor, error) {
return wrapFile(d, noopCache{})
}
func wrapFile(d protoreflect.FileDescriptor, cache descriptorCache) (*FileDescriptor, error) {
fdp := protoutil.ProtoFromFileDescriptor(d)
return convertFile(d, fdp, cache)
}
// WrapMessage wraps the given message descriptor, returning a *desc.MessageDescriptor
// value that represents the same message.
func WrapMessage(d protoreflect.MessageDescriptor) (*MessageDescriptor, error) {
return wrapMessage(d, noopCache{})
}
func wrapMessage(d protoreflect.MessageDescriptor, cache descriptorCache) (*MessageDescriptor, error) {
parent, err := wrapDescriptor(d.Parent(), cache)
if err != nil {
return nil, err
}
switch p := parent.(type) {
case *FileDescriptor:
return p.messages[d.Index()], nil
case *MessageDescriptor:
return p.nested[d.Index()], nil
default:
return nil, fmt.Errorf("message has unexpected parent type: %T", parent)
}
}
// WrapField wraps the given field descriptor, returning a *desc.FieldDescriptor
// value that represents the same field.
func WrapField(d protoreflect.FieldDescriptor) (*FieldDescriptor, error) {
return wrapField(d, noopCache{})
}
func wrapField(d protoreflect.FieldDescriptor, cache descriptorCache) (*FieldDescriptor, error) {
parent, err := wrapDescriptor(d.Parent(), cache)
if err != nil {
return nil, err
}
switch p := parent.(type) {
case *FileDescriptor:
return p.extensions[d.Index()], nil
case *MessageDescriptor:
if d.IsExtension() {
return p.extensions[d.Index()], nil
}
return p.fields[d.Index()], nil
default:
return nil, fmt.Errorf("field has unexpected parent type: %T", parent)
}
}
// WrapOneOf wraps the given oneof descriptor, returning a *desc.OneOfDescriptor
// value that represents the same oneof.
func WrapOneOf(d protoreflect.OneofDescriptor) (*OneOfDescriptor, error) {
return wrapOneOf(d, noopCache{})
}
func wrapOneOf(d protoreflect.OneofDescriptor, cache descriptorCache) (*OneOfDescriptor, error) {
parent, err := wrapDescriptor(d.Parent(), cache)
if err != nil {
return nil, err
}
if p, ok := parent.(*MessageDescriptor); ok {
return p.oneOfs[d.Index()], nil
}
return nil, fmt.Errorf("oneof has unexpected parent type: %T", parent)
}
// WrapEnum wraps the given enum descriptor, returning a *desc.EnumDescriptor
// value that represents the same enum.
func WrapEnum(d protoreflect.EnumDescriptor) (*EnumDescriptor, error) {
return wrapEnum(d, noopCache{})
}
func wrapEnum(d protoreflect.EnumDescriptor, cache descriptorCache) (*EnumDescriptor, error) {
parent, err := wrapDescriptor(d.Parent(), cache)
if err != nil {
return nil, err
}
switch p := parent.(type) {
case *FileDescriptor:
return p.enums[d.Index()], nil
case *MessageDescriptor:
return p.enums[d.Index()], nil
default:
return nil, fmt.Errorf("enum has unexpected parent type: %T", parent)
}
}
// WrapEnumValue wraps the given enum value descriptor, returning a *desc.EnumValueDescriptor
// value that represents the same enum value.
func WrapEnumValue(d protoreflect.EnumValueDescriptor) (*EnumValueDescriptor, error) {
return wrapEnumValue(d, noopCache{})
}
func wrapEnumValue(d protoreflect.EnumValueDescriptor, cache descriptorCache) (*EnumValueDescriptor, error) {
parent, err := wrapDescriptor(d.Parent(), cache)
if err != nil {
return nil, err
}
if p, ok := parent.(*EnumDescriptor); ok {
return p.values[d.Index()], nil
}
return nil, fmt.Errorf("enum value has unexpected parent type: %T", parent)
}
// WrapService wraps the given service descriptor, returning a *desc.ServiceDescriptor
// value that represents the same service.
func WrapService(d protoreflect.ServiceDescriptor) (*ServiceDescriptor, error) {
return wrapService(d, noopCache{})
}
func wrapService(d protoreflect.ServiceDescriptor, cache descriptorCache) (*ServiceDescriptor, error) {
parent, err := wrapDescriptor(d.Parent(), cache)
if err != nil {
return nil, err
}
if p, ok := parent.(*FileDescriptor); ok {
return p.services[d.Index()], nil
}
return nil, fmt.Errorf("service has unexpected parent type: %T", parent)
}
// WrapMethod wraps the given method descriptor, returning a *desc.MethodDescriptor
// value that represents the same method.
func WrapMethod(d protoreflect.MethodDescriptor) (*MethodDescriptor, error) {
return wrapMethod(d, noopCache{})
}
func wrapMethod(d protoreflect.MethodDescriptor, cache descriptorCache) (*MethodDescriptor, error) {
parent, err := wrapDescriptor(d.Parent(), cache)
if err != nil {
return nil, err
}
if p, ok := parent.(*ServiceDescriptor); ok {
return p.methods[d.Index()], nil
}
return nil, fmt.Errorf("method has unexpected parent type: %T", parent)
}