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