blob: 42f0f8eb126f353f3fd8001a796753a7ec5d11fc [file] [log] [blame]
khenaidooefff76e2021-12-15 16:51:30 -05001package desc
2
3import (
4 "bytes"
5 "fmt"
6 "sort"
7 "strconv"
8 "strings"
9 "unicode"
10 "unicode/utf8"
11
12 "github.com/golang/protobuf/proto"
13 dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
14
15 "github.com/jhump/protoreflect/desc/internal"
16)
17
18// Descriptor is the common interface implemented by all descriptor objects.
19type Descriptor interface {
20 // GetName returns the name of the object described by the descriptor. This will
21 // be a base name that does not include enclosing message names or the package name.
22 // For file descriptors, this indicates the path and name to the described file.
23 GetName() string
24 // GetFullyQualifiedName returns the fully-qualified name of the object described by
25 // the descriptor. This will include the package name and any enclosing message names.
26 // For file descriptors, this returns the path and name to the described file (same as
27 // GetName).
28 GetFullyQualifiedName() string
29 // GetParent returns the enclosing element in a proto source file. If the described
30 // object is a top-level object, this returns the file descriptor. Otherwise, it returns
31 // the element in which the described object was declared. File descriptors have no
32 // parent and return nil.
33 GetParent() Descriptor
34 // GetFile returns the file descriptor in which this element was declared. File
35 // descriptors return themselves.
36 GetFile() *FileDescriptor
37 // GetOptions returns the options proto containing options for the described element.
38 GetOptions() proto.Message
39 // GetSourceInfo returns any source code information that was present in the file
40 // descriptor. Source code info is optional. If no source code info is available for
41 // the element (including if there is none at all in the file descriptor) then this
42 // returns nil
43 GetSourceInfo() *dpb.SourceCodeInfo_Location
44 // AsProto returns the underlying descriptor proto for this descriptor.
45 AsProto() proto.Message
46}
47
48type sourceInfoRecomputeFunc = internal.SourceInfoComputeFunc
49
50// FileDescriptor describes a proto source file.
51type FileDescriptor struct {
52 proto *dpb.FileDescriptorProto
53 symbols map[string]Descriptor
54 deps []*FileDescriptor
55 publicDeps []*FileDescriptor
56 weakDeps []*FileDescriptor
57 messages []*MessageDescriptor
58 enums []*EnumDescriptor
59 extensions []*FieldDescriptor
60 services []*ServiceDescriptor
61 fieldIndex map[string]map[int32]*FieldDescriptor
62 isProto3 bool
63 sourceInfo internal.SourceInfoMap
64 sourceInfoRecomputeFunc
65}
66
67func (fd *FileDescriptor) recomputeSourceInfo() {
68 internal.PopulateSourceInfoMap(fd.proto, fd.sourceInfo)
69}
70
71func (fd *FileDescriptor) registerField(field *FieldDescriptor) {
72 fields := fd.fieldIndex[field.owner.GetFullyQualifiedName()]
73 if fields == nil {
74 fields = map[int32]*FieldDescriptor{}
75 fd.fieldIndex[field.owner.GetFullyQualifiedName()] = fields
76 }
77 fields[field.GetNumber()] = field
78}
79
80// GetName returns the name of the file, as it was given to the protoc invocation
81// to compile it, possibly including path (relative to a directory in the proto
82// import path).
83func (fd *FileDescriptor) GetName() string {
84 return fd.proto.GetName()
85}
86
87// GetFullyQualifiedName returns the name of the file, same as GetName. It is
88// present to satisfy the Descriptor interface.
89func (fd *FileDescriptor) GetFullyQualifiedName() string {
90 return fd.proto.GetName()
91}
92
93// GetPackage returns the name of the package declared in the file.
94func (fd *FileDescriptor) GetPackage() string {
95 return fd.proto.GetPackage()
96}
97
98// GetParent always returns nil: files are the root of descriptor hierarchies.
99// Is it present to satisfy the Descriptor interface.
100func (fd *FileDescriptor) GetParent() Descriptor {
101 return nil
102}
103
104// GetFile returns the receiver, which is a file descriptor. This is present
105// to satisfy the Descriptor interface.
106func (fd *FileDescriptor) GetFile() *FileDescriptor {
107 return fd
108}
109
110// GetOptions returns the file's options. Most usages will be more interested
111// in GetFileOptions, which has a concrete return type. This generic version
112// is present to satisfy the Descriptor interface.
113func (fd *FileDescriptor) GetOptions() proto.Message {
114 return fd.proto.GetOptions()
115}
116
117// GetFileOptions returns the file's options.
118func (fd *FileDescriptor) GetFileOptions() *dpb.FileOptions {
119 return fd.proto.GetOptions()
120}
121
122// GetSourceInfo returns nil for files. It is present to satisfy the Descriptor
123// interface.
124func (fd *FileDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
125 return nil
126}
127
128// AsProto returns the underlying descriptor proto. Most usages will be more
129// interested in AsFileDescriptorProto, which has a concrete return type. This
130// generic version is present to satisfy the Descriptor interface.
131func (fd *FileDescriptor) AsProto() proto.Message {
132 return fd.proto
133}
134
135// AsFileDescriptorProto returns the underlying descriptor proto.
136func (fd *FileDescriptor) AsFileDescriptorProto() *dpb.FileDescriptorProto {
137 return fd.proto
138}
139
140// String returns the underlying descriptor proto, in compact text format.
141func (fd *FileDescriptor) String() string {
142 return fd.proto.String()
143}
144
145// IsProto3 returns true if the file declares a syntax of "proto3".
146func (fd *FileDescriptor) IsProto3() bool {
147 return fd.isProto3
148}
149
150// GetDependencies returns all of this file's dependencies. These correspond to
151// import statements in the file.
152func (fd *FileDescriptor) GetDependencies() []*FileDescriptor {
153 return fd.deps
154}
155
156// GetPublicDependencies returns all of this file's public dependencies. These
157// correspond to public import statements in the file.
158func (fd *FileDescriptor) GetPublicDependencies() []*FileDescriptor {
159 return fd.publicDeps
160}
161
162// GetWeakDependencies returns all of this file's weak dependencies. These
163// correspond to weak import statements in the file.
164func (fd *FileDescriptor) GetWeakDependencies() []*FileDescriptor {
165 return fd.weakDeps
166}
167
168// GetMessageTypes returns all top-level messages declared in this file.
169func (fd *FileDescriptor) GetMessageTypes() []*MessageDescriptor {
170 return fd.messages
171}
172
173// GetEnumTypes returns all top-level enums declared in this file.
174func (fd *FileDescriptor) GetEnumTypes() []*EnumDescriptor {
175 return fd.enums
176}
177
178// GetExtensions returns all top-level extensions declared in this file.
179func (fd *FileDescriptor) GetExtensions() []*FieldDescriptor {
180 return fd.extensions
181}
182
183// GetServices returns all services declared in this file.
184func (fd *FileDescriptor) GetServices() []*ServiceDescriptor {
185 return fd.services
186}
187
188// FindSymbol returns the descriptor contained within this file for the
189// element with the given fully-qualified symbol name. If no such element
190// exists then this method returns nil.
191func (fd *FileDescriptor) FindSymbol(symbol string) Descriptor {
192 if symbol[0] == '.' {
193 symbol = symbol[1:]
194 }
195 if ret := fd.symbols[symbol]; ret != nil {
196 return ret
197 }
198
199 // allow accessing symbols through public imports, too
200 for _, dep := range fd.GetPublicDependencies() {
201 if ret := dep.FindSymbol(symbol); ret != nil {
202 return ret
203 }
204 }
205
206 // not found
207 return nil
208}
209
210// FindMessage finds the message with the given fully-qualified name. If no
211// such element exists in this file then nil is returned.
212func (fd *FileDescriptor) FindMessage(msgName string) *MessageDescriptor {
213 if md, ok := fd.symbols[msgName].(*MessageDescriptor); ok {
214 return md
215 } else {
216 return nil
217 }
218}
219
220// FindEnum finds the enum with the given fully-qualified name. If no such
221// element exists in this file then nil is returned.
222func (fd *FileDescriptor) FindEnum(enumName string) *EnumDescriptor {
223 if ed, ok := fd.symbols[enumName].(*EnumDescriptor); ok {
224 return ed
225 } else {
226 return nil
227 }
228}
229
230// FindService finds the service with the given fully-qualified name. If no
231// such element exists in this file then nil is returned.
232func (fd *FileDescriptor) FindService(serviceName string) *ServiceDescriptor {
233 if sd, ok := fd.symbols[serviceName].(*ServiceDescriptor); ok {
234 return sd
235 } else {
236 return nil
237 }
238}
239
240// FindExtension finds the extension field for the given extended type name and
241// tag number. If no such element exists in this file then nil is returned.
242func (fd *FileDescriptor) FindExtension(extendeeName string, tagNumber int32) *FieldDescriptor {
243 if exd, ok := fd.fieldIndex[extendeeName][tagNumber]; ok && exd.IsExtension() {
244 return exd
245 } else {
246 return nil
247 }
248}
249
250// FindExtensionByName finds the extension field with the given fully-qualified
251// name. If no such element exists in this file then nil is returned.
252func (fd *FileDescriptor) FindExtensionByName(extName string) *FieldDescriptor {
253 if exd, ok := fd.symbols[extName].(*FieldDescriptor); ok && exd.IsExtension() {
254 return exd
255 } else {
256 return nil
257 }
258}
259
260// MessageDescriptor describes a protocol buffer message.
261type MessageDescriptor struct {
262 proto *dpb.DescriptorProto
263 parent Descriptor
264 file *FileDescriptor
265 fields []*FieldDescriptor
266 nested []*MessageDescriptor
267 enums []*EnumDescriptor
268 extensions []*FieldDescriptor
269 oneOfs []*OneOfDescriptor
270 extRanges extRanges
271 fqn string
272 sourceInfoPath []int32
273 jsonNames jsonNameMap
274 isProto3 bool
275 isMapEntry bool
276}
277
278func createMessageDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, md *dpb.DescriptorProto, symbols map[string]Descriptor) (*MessageDescriptor, string) {
279 msgName := merge(enclosing, md.GetName())
280 ret := &MessageDescriptor{proto: md, parent: parent, file: fd, fqn: msgName}
281 for _, f := range md.GetField() {
282 fld, n := createFieldDescriptor(fd, ret, msgName, f)
283 symbols[n] = fld
284 ret.fields = append(ret.fields, fld)
285 }
286 for _, nm := range md.NestedType {
287 nmd, n := createMessageDescriptor(fd, ret, msgName, nm, symbols)
288 symbols[n] = nmd
289 ret.nested = append(ret.nested, nmd)
290 }
291 for _, e := range md.EnumType {
292 ed, n := createEnumDescriptor(fd, ret, msgName, e, symbols)
293 symbols[n] = ed
294 ret.enums = append(ret.enums, ed)
295 }
296 for _, ex := range md.GetExtension() {
297 exd, n := createFieldDescriptor(fd, ret, msgName, ex)
298 symbols[n] = exd
299 ret.extensions = append(ret.extensions, exd)
300 }
301 for i, o := range md.GetOneofDecl() {
302 od, n := createOneOfDescriptor(fd, ret, i, msgName, o)
303 symbols[n] = od
304 ret.oneOfs = append(ret.oneOfs, od)
305 }
306 for _, r := range md.GetExtensionRange() {
307 // proto.ExtensionRange is inclusive (and that's how extension ranges are defined in code).
308 // but protoc converts range to exclusive end in descriptor, so we must convert back
309 end := r.GetEnd() - 1
310 ret.extRanges = append(ret.extRanges, proto.ExtensionRange{
311 Start: r.GetStart(),
312 End: end})
313 }
314 sort.Sort(ret.extRanges)
315 ret.isProto3 = fd.isProto3
316 ret.isMapEntry = md.GetOptions().GetMapEntry() &&
317 len(ret.fields) == 2 &&
318 ret.fields[0].GetNumber() == 1 &&
319 ret.fields[1].GetNumber() == 2
320
321 return ret, msgName
322}
323
324func (md *MessageDescriptor) resolve(path []int32, scopes []scope) error {
325 md.sourceInfoPath = append([]int32(nil), path...) // defensive copy
326 path = append(path, internal.Message_nestedMessagesTag)
327 scopes = append(scopes, messageScope(md))
328 for i, nmd := range md.nested {
329 if err := nmd.resolve(append(path, int32(i)), scopes); err != nil {
330 return err
331 }
332 }
333 path[len(path)-1] = internal.Message_enumsTag
334 for i, ed := range md.enums {
335 ed.resolve(append(path, int32(i)))
336 }
337 path[len(path)-1] = internal.Message_fieldsTag
338 for i, fld := range md.fields {
339 if err := fld.resolve(append(path, int32(i)), scopes); err != nil {
340 return err
341 }
342 }
343 path[len(path)-1] = internal.Message_extensionsTag
344 for i, exd := range md.extensions {
345 if err := exd.resolve(append(path, int32(i)), scopes); err != nil {
346 return err
347 }
348 }
349 path[len(path)-1] = internal.Message_oneOfsTag
350 for i, od := range md.oneOfs {
351 od.resolve(append(path, int32(i)))
352 }
353 return nil
354}
355
356// GetName returns the simple (unqualified) name of the message.
357func (md *MessageDescriptor) GetName() string {
358 return md.proto.GetName()
359}
360
361// GetFullyQualifiedName returns the fully qualified name of the message. This
362// includes the package name (if there is one) as well as the names of any
363// enclosing messages.
364func (md *MessageDescriptor) GetFullyQualifiedName() string {
365 return md.fqn
366}
367
368// GetParent returns the message's enclosing descriptor. For top-level messages,
369// this will be a file descriptor. Otherwise it will be the descriptor for the
370// enclosing message.
371func (md *MessageDescriptor) GetParent() Descriptor {
372 return md.parent
373}
374
375// GetFile returns the descriptor for the file in which this message is defined.
376func (md *MessageDescriptor) GetFile() *FileDescriptor {
377 return md.file
378}
379
380// GetOptions returns the message's options. Most usages will be more interested
381// in GetMessageOptions, which has a concrete return type. This generic version
382// is present to satisfy the Descriptor interface.
383func (md *MessageDescriptor) GetOptions() proto.Message {
384 return md.proto.GetOptions()
385}
386
387// GetMessageOptions returns the message's options.
388func (md *MessageDescriptor) GetMessageOptions() *dpb.MessageOptions {
389 return md.proto.GetOptions()
390}
391
392// GetSourceInfo returns source info for the message, if present in the
393// descriptor. Not all descriptors will contain source info. If non-nil, the
394// returned info contains information about the location in the file where the
395// message was defined and also contains comments associated with the message
396// definition.
397func (md *MessageDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
398 return md.file.sourceInfo.Get(md.sourceInfoPath)
399}
400
401// AsProto returns the underlying descriptor proto. Most usages will be more
402// interested in AsDescriptorProto, which has a concrete return type. This
403// generic version is present to satisfy the Descriptor interface.
404func (md *MessageDescriptor) AsProto() proto.Message {
405 return md.proto
406}
407
408// AsDescriptorProto returns the underlying descriptor proto.
409func (md *MessageDescriptor) AsDescriptorProto() *dpb.DescriptorProto {
410 return md.proto
411}
412
413// String returns the underlying descriptor proto, in compact text format.
414func (md *MessageDescriptor) String() string {
415 return md.proto.String()
416}
417
418// IsMapEntry returns true if this is a synthetic message type that represents an entry
419// in a map field.
420func (md *MessageDescriptor) IsMapEntry() bool {
421 return md.isMapEntry
422}
423
424// GetFields returns all of the fields for this message.
425func (md *MessageDescriptor) GetFields() []*FieldDescriptor {
426 return md.fields
427}
428
429// GetNestedMessageTypes returns all of the message types declared inside this message.
430func (md *MessageDescriptor) GetNestedMessageTypes() []*MessageDescriptor {
431 return md.nested
432}
433
434// GetNestedEnumTypes returns all of the enums declared inside this message.
435func (md *MessageDescriptor) GetNestedEnumTypes() []*EnumDescriptor {
436 return md.enums
437}
438
439// GetNestedExtensions returns all of the extensions declared inside this message.
440func (md *MessageDescriptor) GetNestedExtensions() []*FieldDescriptor {
441 return md.extensions
442}
443
444// GetOneOfs returns all of the one-of field sets declared inside this message.
445func (md *MessageDescriptor) GetOneOfs() []*OneOfDescriptor {
446 return md.oneOfs
447}
448
449// IsProto3 returns true if the file in which this message is defined declares a syntax of "proto3".
450func (md *MessageDescriptor) IsProto3() bool {
451 return md.isProto3
452}
453
454// GetExtensionRanges returns the ranges of extension field numbers for this message.
455func (md *MessageDescriptor) GetExtensionRanges() []proto.ExtensionRange {
456 return md.extRanges
457}
458
459// IsExtendable returns true if this message has any extension ranges.
460func (md *MessageDescriptor) IsExtendable() bool {
461 return len(md.extRanges) > 0
462}
463
464// IsExtension returns true if the given tag number is within any of this message's
465// extension ranges.
466func (md *MessageDescriptor) IsExtension(tagNumber int32) bool {
467 return md.extRanges.IsExtension(tagNumber)
468}
469
470type extRanges []proto.ExtensionRange
471
472func (er extRanges) String() string {
473 var buf bytes.Buffer
474 first := true
475 for _, r := range er {
476 if first {
477 first = false
478 } else {
479 buf.WriteString(",")
480 }
481 fmt.Fprintf(&buf, "%d..%d", r.Start, r.End)
482 }
483 return buf.String()
484}
485
486func (er extRanges) IsExtension(tagNumber int32) bool {
487 i := sort.Search(len(er), func(i int) bool { return er[i].End >= tagNumber })
488 return i < len(er) && tagNumber >= er[i].Start
489}
490
491func (er extRanges) Len() int {
492 return len(er)
493}
494
495func (er extRanges) Less(i, j int) bool {
496 return er[i].Start < er[j].Start
497}
498
499func (er extRanges) Swap(i, j int) {
500 er[i], er[j] = er[j], er[i]
501}
502
503// FindFieldByName finds the field with the given name. If no such field exists
504// then nil is returned. Only regular fields are returned, not extensions.
505func (md *MessageDescriptor) FindFieldByName(fieldName string) *FieldDescriptor {
506 fqn := fmt.Sprintf("%s.%s", md.fqn, fieldName)
507 if fd, ok := md.file.symbols[fqn].(*FieldDescriptor); ok && !fd.IsExtension() {
508 return fd
509 } else {
510 return nil
511 }
512}
513
514// FindFieldByNumber finds the field with the given tag number. If no such field
515// exists then nil is returned. Only regular fields are returned, not extensions.
516func (md *MessageDescriptor) FindFieldByNumber(tagNumber int32) *FieldDescriptor {
517 if fd, ok := md.file.fieldIndex[md.fqn][tagNumber]; ok && !fd.IsExtension() {
518 return fd
519 } else {
520 return nil
521 }
522}
523
524// FieldDescriptor describes a field of a protocol buffer message.
525type FieldDescriptor struct {
526 proto *dpb.FieldDescriptorProto
527 parent Descriptor
528 owner *MessageDescriptor
529 file *FileDescriptor
530 oneOf *OneOfDescriptor
531 msgType *MessageDescriptor
532 enumType *EnumDescriptor
533 fqn string
534 sourceInfoPath []int32
535 def memoizedDefault
536 isMap bool
537}
538
539func createFieldDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, fld *dpb.FieldDescriptorProto) (*FieldDescriptor, string) {
540 fldName := merge(enclosing, fld.GetName())
541 ret := &FieldDescriptor{proto: fld, parent: parent, file: fd, fqn: fldName}
542 if fld.GetExtendee() == "" {
543 ret.owner = parent.(*MessageDescriptor)
544 }
545 // owner for extensions, field type (be it message or enum), and one-ofs get resolved later
546 return ret, fldName
547}
548
549func (fd *FieldDescriptor) resolve(path []int32, scopes []scope) error {
550 if fd.proto.OneofIndex != nil && fd.oneOf == nil {
551 return fmt.Errorf("could not link field %s to one-of index %d", fd.fqn, *fd.proto.OneofIndex)
552 }
553 fd.sourceInfoPath = append([]int32(nil), path...) // defensive copy
554 if fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_ENUM {
555 if desc, err := resolve(fd.file, fd.proto.GetTypeName(), scopes); err != nil {
556 return err
557 } else {
558 fd.enumType = desc.(*EnumDescriptor)
559 }
560 }
561 if fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_MESSAGE || fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_GROUP {
562 if desc, err := resolve(fd.file, fd.proto.GetTypeName(), scopes); err != nil {
563 return err
564 } else {
565 fd.msgType = desc.(*MessageDescriptor)
566 }
567 }
568 if fd.proto.GetExtendee() != "" {
569 if desc, err := resolve(fd.file, fd.proto.GetExtendee(), scopes); err != nil {
570 return err
571 } else {
572 fd.owner = desc.(*MessageDescriptor)
573 }
574 }
575 fd.file.registerField(fd)
576 fd.isMap = fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REPEATED &&
577 fd.proto.GetType() == dpb.FieldDescriptorProto_TYPE_MESSAGE &&
578 fd.GetMessageType().IsMapEntry()
579 return nil
580}
581
582func (fd *FieldDescriptor) determineDefault() interface{} {
583 if fd.IsMap() {
584 return map[interface{}]interface{}(nil)
585 } else if fd.IsRepeated() {
586 return []interface{}(nil)
587 } else if fd.msgType != nil {
588 return nil
589 }
590
591 proto3 := fd.file.isProto3
592 if !proto3 {
593 def := fd.AsFieldDescriptorProto().GetDefaultValue()
594 if def != "" {
595 ret := parseDefaultValue(fd, def)
596 if ret != nil {
597 return ret
598 }
599 // if we can't parse default value, fall-through to return normal default...
600 }
601 }
602
603 switch fd.GetType() {
604 case dpb.FieldDescriptorProto_TYPE_FIXED32,
605 dpb.FieldDescriptorProto_TYPE_UINT32:
606 return uint32(0)
607 case dpb.FieldDescriptorProto_TYPE_SFIXED32,
608 dpb.FieldDescriptorProto_TYPE_INT32,
609 dpb.FieldDescriptorProto_TYPE_SINT32:
610 return int32(0)
611 case dpb.FieldDescriptorProto_TYPE_FIXED64,
612 dpb.FieldDescriptorProto_TYPE_UINT64:
613 return uint64(0)
614 case dpb.FieldDescriptorProto_TYPE_SFIXED64,
615 dpb.FieldDescriptorProto_TYPE_INT64,
616 dpb.FieldDescriptorProto_TYPE_SINT64:
617 return int64(0)
618 case dpb.FieldDescriptorProto_TYPE_FLOAT:
619 return float32(0.0)
620 case dpb.FieldDescriptorProto_TYPE_DOUBLE:
621 return float64(0.0)
622 case dpb.FieldDescriptorProto_TYPE_BOOL:
623 return false
624 case dpb.FieldDescriptorProto_TYPE_BYTES:
625 return []byte(nil)
626 case dpb.FieldDescriptorProto_TYPE_STRING:
627 return ""
628 case dpb.FieldDescriptorProto_TYPE_ENUM:
629 if proto3 {
630 return int32(0)
631 }
632 enumVals := fd.GetEnumType().GetValues()
633 if len(enumVals) > 0 {
634 return enumVals[0].GetNumber()
635 } else {
636 return int32(0) // WTF?
637 }
638 default:
639 panic(fmt.Sprintf("Unknown field type: %v", fd.GetType()))
640 }
641}
642
643func parseDefaultValue(fd *FieldDescriptor, val string) interface{} {
644 switch fd.GetType() {
645 case dpb.FieldDescriptorProto_TYPE_ENUM:
646 vd := fd.GetEnumType().FindValueByName(val)
647 if vd != nil {
648 return vd.GetNumber()
649 }
650 return nil
651 case dpb.FieldDescriptorProto_TYPE_BOOL:
652 if val == "true" {
653 return true
654 } else if val == "false" {
655 return false
656 }
657 return nil
658 case dpb.FieldDescriptorProto_TYPE_BYTES:
659 return []byte(unescape(val))
660 case dpb.FieldDescriptorProto_TYPE_STRING:
661 return val
662 case dpb.FieldDescriptorProto_TYPE_FLOAT:
663 if f, err := strconv.ParseFloat(val, 32); err == nil {
664 return float32(f)
665 } else {
666 return float32(0)
667 }
668 case dpb.FieldDescriptorProto_TYPE_DOUBLE:
669 if f, err := strconv.ParseFloat(val, 64); err == nil {
670 return f
671 } else {
672 return float64(0)
673 }
674 case dpb.FieldDescriptorProto_TYPE_INT32,
675 dpb.FieldDescriptorProto_TYPE_SINT32,
676 dpb.FieldDescriptorProto_TYPE_SFIXED32:
677 if i, err := strconv.ParseInt(val, 10, 32); err == nil {
678 return int32(i)
679 } else {
680 return int32(0)
681 }
682 case dpb.FieldDescriptorProto_TYPE_UINT32,
683 dpb.FieldDescriptorProto_TYPE_FIXED32:
684 if i, err := strconv.ParseUint(val, 10, 32); err == nil {
685 return uint32(i)
686 } else {
687 return uint32(0)
688 }
689 case dpb.FieldDescriptorProto_TYPE_INT64,
690 dpb.FieldDescriptorProto_TYPE_SINT64,
691 dpb.FieldDescriptorProto_TYPE_SFIXED64:
692 if i, err := strconv.ParseInt(val, 10, 64); err == nil {
693 return i
694 } else {
695 return int64(0)
696 }
697 case dpb.FieldDescriptorProto_TYPE_UINT64,
698 dpb.FieldDescriptorProto_TYPE_FIXED64:
699 if i, err := strconv.ParseUint(val, 10, 64); err == nil {
700 return i
701 } else {
702 return uint64(0)
703 }
704 default:
705 return nil
706 }
707}
708
709func unescape(s string) string {
710 // protoc encodes default values for 'bytes' fields using C escaping,
711 // so this function reverses that escaping
712 out := make([]byte, 0, len(s))
713 var buf [4]byte
714 for len(s) > 0 {
715 if s[0] != '\\' || len(s) < 2 {
716 // not escape sequence, or too short to be well-formed escape
717 out = append(out, s[0])
718 s = s[1:]
719 } else if s[1] == 'x' || s[1] == 'X' {
720 n := matchPrefix(s[2:], 2, isHex)
721 if n == 0 {
722 // bad escape
723 out = append(out, s[:2]...)
724 s = s[2:]
725 } else {
726 c, err := strconv.ParseUint(s[2:2+n], 16, 8)
727 if err != nil {
728 // shouldn't really happen...
729 out = append(out, s[:2+n]...)
730 } else {
731 out = append(out, byte(c))
732 }
733 s = s[2+n:]
734 }
735 } else if s[1] >= '0' && s[1] <= '7' {
736 n := 1 + matchPrefix(s[2:], 2, isOctal)
737 c, err := strconv.ParseUint(s[1:1+n], 8, 8)
738 if err != nil || c > 0xff {
739 out = append(out, s[:1+n]...)
740 } else {
741 out = append(out, byte(c))
742 }
743 s = s[1+n:]
744 } else if s[1] == 'u' {
745 if len(s) < 6 {
746 // bad escape
747 out = append(out, s...)
748 s = s[len(s):]
749 } else {
750 c, err := strconv.ParseUint(s[2:6], 16, 16)
751 if err != nil {
752 // bad escape
753 out = append(out, s[:6]...)
754 } else {
755 w := utf8.EncodeRune(buf[:], rune(c))
756 out = append(out, buf[:w]...)
757 }
758 s = s[6:]
759 }
760 } else if s[1] == 'U' {
761 if len(s) < 10 {
762 // bad escape
763 out = append(out, s...)
764 s = s[len(s):]
765 } else {
766 c, err := strconv.ParseUint(s[2:10], 16, 32)
767 if err != nil || c > 0x10ffff {
768 // bad escape
769 out = append(out, s[:10]...)
770 } else {
771 w := utf8.EncodeRune(buf[:], rune(c))
772 out = append(out, buf[:w]...)
773 }
774 s = s[10:]
775 }
776 } else {
777 switch s[1] {
778 case 'a':
779 out = append(out, '\a')
780 case 'b':
781 out = append(out, '\b')
782 case 'f':
783 out = append(out, '\f')
784 case 'n':
785 out = append(out, '\n')
786 case 'r':
787 out = append(out, '\r')
788 case 't':
789 out = append(out, '\t')
790 case 'v':
791 out = append(out, '\v')
792 case '\\':
793 out = append(out, '\\')
794 case '\'':
795 out = append(out, '\'')
796 case '"':
797 out = append(out, '"')
798 case '?':
799 out = append(out, '?')
800 default:
801 // invalid escape, just copy it as-is
802 out = append(out, s[:2]...)
803 }
804 s = s[2:]
805 }
806 }
807 return string(out)
808}
809
810func isOctal(b byte) bool { return b >= '0' && b <= '7' }
811func isHex(b byte) bool {
812 return (b >= '0' && b <= '9') || (b >= 'a' && b <= 'f') || (b >= 'A' && b <= 'F')
813}
814func matchPrefix(s string, limit int, fn func(byte) bool) int {
815 l := len(s)
816 if l > limit {
817 l = limit
818 }
819 i := 0
820 for ; i < l; i++ {
821 if !fn(s[i]) {
822 return i
823 }
824 }
825 return i
826}
827
828// GetName returns the name of the field.
829func (fd *FieldDescriptor) GetName() string {
830 return fd.proto.GetName()
831}
832
833// GetNumber returns the tag number of this field.
834func (fd *FieldDescriptor) GetNumber() int32 {
835 return fd.proto.GetNumber()
836}
837
838// GetFullyQualifiedName returns the fully qualified name of the field. Unlike
839// GetName, this includes fully qualified name of the enclosing message for
840// regular fields.
841//
842// For extension fields, this includes the package (if there is one) as well as
843// any enclosing messages. The package and/or enclosing messages are for where
844// the extension is defined, not the message it extends.
845//
846// If this field is part of a one-of, the fully qualified name does *not*
847// include the name of the one-of, only of the enclosing message.
848func (fd *FieldDescriptor) GetFullyQualifiedName() string {
849 return fd.fqn
850}
851
852// GetParent returns the fields's enclosing descriptor. For normal
853// (non-extension) fields, this is the enclosing message. For extensions, this
854// is the descriptor in which the extension is defined, not the message that is
855// extended. The parent for an extension may be a file descriptor or a message,
856// depending on where the extension is defined.
857func (fd *FieldDescriptor) GetParent() Descriptor {
858 return fd.parent
859}
860
861// GetFile returns the descriptor for the file in which this field is defined.
862func (fd *FieldDescriptor) GetFile() *FileDescriptor {
863 return fd.file
864}
865
866// GetOptions returns the field's options. Most usages will be more interested
867// in GetFieldOptions, which has a concrete return type. This generic version
868// is present to satisfy the Descriptor interface.
869func (fd *FieldDescriptor) GetOptions() proto.Message {
870 return fd.proto.GetOptions()
871}
872
873// GetFieldOptions returns the field's options.
874func (fd *FieldDescriptor) GetFieldOptions() *dpb.FieldOptions {
875 return fd.proto.GetOptions()
876}
877
878// GetSourceInfo returns source info for the field, if present in the
879// descriptor. Not all descriptors will contain source info. If non-nil, the
880// returned info contains information about the location in the file where the
881// field was defined and also contains comments associated with the field
882// definition.
883func (fd *FieldDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
884 return fd.file.sourceInfo.Get(fd.sourceInfoPath)
885}
886
887// AsProto returns the underlying descriptor proto. Most usages will be more
888// interested in AsFieldDescriptorProto, which has a concrete return type. This
889// generic version is present to satisfy the Descriptor interface.
890func (fd *FieldDescriptor) AsProto() proto.Message {
891 return fd.proto
892}
893
894// AsFieldDescriptorProto returns the underlying descriptor proto.
895func (fd *FieldDescriptor) AsFieldDescriptorProto() *dpb.FieldDescriptorProto {
896 return fd.proto
897}
898
899// String returns the underlying descriptor proto, in compact text format.
900func (fd *FieldDescriptor) String() string {
901 return fd.proto.String()
902}
903
904// GetJSONName returns the name of the field as referenced in the message's JSON
905// format.
906func (fd *FieldDescriptor) GetJSONName() string {
907 if jsonName := fd.proto.JsonName; jsonName != nil {
908 // if json name is present, use its value
909 return *jsonName
910 }
911 // otherwise, compute the proper JSON name from the field name
912 return jsonCamelCase(fd.proto.GetName())
913}
914
915func jsonCamelCase(s string) string {
916 // This mirrors the implementation in protoc/C++ runtime and in the Java runtime:
917 // https://github.com/protocolbuffers/protobuf/blob/a104dffcb6b1958a424f5fa6f9e6bdc0ab9b6f9e/src/google/protobuf/descriptor.cc#L276
918 // https://github.com/protocolbuffers/protobuf/blob/a1c886834425abb64a966231dd2c9dd84fb289b3/java/core/src/main/java/com/google/protobuf/Descriptors.java#L1286
919 var buf bytes.Buffer
920 prevWasUnderscore := false
921 for _, r := range s {
922 if r == '_' {
923 prevWasUnderscore = true
924 continue
925 }
926 if prevWasUnderscore {
927 r = unicode.ToUpper(r)
928 prevWasUnderscore = false
929 }
930 buf.WriteRune(r)
931 }
932 return buf.String()
933}
934
935// GetFullyQualifiedJSONName returns the JSON format name (same as GetJSONName),
936// but includes the fully qualified name of the enclosing message.
937//
938// If the field is an extension, it will return the package name (if there is
939// one) as well as the names of any enclosing messages. The package and/or
940// enclosing messages are for where the extension is defined, not the message it
941// extends.
942func (fd *FieldDescriptor) GetFullyQualifiedJSONName() string {
943 parent := fd.GetParent()
944 switch parent := parent.(type) {
945 case *FileDescriptor:
946 pkg := parent.GetPackage()
947 if pkg == "" {
948 return fd.GetJSONName()
949 }
950 return fmt.Sprintf("%s.%s", pkg, fd.GetJSONName())
951 default:
952 return fmt.Sprintf("%s.%s", parent.GetFullyQualifiedName(), fd.GetJSONName())
953 }
954}
955
956// GetOwner returns the message type that this field belongs to. If this is a normal
957// field then this is the same as GetParent. But for extensions, this will be the
958// extendee message whereas GetParent refers to where the extension was declared.
959func (fd *FieldDescriptor) GetOwner() *MessageDescriptor {
960 return fd.owner
961}
962
963// IsExtension returns true if this is an extension field.
964func (fd *FieldDescriptor) IsExtension() bool {
965 return fd.proto.GetExtendee() != ""
966}
967
968// GetOneOf returns the one-of field set to which this field belongs. If this field
969// is not part of a one-of then this method returns nil.
970func (fd *FieldDescriptor) GetOneOf() *OneOfDescriptor {
971 return fd.oneOf
972}
973
974// GetType returns the type of this field. If the type indicates an enum, the
975// enum type can be queried via GetEnumType. If the type indicates a message, the
976// message type can be queried via GetMessageType.
977func (fd *FieldDescriptor) GetType() dpb.FieldDescriptorProto_Type {
978 return fd.proto.GetType()
979}
980
981// GetLabel returns the label for this field. The label can be required (proto2-only),
982// optional (default for proto3), or required.
983func (fd *FieldDescriptor) GetLabel() dpb.FieldDescriptorProto_Label {
984 return fd.proto.GetLabel()
985}
986
987// IsRequired returns true if this field has the "required" label.
988func (fd *FieldDescriptor) IsRequired() bool {
989 return fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REQUIRED
990}
991
992// IsRepeated returns true if this field has the "repeated" label.
993func (fd *FieldDescriptor) IsRepeated() bool {
994 return fd.proto.GetLabel() == dpb.FieldDescriptorProto_LABEL_REPEATED
995}
996
997// IsProto3Optional returns true if this field has an explicit "optional" label
998// and is in a "proto3" syntax file. Such fields, if they are normal fields (not
999// extensions), will be nested in synthetic oneofs that contain only the single
1000// field.
1001func (fd *FieldDescriptor) IsProto3Optional() bool {
1002 return internal.GetProto3Optional(fd.proto)
1003}
1004
1005// HasPresence returns true if this field can distinguish when a value is
1006// present or not. Scalar fields in "proto3" syntax files, for example, return
1007// false since absent values are indistinguishable from zero values.
1008func (fd *FieldDescriptor) HasPresence() bool {
1009 if !fd.file.isProto3 {
1010 return true
1011 }
1012 return fd.msgType != nil || fd.oneOf != nil
1013}
1014
1015// IsMap returns true if this is a map field. If so, it will have the "repeated"
1016// label its type will be a message that represents a map entry. The map entry
1017// message will have exactly two fields: tag #1 is the key and tag #2 is the value.
1018func (fd *FieldDescriptor) IsMap() bool {
1019 return fd.isMap
1020}
1021
1022// GetMapKeyType returns the type of the key field if this is a map field. If it is
1023// not a map field, nil is returned.
1024func (fd *FieldDescriptor) GetMapKeyType() *FieldDescriptor {
1025 if fd.isMap {
1026 return fd.msgType.FindFieldByNumber(int32(1))
1027 }
1028 return nil
1029}
1030
1031// GetMapValueType returns the type of the value field if this is a map field. If it
1032// is not a map field, nil is returned.
1033func (fd *FieldDescriptor) GetMapValueType() *FieldDescriptor {
1034 if fd.isMap {
1035 return fd.msgType.FindFieldByNumber(int32(2))
1036 }
1037 return nil
1038}
1039
1040// GetMessageType returns the type of this field if it is a message type. If
1041// this field is not a message type, it returns nil.
1042func (fd *FieldDescriptor) GetMessageType() *MessageDescriptor {
1043 return fd.msgType
1044}
1045
1046// GetEnumType returns the type of this field if it is an enum type. If this
1047// field is not an enum type, it returns nil.
1048func (fd *FieldDescriptor) GetEnumType() *EnumDescriptor {
1049 return fd.enumType
1050}
1051
1052// GetDefaultValue returns the default value for this field.
1053//
1054// If this field represents a message type, this method always returns nil (even though
1055// for proto2 files, the default value should be a default instance of the message type).
1056// If the field represents an enum type, this method returns an int32 corresponding to the
1057// enum value. If this field is a map, it returns a nil map[interface{}]interface{}. If
1058// this field is repeated (and not a map), it returns a nil []interface{}.
1059//
1060// Otherwise, it returns the declared default value for the field or a zero value, if no
1061// default is declared or if the file is proto3. The type of said return value corresponds
1062// to the type of the field:
1063// +-------------------------+-----------+
1064// | Declared Type | Go Type |
1065// +-------------------------+-----------+
1066// | int32, sint32, sfixed32 | int32 |
1067// | int64, sint64, sfixed64 | int64 |
1068// | uint32, fixed32 | uint32 |
1069// | uint64, fixed64 | uint64 |
1070// | float | float32 |
1071// | double | double32 |
1072// | bool | bool |
1073// | string | string |
1074// | bytes | []byte |
1075// +-------------------------+-----------+
1076func (fd *FieldDescriptor) GetDefaultValue() interface{} {
1077 return fd.getDefaultValue()
1078}
1079
1080// EnumDescriptor describes an enum declared in a proto file.
1081type EnumDescriptor struct {
1082 proto *dpb.EnumDescriptorProto
1083 parent Descriptor
1084 file *FileDescriptor
1085 values []*EnumValueDescriptor
1086 valuesByNum sortedValues
1087 fqn string
1088 sourceInfoPath []int32
1089}
1090
1091func createEnumDescriptor(fd *FileDescriptor, parent Descriptor, enclosing string, ed *dpb.EnumDescriptorProto, symbols map[string]Descriptor) (*EnumDescriptor, string) {
1092 enumName := merge(enclosing, ed.GetName())
1093 ret := &EnumDescriptor{proto: ed, parent: parent, file: fd, fqn: enumName}
1094 for _, ev := range ed.GetValue() {
1095 evd, n := createEnumValueDescriptor(fd, ret, enumName, ev)
1096 symbols[n] = evd
1097 ret.values = append(ret.values, evd)
1098 }
1099 if len(ret.values) > 0 {
1100 ret.valuesByNum = make(sortedValues, len(ret.values))
1101 copy(ret.valuesByNum, ret.values)
1102 sort.Stable(ret.valuesByNum)
1103 }
1104 return ret, enumName
1105}
1106
1107type sortedValues []*EnumValueDescriptor
1108
1109func (sv sortedValues) Len() int {
1110 return len(sv)
1111}
1112
1113func (sv sortedValues) Less(i, j int) bool {
1114 return sv[i].GetNumber() < sv[j].GetNumber()
1115}
1116
1117func (sv sortedValues) Swap(i, j int) {
1118 sv[i], sv[j] = sv[j], sv[i]
1119}
1120
1121func (ed *EnumDescriptor) resolve(path []int32) {
1122 ed.sourceInfoPath = append([]int32(nil), path...) // defensive copy
1123 path = append(path, internal.Enum_valuesTag)
1124 for i, evd := range ed.values {
1125 evd.resolve(append(path, int32(i)))
1126 }
1127}
1128
1129// GetName returns the simple (unqualified) name of the enum type.
1130func (ed *EnumDescriptor) GetName() string {
1131 return ed.proto.GetName()
1132}
1133
1134// GetFullyQualifiedName returns the fully qualified name of the enum type.
1135// This includes the package name (if there is one) as well as the names of any
1136// enclosing messages.
1137func (ed *EnumDescriptor) GetFullyQualifiedName() string {
1138 return ed.fqn
1139}
1140
1141// GetParent returns the enum type's enclosing descriptor. For top-level enums,
1142// this will be a file descriptor. Otherwise it will be the descriptor for the
1143// enclosing message.
1144func (ed *EnumDescriptor) GetParent() Descriptor {
1145 return ed.parent
1146}
1147
1148// GetFile returns the descriptor for the file in which this enum is defined.
1149func (ed *EnumDescriptor) GetFile() *FileDescriptor {
1150 return ed.file
1151}
1152
1153// GetOptions returns the enum type's options. Most usages will be more
1154// interested in GetEnumOptions, which has a concrete return type. This generic
1155// version is present to satisfy the Descriptor interface.
1156func (ed *EnumDescriptor) GetOptions() proto.Message {
1157 return ed.proto.GetOptions()
1158}
1159
1160// GetEnumOptions returns the enum type's options.
1161func (ed *EnumDescriptor) GetEnumOptions() *dpb.EnumOptions {
1162 return ed.proto.GetOptions()
1163}
1164
1165// GetSourceInfo returns source info for the enum type, if present in the
1166// descriptor. Not all descriptors will contain source info. If non-nil, the
1167// returned info contains information about the location in the file where the
1168// enum type was defined and also contains comments associated with the enum
1169// definition.
1170func (ed *EnumDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
1171 return ed.file.sourceInfo.Get(ed.sourceInfoPath)
1172}
1173
1174// AsProto returns the underlying descriptor proto. Most usages will be more
1175// interested in AsEnumDescriptorProto, which has a concrete return type. This
1176// generic version is present to satisfy the Descriptor interface.
1177func (ed *EnumDescriptor) AsProto() proto.Message {
1178 return ed.proto
1179}
1180
1181// AsEnumDescriptorProto returns the underlying descriptor proto.
1182func (ed *EnumDescriptor) AsEnumDescriptorProto() *dpb.EnumDescriptorProto {
1183 return ed.proto
1184}
1185
1186// String returns the underlying descriptor proto, in compact text format.
1187func (ed *EnumDescriptor) String() string {
1188 return ed.proto.String()
1189}
1190
1191// GetValues returns all of the allowed values defined for this enum.
1192func (ed *EnumDescriptor) GetValues() []*EnumValueDescriptor {
1193 return ed.values
1194}
1195
1196// FindValueByName finds the enum value with the given name. If no such value exists
1197// then nil is returned.
1198func (ed *EnumDescriptor) FindValueByName(name string) *EnumValueDescriptor {
1199 fqn := fmt.Sprintf("%s.%s", ed.fqn, name)
1200 if vd, ok := ed.file.symbols[fqn].(*EnumValueDescriptor); ok {
1201 return vd
1202 } else {
1203 return nil
1204 }
1205}
1206
1207// FindValueByNumber finds the value with the given numeric value. If no such value
1208// exists then nil is returned. If aliases are allowed and multiple values have the
1209// given number, the first declared value is returned.
1210func (ed *EnumDescriptor) FindValueByNumber(num int32) *EnumValueDescriptor {
1211 index := sort.Search(len(ed.valuesByNum), func(i int) bool { return ed.valuesByNum[i].GetNumber() >= num })
1212 if index < len(ed.valuesByNum) {
1213 vd := ed.valuesByNum[index]
1214 if vd.GetNumber() == num {
1215 return vd
1216 }
1217 }
1218 return nil
1219}
1220
1221// EnumValueDescriptor describes an allowed value of an enum declared in a proto file.
1222type EnumValueDescriptor struct {
1223 proto *dpb.EnumValueDescriptorProto
1224 parent *EnumDescriptor
1225 file *FileDescriptor
1226 fqn string
1227 sourceInfoPath []int32
1228}
1229
1230func createEnumValueDescriptor(fd *FileDescriptor, parent *EnumDescriptor, enclosing string, evd *dpb.EnumValueDescriptorProto) (*EnumValueDescriptor, string) {
1231 valName := merge(enclosing, evd.GetName())
1232 return &EnumValueDescriptor{proto: evd, parent: parent, file: fd, fqn: valName}, valName
1233}
1234
1235func (vd *EnumValueDescriptor) resolve(path []int32) {
1236 vd.sourceInfoPath = append([]int32(nil), path...) // defensive copy
1237}
1238
1239// GetName returns the name of the enum value.
1240func (vd *EnumValueDescriptor) GetName() string {
1241 return vd.proto.GetName()
1242}
1243
1244// GetNumber returns the numeric value associated with this enum value.
1245func (vd *EnumValueDescriptor) GetNumber() int32 {
1246 return vd.proto.GetNumber()
1247}
1248
1249// GetFullyQualifiedName returns the fully qualified name of the enum value.
1250// Unlike GetName, this includes fully qualified name of the enclosing enum.
1251func (vd *EnumValueDescriptor) GetFullyQualifiedName() string {
1252 return vd.fqn
1253}
1254
1255// GetParent returns the descriptor for the enum in which this enum value is
1256// defined. Most usages will prefer to use GetEnum, which has a concrete return
1257// type. This more generic method is present to satisfy the Descriptor interface.
1258func (vd *EnumValueDescriptor) GetParent() Descriptor {
1259 return vd.parent
1260}
1261
1262// GetEnum returns the enum in which this enum value is defined.
1263func (vd *EnumValueDescriptor) GetEnum() *EnumDescriptor {
1264 return vd.parent
1265}
1266
1267// GetFile returns the descriptor for the file in which this enum value is
1268// defined.
1269func (vd *EnumValueDescriptor) GetFile() *FileDescriptor {
1270 return vd.file
1271}
1272
1273// GetOptions returns the enum value's options. Most usages will be more
1274// interested in GetEnumValueOptions, which has a concrete return type. This
1275// generic version is present to satisfy the Descriptor interface.
1276func (vd *EnumValueDescriptor) GetOptions() proto.Message {
1277 return vd.proto.GetOptions()
1278}
1279
1280// GetEnumValueOptions returns the enum value's options.
1281func (vd *EnumValueDescriptor) GetEnumValueOptions() *dpb.EnumValueOptions {
1282 return vd.proto.GetOptions()
1283}
1284
1285// GetSourceInfo returns source info for the enum value, if present in the
1286// descriptor. Not all descriptors will contain source info. If non-nil, the
1287// returned info contains information about the location in the file where the
1288// enum value was defined and also contains comments associated with the enum
1289// value definition.
1290func (vd *EnumValueDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
1291 return vd.file.sourceInfo.Get(vd.sourceInfoPath)
1292}
1293
1294// AsProto returns the underlying descriptor proto. Most usages will be more
1295// interested in AsEnumValueDescriptorProto, which has a concrete return type.
1296// This generic version is present to satisfy the Descriptor interface.
1297func (vd *EnumValueDescriptor) AsProto() proto.Message {
1298 return vd.proto
1299}
1300
1301// AsEnumValueDescriptorProto returns the underlying descriptor proto.
1302func (vd *EnumValueDescriptor) AsEnumValueDescriptorProto() *dpb.EnumValueDescriptorProto {
1303 return vd.proto
1304}
1305
1306// String returns the underlying descriptor proto, in compact text format.
1307func (vd *EnumValueDescriptor) String() string {
1308 return vd.proto.String()
1309}
1310
1311// ServiceDescriptor describes an RPC service declared in a proto file.
1312type ServiceDescriptor struct {
1313 proto *dpb.ServiceDescriptorProto
1314 file *FileDescriptor
1315 methods []*MethodDescriptor
1316 fqn string
1317 sourceInfoPath []int32
1318}
1319
1320func createServiceDescriptor(fd *FileDescriptor, enclosing string, sd *dpb.ServiceDescriptorProto, symbols map[string]Descriptor) (*ServiceDescriptor, string) {
1321 serviceName := merge(enclosing, sd.GetName())
1322 ret := &ServiceDescriptor{proto: sd, file: fd, fqn: serviceName}
1323 for _, m := range sd.GetMethod() {
1324 md, n := createMethodDescriptor(fd, ret, serviceName, m)
1325 symbols[n] = md
1326 ret.methods = append(ret.methods, md)
1327 }
1328 return ret, serviceName
1329}
1330
1331func (sd *ServiceDescriptor) resolve(path []int32, scopes []scope) error {
1332 sd.sourceInfoPath = append([]int32(nil), path...) // defensive copy
1333 path = append(path, internal.Service_methodsTag)
1334 for i, md := range sd.methods {
1335 if err := md.resolve(append(path, int32(i)), scopes); err != nil {
1336 return err
1337 }
1338 }
1339 return nil
1340}
1341
1342// GetName returns the simple (unqualified) name of the service.
1343func (sd *ServiceDescriptor) GetName() string {
1344 return sd.proto.GetName()
1345}
1346
1347// GetFullyQualifiedName returns the fully qualified name of the service. This
1348// includes the package name (if there is one).
1349func (sd *ServiceDescriptor) GetFullyQualifiedName() string {
1350 return sd.fqn
1351}
1352
1353// GetParent returns the descriptor for the file in which this service is
1354// defined. Most usages will prefer to use GetFile, which has a concrete return
1355// type. This more generic method is present to satisfy the Descriptor interface.
1356func (sd *ServiceDescriptor) GetParent() Descriptor {
1357 return sd.file
1358}
1359
1360// GetFile returns the descriptor for the file in which this service is defined.
1361func (sd *ServiceDescriptor) GetFile() *FileDescriptor {
1362 return sd.file
1363}
1364
1365// GetOptions returns the service's options. Most usages will be more interested
1366// in GetServiceOptions, which has a concrete return type. This generic version
1367// is present to satisfy the Descriptor interface.
1368func (sd *ServiceDescriptor) GetOptions() proto.Message {
1369 return sd.proto.GetOptions()
1370}
1371
1372// GetServiceOptions returns the service's options.
1373func (sd *ServiceDescriptor) GetServiceOptions() *dpb.ServiceOptions {
1374 return sd.proto.GetOptions()
1375}
1376
1377// GetSourceInfo returns source info for the service, if present in the
1378// descriptor. Not all descriptors will contain source info. If non-nil, the
1379// returned info contains information about the location in the file where the
1380// service was defined and also contains comments associated with the service
1381// definition.
1382func (sd *ServiceDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
1383 return sd.file.sourceInfo.Get(sd.sourceInfoPath)
1384}
1385
1386// AsProto returns the underlying descriptor proto. Most usages will be more
1387// interested in AsServiceDescriptorProto, which has a concrete return type.
1388// This generic version is present to satisfy the Descriptor interface.
1389func (sd *ServiceDescriptor) AsProto() proto.Message {
1390 return sd.proto
1391}
1392
1393// AsServiceDescriptorProto returns the underlying descriptor proto.
1394func (sd *ServiceDescriptor) AsServiceDescriptorProto() *dpb.ServiceDescriptorProto {
1395 return sd.proto
1396}
1397
1398// String returns the underlying descriptor proto, in compact text format.
1399func (sd *ServiceDescriptor) String() string {
1400 return sd.proto.String()
1401}
1402
1403// GetMethods returns all of the RPC methods for this service.
1404func (sd *ServiceDescriptor) GetMethods() []*MethodDescriptor {
1405 return sd.methods
1406}
1407
1408// FindMethodByName finds the method with the given name. If no such method exists
1409// then nil is returned.
1410func (sd *ServiceDescriptor) FindMethodByName(name string) *MethodDescriptor {
1411 fqn := fmt.Sprintf("%s.%s", sd.fqn, name)
1412 if md, ok := sd.file.symbols[fqn].(*MethodDescriptor); ok {
1413 return md
1414 } else {
1415 return nil
1416 }
1417}
1418
1419// MethodDescriptor describes an RPC method declared in a proto file.
1420type MethodDescriptor struct {
1421 proto *dpb.MethodDescriptorProto
1422 parent *ServiceDescriptor
1423 file *FileDescriptor
1424 inType *MessageDescriptor
1425 outType *MessageDescriptor
1426 fqn string
1427 sourceInfoPath []int32
1428}
1429
1430func createMethodDescriptor(fd *FileDescriptor, parent *ServiceDescriptor, enclosing string, md *dpb.MethodDescriptorProto) (*MethodDescriptor, string) {
1431 // request and response types get resolved later
1432 methodName := merge(enclosing, md.GetName())
1433 return &MethodDescriptor{proto: md, parent: parent, file: fd, fqn: methodName}, methodName
1434}
1435
1436func (md *MethodDescriptor) resolve(path []int32, scopes []scope) error {
1437 md.sourceInfoPath = append([]int32(nil), path...) // defensive copy
1438 if desc, err := resolve(md.file, md.proto.GetInputType(), scopes); err != nil {
1439 return err
1440 } else {
1441 md.inType = desc.(*MessageDescriptor)
1442 }
1443 if desc, err := resolve(md.file, md.proto.GetOutputType(), scopes); err != nil {
1444 return err
1445 } else {
1446 md.outType = desc.(*MessageDescriptor)
1447 }
1448 return nil
1449}
1450
1451// GetName returns the name of the method.
1452func (md *MethodDescriptor) GetName() string {
1453 return md.proto.GetName()
1454}
1455
1456// GetFullyQualifiedName returns the fully qualified name of the method. Unlike
1457// GetName, this includes fully qualified name of the enclosing service.
1458func (md *MethodDescriptor) GetFullyQualifiedName() string {
1459 return md.fqn
1460}
1461
1462// GetParent returns the descriptor for the service in which this method is
1463// defined. Most usages will prefer to use GetService, which has a concrete
1464// return type. This more generic method is present to satisfy the Descriptor
1465// interface.
1466func (md *MethodDescriptor) GetParent() Descriptor {
1467 return md.parent
1468}
1469
1470// GetService returns the RPC service in which this method is declared.
1471func (md *MethodDescriptor) GetService() *ServiceDescriptor {
1472 return md.parent
1473}
1474
1475// GetFile returns the descriptor for the file in which this method is defined.
1476func (md *MethodDescriptor) GetFile() *FileDescriptor {
1477 return md.file
1478}
1479
1480// GetOptions returns the method's options. Most usages will be more interested
1481// in GetMethodOptions, which has a concrete return type. This generic version
1482// is present to satisfy the Descriptor interface.
1483func (md *MethodDescriptor) GetOptions() proto.Message {
1484 return md.proto.GetOptions()
1485}
1486
1487// GetMethodOptions returns the method's options.
1488func (md *MethodDescriptor) GetMethodOptions() *dpb.MethodOptions {
1489 return md.proto.GetOptions()
1490}
1491
1492// GetSourceInfo returns source info for the method, if present in the
1493// descriptor. Not all descriptors will contain source info. If non-nil, the
1494// returned info contains information about the location in the file where the
1495// method was defined and also contains comments associated with the method
1496// definition.
1497func (md *MethodDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
1498 return md.file.sourceInfo.Get(md.sourceInfoPath)
1499}
1500
1501// AsProto returns the underlying descriptor proto. Most usages will be more
1502// interested in AsMethodDescriptorProto, which has a concrete return type. This
1503// generic version is present to satisfy the Descriptor interface.
1504func (md *MethodDescriptor) AsProto() proto.Message {
1505 return md.proto
1506}
1507
1508// AsMethodDescriptorProto returns the underlying descriptor proto.
1509func (md *MethodDescriptor) AsMethodDescriptorProto() *dpb.MethodDescriptorProto {
1510 return md.proto
1511}
1512
1513// String returns the underlying descriptor proto, in compact text format.
1514func (md *MethodDescriptor) String() string {
1515 return md.proto.String()
1516}
1517
1518// IsServerStreaming returns true if this is a server-streaming method.
1519func (md *MethodDescriptor) IsServerStreaming() bool {
1520 return md.proto.GetServerStreaming()
1521}
1522
1523// IsClientStreaming returns true if this is a client-streaming method.
1524func (md *MethodDescriptor) IsClientStreaming() bool {
1525 return md.proto.GetClientStreaming()
1526}
1527
1528// GetInputType returns the input type, or request type, of the RPC method.
1529func (md *MethodDescriptor) GetInputType() *MessageDescriptor {
1530 return md.inType
1531}
1532
1533// GetOutputType returns the output type, or response type, of the RPC method.
1534func (md *MethodDescriptor) GetOutputType() *MessageDescriptor {
1535 return md.outType
1536}
1537
1538// OneOfDescriptor describes a one-of field set declared in a protocol buffer message.
1539type OneOfDescriptor struct {
1540 proto *dpb.OneofDescriptorProto
1541 parent *MessageDescriptor
1542 file *FileDescriptor
1543 choices []*FieldDescriptor
1544 fqn string
1545 sourceInfoPath []int32
1546}
1547
1548func createOneOfDescriptor(fd *FileDescriptor, parent *MessageDescriptor, index int, enclosing string, od *dpb.OneofDescriptorProto) (*OneOfDescriptor, string) {
1549 oneOfName := merge(enclosing, od.GetName())
1550 ret := &OneOfDescriptor{proto: od, parent: parent, file: fd, fqn: oneOfName}
1551 for _, f := range parent.fields {
1552 oi := f.proto.OneofIndex
1553 if oi != nil && *oi == int32(index) {
1554 f.oneOf = ret
1555 ret.choices = append(ret.choices, f)
1556 }
1557 }
1558 return ret, oneOfName
1559}
1560
1561func (od *OneOfDescriptor) resolve(path []int32) {
1562 od.sourceInfoPath = append([]int32(nil), path...) // defensive copy
1563}
1564
1565// GetName returns the name of the one-of.
1566func (od *OneOfDescriptor) GetName() string {
1567 return od.proto.GetName()
1568}
1569
1570// GetFullyQualifiedName returns the fully qualified name of the one-of. Unlike
1571// GetName, this includes fully qualified name of the enclosing message.
1572func (od *OneOfDescriptor) GetFullyQualifiedName() string {
1573 return od.fqn
1574}
1575
1576// GetParent returns the descriptor for the message in which this one-of is
1577// defined. Most usages will prefer to use GetOwner, which has a concrete
1578// return type. This more generic method is present to satisfy the Descriptor
1579// interface.
1580func (od *OneOfDescriptor) GetParent() Descriptor {
1581 return od.parent
1582}
1583
1584// GetOwner returns the message to which this one-of field set belongs.
1585func (od *OneOfDescriptor) GetOwner() *MessageDescriptor {
1586 return od.parent
1587}
1588
1589// GetFile returns the descriptor for the file in which this one-fof is defined.
1590func (od *OneOfDescriptor) GetFile() *FileDescriptor {
1591 return od.file
1592}
1593
1594// GetOptions returns the one-of's options. Most usages will be more interested
1595// in GetOneOfOptions, which has a concrete return type. This generic version
1596// is present to satisfy the Descriptor interface.
1597func (od *OneOfDescriptor) GetOptions() proto.Message {
1598 return od.proto.GetOptions()
1599}
1600
1601// GetOneOfOptions returns the one-of's options.
1602func (od *OneOfDescriptor) GetOneOfOptions() *dpb.OneofOptions {
1603 return od.proto.GetOptions()
1604}
1605
1606// GetSourceInfo returns source info for the one-of, if present in the
1607// descriptor. Not all descriptors will contain source info. If non-nil, the
1608// returned info contains information about the location in the file where the
1609// one-of was defined and also contains comments associated with the one-of
1610// definition.
1611func (od *OneOfDescriptor) GetSourceInfo() *dpb.SourceCodeInfo_Location {
1612 return od.file.sourceInfo.Get(od.sourceInfoPath)
1613}
1614
1615// AsProto returns the underlying descriptor proto. Most usages will be more
1616// interested in AsOneofDescriptorProto, which has a concrete return type. This
1617// generic version is present to satisfy the Descriptor interface.
1618func (od *OneOfDescriptor) AsProto() proto.Message {
1619 return od.proto
1620}
1621
1622// AsOneofDescriptorProto returns the underlying descriptor proto.
1623func (od *OneOfDescriptor) AsOneofDescriptorProto() *dpb.OneofDescriptorProto {
1624 return od.proto
1625}
1626
1627// String returns the underlying descriptor proto, in compact text format.
1628func (od *OneOfDescriptor) String() string {
1629 return od.proto.String()
1630}
1631
1632// GetChoices returns the fields that are part of the one-of field set. At most one of
1633// these fields may be set for a given message.
1634func (od *OneOfDescriptor) GetChoices() []*FieldDescriptor {
1635 return od.choices
1636}
1637
1638func (od *OneOfDescriptor) IsSynthetic() bool {
1639 return len(od.choices) == 1 && od.choices[0].IsProto3Optional()
1640}
1641
1642// scope represents a lexical scope in a proto file in which messages and enums
1643// can be declared.
1644type scope func(string) Descriptor
1645
1646func fileScope(fd *FileDescriptor) scope {
1647 // we search symbols in this file, but also symbols in other files that have
1648 // the same package as this file or a "parent" package (in protobuf,
1649 // packages are a hierarchy like C++ namespaces)
1650 prefixes := internal.CreatePrefixList(fd.proto.GetPackage())
1651 return func(name string) Descriptor {
1652 for _, prefix := range prefixes {
1653 n := merge(prefix, name)
1654 d := findSymbol(fd, n, false)
1655 if d != nil {
1656 return d
1657 }
1658 }
1659 return nil
1660 }
1661}
1662
1663func messageScope(md *MessageDescriptor) scope {
1664 return func(name string) Descriptor {
1665 n := merge(md.fqn, name)
1666 if d, ok := md.file.symbols[n]; ok {
1667 return d
1668 }
1669 return nil
1670 }
1671}
1672
1673func resolve(fd *FileDescriptor, name string, scopes []scope) (Descriptor, error) {
1674 if strings.HasPrefix(name, ".") {
1675 // already fully-qualified
1676 d := findSymbol(fd, name[1:], false)
1677 if d != nil {
1678 return d, nil
1679 }
1680 } else {
1681 // unqualified, so we look in the enclosing (last) scope first and move
1682 // towards outermost (first) scope, trying to resolve the symbol
1683 for i := len(scopes) - 1; i >= 0; i-- {
1684 d := scopes[i](name)
1685 if d != nil {
1686 return d, nil
1687 }
1688 }
1689 }
1690 return nil, fmt.Errorf("file %q included an unresolvable reference to %q", fd.proto.GetName(), name)
1691}
1692
1693func findSymbol(fd *FileDescriptor, name string, public bool) Descriptor {
1694 d := fd.symbols[name]
1695 if d != nil {
1696 return d
1697 }
1698
1699 // When public = false, we are searching only directly imported symbols. But we
1700 // also need to search transitive public imports due to semantics of public imports.
1701 var deps []*FileDescriptor
1702 if public {
1703 deps = fd.publicDeps
1704 } else {
1705 deps = fd.deps
1706 }
1707 for _, dep := range deps {
1708 d = findSymbol(dep, name, true)
1709 if d != nil {
1710 return d
1711 }
1712 }
1713
1714 return nil
1715}
1716
1717func merge(a, b string) string {
1718 if a == "" {
1719 return b
1720 } else {
1721 return a + "." + b
1722 }
1723}