You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

249 lines
9.5 KiB

  1. // Copyright 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package protodesc
  5. import (
  6. "google.golang.org/protobuf/internal/errors"
  7. "google.golang.org/protobuf/internal/filedesc"
  8. "google.golang.org/protobuf/internal/strs"
  9. "google.golang.org/protobuf/proto"
  10. "google.golang.org/protobuf/reflect/protoreflect"
  11. "google.golang.org/protobuf/types/descriptorpb"
  12. )
  13. type descsByName map[protoreflect.FullName]protoreflect.Descriptor
  14. func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (es []filedesc.Enum, err error) {
  15. es = make([]filedesc.Enum, len(eds)) // allocate up-front to ensure stable pointers
  16. for i, ed := range eds {
  17. e := &es[i]
  18. e.L2 = new(filedesc.EnumL2)
  19. if e.L0, err = r.makeBase(e, parent, ed.GetName(), i, sb); err != nil {
  20. return nil, err
  21. }
  22. if opts := ed.GetOptions(); opts != nil {
  23. opts = proto.Clone(opts).(*descriptorpb.EnumOptions)
  24. e.L2.Options = func() protoreflect.ProtoMessage { return opts }
  25. }
  26. for _, s := range ed.GetReservedName() {
  27. e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
  28. }
  29. for _, rr := range ed.GetReservedRange() {
  30. e.L2.ReservedRanges.List = append(e.L2.ReservedRanges.List, [2]protoreflect.EnumNumber{
  31. protoreflect.EnumNumber(rr.GetStart()),
  32. protoreflect.EnumNumber(rr.GetEnd()),
  33. })
  34. }
  35. if e.L2.Values.List, err = r.initEnumValuesFromDescriptorProto(ed.GetValue(), e, sb); err != nil {
  36. return nil, err
  37. }
  38. }
  39. return es, nil
  40. }
  41. func (r descsByName) initEnumValuesFromDescriptorProto(vds []*descriptorpb.EnumValueDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (vs []filedesc.EnumValue, err error) {
  42. vs = make([]filedesc.EnumValue, len(vds)) // allocate up-front to ensure stable pointers
  43. for i, vd := range vds {
  44. v := &vs[i]
  45. if v.L0, err = r.makeBase(v, parent, vd.GetName(), i, sb); err != nil {
  46. return nil, err
  47. }
  48. if opts := vd.GetOptions(); opts != nil {
  49. opts = proto.Clone(opts).(*descriptorpb.EnumValueOptions)
  50. v.L1.Options = func() protoreflect.ProtoMessage { return opts }
  51. }
  52. v.L1.Number = protoreflect.EnumNumber(vd.GetNumber())
  53. }
  54. return vs, nil
  55. }
  56. func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Message, err error) {
  57. ms = make([]filedesc.Message, len(mds)) // allocate up-front to ensure stable pointers
  58. for i, md := range mds {
  59. m := &ms[i]
  60. m.L2 = new(filedesc.MessageL2)
  61. if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
  62. return nil, err
  63. }
  64. if opts := md.GetOptions(); opts != nil {
  65. opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
  66. m.L2.Options = func() protoreflect.ProtoMessage { return opts }
  67. m.L1.IsMapEntry = opts.GetMapEntry()
  68. m.L1.IsMessageSet = opts.GetMessageSetWireFormat()
  69. }
  70. for _, s := range md.GetReservedName() {
  71. m.L2.ReservedNames.List = append(m.L2.ReservedNames.List, protoreflect.Name(s))
  72. }
  73. for _, rr := range md.GetReservedRange() {
  74. m.L2.ReservedRanges.List = append(m.L2.ReservedRanges.List, [2]protoreflect.FieldNumber{
  75. protoreflect.FieldNumber(rr.GetStart()),
  76. protoreflect.FieldNumber(rr.GetEnd()),
  77. })
  78. }
  79. for _, xr := range md.GetExtensionRange() {
  80. m.L2.ExtensionRanges.List = append(m.L2.ExtensionRanges.List, [2]protoreflect.FieldNumber{
  81. protoreflect.FieldNumber(xr.GetStart()),
  82. protoreflect.FieldNumber(xr.GetEnd()),
  83. })
  84. var optsFunc func() protoreflect.ProtoMessage
  85. if opts := xr.GetOptions(); opts != nil {
  86. opts = proto.Clone(opts).(*descriptorpb.ExtensionRangeOptions)
  87. optsFunc = func() protoreflect.ProtoMessage { return opts }
  88. }
  89. m.L2.ExtensionRangeOptions = append(m.L2.ExtensionRangeOptions, optsFunc)
  90. }
  91. if m.L2.Fields.List, err = r.initFieldsFromDescriptorProto(md.GetField(), m, sb); err != nil {
  92. return nil, err
  93. }
  94. if m.L2.Oneofs.List, err = r.initOneofsFromDescriptorProto(md.GetOneofDecl(), m, sb); err != nil {
  95. return nil, err
  96. }
  97. if m.L1.Enums.List, err = r.initEnumDeclarations(md.GetEnumType(), m, sb); err != nil {
  98. return nil, err
  99. }
  100. if m.L1.Messages.List, err = r.initMessagesDeclarations(md.GetNestedType(), m, sb); err != nil {
  101. return nil, err
  102. }
  103. if m.L1.Extensions.List, err = r.initExtensionDeclarations(md.GetExtension(), m, sb); err != nil {
  104. return nil, err
  105. }
  106. }
  107. return ms, nil
  108. }
  109. func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) {
  110. fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers
  111. for i, fd := range fds {
  112. f := &fs[i]
  113. if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil {
  114. return nil, err
  115. }
  116. f.L1.IsProto3Optional = fd.GetProto3Optional()
  117. if opts := fd.GetOptions(); opts != nil {
  118. opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
  119. f.L1.Options = func() protoreflect.ProtoMessage { return opts }
  120. f.L1.IsWeak = opts.GetWeak()
  121. f.L1.HasPacked = opts.Packed != nil
  122. f.L1.IsPacked = opts.GetPacked()
  123. }
  124. f.L1.Number = protoreflect.FieldNumber(fd.GetNumber())
  125. f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel())
  126. if fd.Type != nil {
  127. f.L1.Kind = protoreflect.Kind(fd.GetType())
  128. }
  129. if fd.JsonName != nil {
  130. f.L1.StringName.InitJSON(fd.GetJsonName())
  131. }
  132. }
  133. return fs, nil
  134. }
  135. func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (os []filedesc.Oneof, err error) {
  136. os = make([]filedesc.Oneof, len(ods)) // allocate up-front to ensure stable pointers
  137. for i, od := range ods {
  138. o := &os[i]
  139. if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil {
  140. return nil, err
  141. }
  142. if opts := od.GetOptions(); opts != nil {
  143. opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
  144. o.L1.Options = func() protoreflect.ProtoMessage { return opts }
  145. }
  146. }
  147. return os, nil
  148. }
  149. func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (xs []filedesc.Extension, err error) {
  150. xs = make([]filedesc.Extension, len(xds)) // allocate up-front to ensure stable pointers
  151. for i, xd := range xds {
  152. x := &xs[i]
  153. x.L2 = new(filedesc.ExtensionL2)
  154. if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil {
  155. return nil, err
  156. }
  157. if opts := xd.GetOptions(); opts != nil {
  158. opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
  159. x.L2.Options = func() protoreflect.ProtoMessage { return opts }
  160. x.L2.IsPacked = opts.GetPacked()
  161. }
  162. x.L1.Number = protoreflect.FieldNumber(xd.GetNumber())
  163. x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel())
  164. if xd.Type != nil {
  165. x.L1.Kind = protoreflect.Kind(xd.GetType())
  166. }
  167. if xd.JsonName != nil {
  168. x.L2.StringName.InitJSON(xd.GetJsonName())
  169. }
  170. }
  171. return xs, nil
  172. }
  173. func (r descsByName) initServiceDeclarations(sds []*descriptorpb.ServiceDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ss []filedesc.Service, err error) {
  174. ss = make([]filedesc.Service, len(sds)) // allocate up-front to ensure stable pointers
  175. for i, sd := range sds {
  176. s := &ss[i]
  177. s.L2 = new(filedesc.ServiceL2)
  178. if s.L0, err = r.makeBase(s, parent, sd.GetName(), i, sb); err != nil {
  179. return nil, err
  180. }
  181. if opts := sd.GetOptions(); opts != nil {
  182. opts = proto.Clone(opts).(*descriptorpb.ServiceOptions)
  183. s.L2.Options = func() protoreflect.ProtoMessage { return opts }
  184. }
  185. if s.L2.Methods.List, err = r.initMethodsFromDescriptorProto(sd.GetMethod(), s, sb); err != nil {
  186. return nil, err
  187. }
  188. }
  189. return ss, nil
  190. }
  191. func (r descsByName) initMethodsFromDescriptorProto(mds []*descriptorpb.MethodDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Method, err error) {
  192. ms = make([]filedesc.Method, len(mds)) // allocate up-front to ensure stable pointers
  193. for i, md := range mds {
  194. m := &ms[i]
  195. if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
  196. return nil, err
  197. }
  198. if opts := md.GetOptions(); opts != nil {
  199. opts = proto.Clone(opts).(*descriptorpb.MethodOptions)
  200. m.L1.Options = func() protoreflect.ProtoMessage { return opts }
  201. }
  202. m.L1.IsStreamingClient = md.GetClientStreaming()
  203. m.L1.IsStreamingServer = md.GetServerStreaming()
  204. }
  205. return ms, nil
  206. }
  207. func (r descsByName) makeBase(child, parent protoreflect.Descriptor, name string, idx int, sb *strs.Builder) (filedesc.BaseL0, error) {
  208. if !protoreflect.Name(name).IsValid() {
  209. return filedesc.BaseL0{}, errors.New("descriptor %q has an invalid nested name: %q", parent.FullName(), name)
  210. }
  211. // Derive the full name of the child.
  212. // Note that enum values are a sibling to the enum parent in the namespace.
  213. var fullName protoreflect.FullName
  214. if _, ok := parent.(protoreflect.EnumDescriptor); ok {
  215. fullName = sb.AppendFullName(parent.FullName().Parent(), protoreflect.Name(name))
  216. } else {
  217. fullName = sb.AppendFullName(parent.FullName(), protoreflect.Name(name))
  218. }
  219. if _, ok := r[fullName]; ok {
  220. return filedesc.BaseL0{}, errors.New("descriptor %q already declared", fullName)
  221. }
  222. r[fullName] = child
  223. // TODO: Verify that the full name does not already exist in the resolver?
  224. // This is not as critical since most usages of NewFile will register
  225. // the created file back into the registry, which will perform this check.
  226. return filedesc.BaseL0{
  227. FullName: fullName,
  228. ParentFile: parent.ParentFile().(*filedesc.File),
  229. Parent: parent,
  230. Index: idx,
  231. }, nil
  232. }