desc_init.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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. if f.Base.L0.ParentFile.Syntax() == protoreflect.Editions {
  133. f.L1.Presence = resolveFeatureHasFieldPresence(f.Base.L0.ParentFile, fd)
  134. // We reuse the existing field because the old option `[packed =
  135. // true]` is mutually exclusive with the editions feature.
  136. if fd.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REPEATED {
  137. f.L1.HasPacked = true
  138. f.L1.IsPacked = resolveFeatureRepeatedFieldEncodingPacked(f.Base.L0.ParentFile, fd)
  139. }
  140. // We pretend this option is always explicitly set because the only
  141. // use of HasEnforceUTF8 is to determine whether to use EnforceUTF8
  142. // or to return the appropriate default.
  143. // When using editions we either parse the option or resolve the
  144. // appropriate default here (instead of later when this option is
  145. // requested from the descriptor).
  146. // In proto2/proto3 syntax HasEnforceUTF8 might be false.
  147. f.L1.HasEnforceUTF8 = true
  148. f.L1.EnforceUTF8 = resolveFeatureEnforceUTF8(f.Base.L0.ParentFile, fd)
  149. if f.L1.Kind == protoreflect.MessageKind && resolveFeatureDelimitedEncoding(f.Base.L0.ParentFile, fd) {
  150. f.L1.Kind = protoreflect.GroupKind
  151. }
  152. }
  153. }
  154. return fs, nil
  155. }
  156. func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (os []filedesc.Oneof, err error) {
  157. os = make([]filedesc.Oneof, len(ods)) // allocate up-front to ensure stable pointers
  158. for i, od := range ods {
  159. o := &os[i]
  160. if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil {
  161. return nil, err
  162. }
  163. if opts := od.GetOptions(); opts != nil {
  164. opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
  165. o.L1.Options = func() protoreflect.ProtoMessage { return opts }
  166. }
  167. }
  168. return os, nil
  169. }
  170. func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (xs []filedesc.Extension, err error) {
  171. xs = make([]filedesc.Extension, len(xds)) // allocate up-front to ensure stable pointers
  172. for i, xd := range xds {
  173. x := &xs[i]
  174. x.L2 = new(filedesc.ExtensionL2)
  175. if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil {
  176. return nil, err
  177. }
  178. if opts := xd.GetOptions(); opts != nil {
  179. opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
  180. x.L2.Options = func() protoreflect.ProtoMessage { return opts }
  181. x.L2.IsPacked = opts.GetPacked()
  182. }
  183. x.L1.Number = protoreflect.FieldNumber(xd.GetNumber())
  184. x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel())
  185. if xd.Type != nil {
  186. x.L1.Kind = protoreflect.Kind(xd.GetType())
  187. }
  188. if xd.JsonName != nil {
  189. x.L2.StringName.InitJSON(xd.GetJsonName())
  190. }
  191. }
  192. return xs, nil
  193. }
  194. func (r descsByName) initServiceDeclarations(sds []*descriptorpb.ServiceDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ss []filedesc.Service, err error) {
  195. ss = make([]filedesc.Service, len(sds)) // allocate up-front to ensure stable pointers
  196. for i, sd := range sds {
  197. s := &ss[i]
  198. s.L2 = new(filedesc.ServiceL2)
  199. if s.L0, err = r.makeBase(s, parent, sd.GetName(), i, sb); err != nil {
  200. return nil, err
  201. }
  202. if opts := sd.GetOptions(); opts != nil {
  203. opts = proto.Clone(opts).(*descriptorpb.ServiceOptions)
  204. s.L2.Options = func() protoreflect.ProtoMessage { return opts }
  205. }
  206. if s.L2.Methods.List, err = r.initMethodsFromDescriptorProto(sd.GetMethod(), s, sb); err != nil {
  207. return nil, err
  208. }
  209. }
  210. return ss, nil
  211. }
  212. func (r descsByName) initMethodsFromDescriptorProto(mds []*descriptorpb.MethodDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Method, err error) {
  213. ms = make([]filedesc.Method, len(mds)) // allocate up-front to ensure stable pointers
  214. for i, md := range mds {
  215. m := &ms[i]
  216. if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
  217. return nil, err
  218. }
  219. if opts := md.GetOptions(); opts != nil {
  220. opts = proto.Clone(opts).(*descriptorpb.MethodOptions)
  221. m.L1.Options = func() protoreflect.ProtoMessage { return opts }
  222. }
  223. m.L1.IsStreamingClient = md.GetClientStreaming()
  224. m.L1.IsStreamingServer = md.GetServerStreaming()
  225. }
  226. return ms, nil
  227. }
  228. func (r descsByName) makeBase(child, parent protoreflect.Descriptor, name string, idx int, sb *strs.Builder) (filedesc.BaseL0, error) {
  229. if !protoreflect.Name(name).IsValid() {
  230. return filedesc.BaseL0{}, errors.New("descriptor %q has an invalid nested name: %q", parent.FullName(), name)
  231. }
  232. // Derive the full name of the child.
  233. // Note that enum values are a sibling to the enum parent in the namespace.
  234. var fullName protoreflect.FullName
  235. if _, ok := parent.(protoreflect.EnumDescriptor); ok {
  236. fullName = sb.AppendFullName(parent.FullName().Parent(), protoreflect.Name(name))
  237. } else {
  238. fullName = sb.AppendFullName(parent.FullName(), protoreflect.Name(name))
  239. }
  240. if _, ok := r[fullName]; ok {
  241. return filedesc.BaseL0{}, errors.New("descriptor %q already declared", fullName)
  242. }
  243. r[fullName] = child
  244. // TODO: Verify that the full name does not already exist in the resolver?
  245. // This is not as critical since most usages of NewFile will register
  246. // the created file back into the registry, which will perform this check.
  247. return filedesc.BaseL0{
  248. FullName: fullName,
  249. ParentFile: parent.ParentFile().(*filedesc.File),
  250. Parent: parent,
  251. Index: idx,
  252. }, nil
  253. }