Descriptor.swift 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469
  1. // Sources/SwiftProtobufPluginLibrary/Descriptor.swift - Descriptor wrappers
  2. //
  3. // Copyright (c) 2014 - 2017 Apple Inc. and the project authors
  4. // Licensed under Apache License v2.0 with Runtime Library Exception
  5. //
  6. // See LICENSE.txt for license information:
  7. // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
  8. //
  9. // -----------------------------------------------------------------------------
  10. ///
  11. /// This is like Descriptor.{h,cc} in the google/protobuf C++ code, it provides
  12. /// wrappers around the protos to make a more usable object graph for generation
  13. /// and also provides some SwiftProtobuf specific additions that would be useful
  14. /// to anyone generating something that uses SwiftProtobufs (like support the
  15. /// `service` messages). It is *not* the intent for these to eventually be used
  16. /// as part of some reflection or generate message api.
  17. ///
  18. /// Unlike the C++ Descriptors, the intent is for these to *only* be used within
  19. /// the context of a protoc plugin, meaning, the
  20. /// `Google_Protobuf_FileDescriptorSet` used to create these will be *always*
  21. /// be well formed by protoc and the guarentees it provides.
  22. ///
  23. // -----------------------------------------------------------------------------
  24. import Foundation
  25. import SwiftProtobuf
  26. /// The front interface for building/getting descriptors. The objects
  27. /// vended from the here are different from the raw
  28. /// `Google_Protobuf_*Proto` types in that they have all the cross object
  29. /// references resolved or wired up, making for an easier to use object
  30. /// model.
  31. ///
  32. /// This is like the `DescriptorPool` class in the C++ protobuf library.
  33. public final class DescriptorSet {
  34. /// The list of `FileDescriptor`s in this set.
  35. public let files: [FileDescriptor]
  36. private let registry = Registry()
  37. // Construct out of a `Google_Protobuf_FileDescriptorSet` likely
  38. // created by protoc.
  39. public convenience init(proto: Google_Protobuf_FileDescriptorSet) {
  40. self.init(protos: proto.file)
  41. }
  42. /// The bundled in `google.protobuf.FeatureSetDefault` that defines what
  43. /// the plugin library can support.
  44. private static let bundledFeatureSetDefaults =
  45. // Decoding the bundle defaults better never fail
  46. try! Google_Protobuf_FeatureSetDefaults(serializedBytes: bundledFeatureSetDefaultBytes)
  47. /// The range of Editions that the library can support.
  48. ///
  49. /// This will limit what edition versions a plugin can claim to support.
  50. public static var bundledEditionsSupport: ClosedRange<Google_Protobuf_Edition> {
  51. return bundledFeatureSetDefaults.minimumEdition...bundledFeatureSetDefaults.maximumEdition
  52. }
  53. /// Construct out of a ordered list of
  54. /// `Google_Protobuf_FileDescriptorProto`s likely created by protoc.
  55. public convenience init(protos: [Google_Protobuf_FileDescriptorProto]) {
  56. self.init(protos: protos,
  57. featureSetDefaults: DescriptorSet.bundledFeatureSetDefaults)
  58. }
  59. /// Construct out of a ordered list of
  60. /// `Google_Protobuf_FileDescriptorProto`s likely created by protoc. Since
  61. /// .proto files can import other .proto files, the imports have to be
  62. /// listed before the things that use them so the graph can be
  63. /// reconstructed.
  64. ///
  65. /// - Parameters:
  66. /// - protos: An ordered list of `Google_Protobuf_FileDescriptorProto`.
  67. /// They must be order such that a file is provided before another file
  68. /// that depends on it.
  69. /// - featureSetDefaults: A `Google_Protobuf_FeatureSetDefaults` that provides
  70. /// the Feature defaults to use when parsing the give File protos.
  71. /// - featureExtensions: A list of Protobuf Extension extensions to
  72. /// `google.protobuf.FeatureSet` that define custom features. If used, the
  73. /// `defaults` should have been parsed with the extensions being
  74. /// supported.
  75. public init(
  76. protos: [Google_Protobuf_FileDescriptorProto],
  77. featureSetDefaults: Google_Protobuf_FeatureSetDefaults,
  78. featureExtensions: [any AnyMessageExtension] = []
  79. ) {
  80. precondition(Self.bundledEditionsSupport.contains(featureSetDefaults.minimumEdition),
  81. "Attempt to use a FeatureSetDefault minimumEdition that isn't supported by the library.")
  82. precondition(Self.bundledEditionsSupport.contains(featureSetDefaults.maximumEdition),
  83. "Attempt to use a FeatureSetDefault maximumEdition that isn't supported by the library.")
  84. // If a protoc is too old ≤v26, it might have `features` instead of `overridable_features` and
  85. // `fixed_features`, try to catch that.
  86. precondition(
  87. nil == featureSetDefaults.defaults.first(where: { !$0.hasOverridableFeatures && !$0.hasFixedFeatures }),
  88. "These FeatureSetDefault don't appear valid, make sure you are using a new enough protoc to generate them. ")
  89. let registry = self.registry
  90. self.files = protos.map {
  91. return FileDescriptor(proto: $0,
  92. featureSetDefaults: featureSetDefaults,
  93. featureExtensions: featureExtensions,
  94. registry: registry)
  95. }
  96. }
  97. /// Lookup a specific file. The names for files are what was captured in
  98. /// the `Google_Protobuf_FileDescriptorProto` when it was created, protoc
  99. /// uses the path name for how the file was found.
  100. ///
  101. /// This is a legacy api since it requires the file to be found or it aborts.
  102. /// Mainly kept for grpc-swift compatibility.
  103. @available(*, deprecated, renamed: "fileDescriptor(named:)")
  104. public func lookupFileDescriptor(protoName name: String) -> FileDescriptor {
  105. return registry.fileDescriptor(named: name)!
  106. }
  107. /// Find a specific file. The names for files are what was captured in
  108. /// the `Google_Protobuf_FileDescriptorProto` when it was created, protoc
  109. /// uses the path name for how the file was found.
  110. public func fileDescriptor(named name: String) -> FileDescriptor? {
  111. return registry.fileDescriptor(named: name)
  112. }
  113. /// Find the `Descriptor` for a named proto message.
  114. ///
  115. /// This is a legacy api since it requires the proto to be found or it aborts.
  116. /// Mainly kept for grpc-swift compatibility.
  117. @available(*, deprecated, renamed: "descriptor(named:)")
  118. public func lookupDescriptor(protoName: String) -> Descriptor {
  119. self.descriptor(named: protoName)!
  120. }
  121. /// Find the `Descriptor` for a named proto message.
  122. public func descriptor(named fullName: String) -> Descriptor? {
  123. return registry.descriptor(named: ".\(fullName)")
  124. }
  125. /// Find the `EnumDescriptor` for a named proto enum.
  126. ///
  127. /// This is a legacy api since it requires the enum to be found or it aborts.
  128. /// Mainly kept for grpc-swift compatibility.
  129. @available(*, deprecated, renamed: "enumDescriptor(named:)")
  130. public func lookupEnumDescriptor(protoName: String) -> EnumDescriptor {
  131. return enumDescriptor(named: protoName)!
  132. }
  133. /// Find the `EnumDescriptor` for a named proto enum.
  134. public func enumDescriptor(named fullName: String) -> EnumDescriptor? {
  135. return registry.enumDescriptor(named: ".\(fullName)")
  136. }
  137. /// Find the `ServiceDescriptor` for a named proto service.
  138. ///
  139. /// This is a legacy api since it requires the enum to be found or it aborts.
  140. /// Mainly kept for grpc-swift compatibility.
  141. @available(*, deprecated, renamed: "serviceDescriptor(named:)")
  142. public func lookupServiceDescriptor(protoName: String) -> ServiceDescriptor {
  143. return serviceDescriptor(named: protoName)!
  144. }
  145. /// Find the `ServiceDescriptor` for a named proto service.
  146. public func serviceDescriptor(named fullName: String) -> ServiceDescriptor? {
  147. return registry.serviceDescriptor(named: ".\(fullName)")
  148. }
  149. }
  150. /// Models a .proto file. `FileDescriptor`s are not directly created,
  151. /// instead they are constructed/fetched via the `DescriptorSet` or
  152. /// they are directly accessed via a `file` property on all the other
  153. /// types of descriptors.
  154. public final class FileDescriptor {
  155. @available(*, deprecated, message: "This enum has been deprecated. Use `Google_Protobuf_Edition` instead.")
  156. public enum Syntax: String {
  157. case proto2
  158. case proto3
  159. public init?(rawValue: String) {
  160. switch rawValue {
  161. case "proto2", "":
  162. self = .proto2
  163. case "proto3":
  164. self = .proto3
  165. default:
  166. return nil
  167. }
  168. }
  169. }
  170. /// The filename used with protoc.
  171. public let name: String
  172. /// The proto package.
  173. public let package: String
  174. @available(*, deprecated, message: "This property has been deprecated. Use `edition` instead.")
  175. public var syntax: Syntax {
  176. Syntax(rawValue: self._proto.syntax)!
  177. }
  178. /// The edition of the file.
  179. public let edition: Google_Protobuf_Edition
  180. /// The resolved features for this File.
  181. public let features: Google_Protobuf_FeatureSet
  182. /// The imports for this file.
  183. public let dependencies: [FileDescriptor]
  184. /// The subset of the imports that were declared `public`.
  185. public let publicDependencies: [FileDescriptor]
  186. /// The subset of the imports that were declared `weak`.
  187. public let weakDependencies: [FileDescriptor]
  188. /// The enum defintions at the file scope level.
  189. public let enums: [EnumDescriptor]
  190. /// The message defintions at the file scope level.
  191. public let messages: [Descriptor]
  192. /// The extension field defintions at the file scope level.
  193. public let extensions: [FieldDescriptor]
  194. /// The service defintions at the file scope level.
  195. public let services: [ServiceDescriptor]
  196. /// The `Google_Protobuf_FileOptions` set on this file.
  197. @available(*, deprecated, renamed: "options")
  198. public var fileOptions: Google_Protobuf_FileOptions { self.options }
  199. /// The `Google_Protobuf_FileOptions` set on this file.
  200. public let options: Google_Protobuf_FileOptions
  201. private let sourceCodeInfo: Google_Protobuf_SourceCodeInfo
  202. /// The proto version of the descriptor that defines this File.
  203. ///
  204. /// Thanks to Editions, this isn't likely to be exactly what
  205. /// folks want anymore, so wave any other plugins off it.
  206. @available(*, deprecated,
  207. message: "Use the properties directly or open a GitHub issue for something missing")
  208. public var proto: Google_Protobuf_FileDescriptorProto { return _proto }
  209. private let _proto: Google_Protobuf_FileDescriptorProto
  210. @available(*, deprecated, message: "Use `fileOptions/deprecated` instead.")
  211. public var isDeprecated: Bool { return proto.options.deprecated }
  212. fileprivate init(
  213. proto: Google_Protobuf_FileDescriptorProto,
  214. featureSetDefaults: Google_Protobuf_FeatureSetDefaults,
  215. featureExtensions: [any AnyMessageExtension],
  216. registry: Registry
  217. ) {
  218. self.name = proto.name
  219. self.package = proto.package
  220. // This logic comes from upstream `DescriptorBuilder::BuildFileImpl()`.
  221. if proto.hasEdition {
  222. self.edition = proto.edition
  223. } else {
  224. switch proto.syntax {
  225. case "", "proto2":
  226. self.edition = .proto2
  227. case "proto3":
  228. self.edition = .proto3
  229. default:
  230. self.edition = .unknown
  231. fatalError(
  232. "protoc provided an expected value (\"\(proto.syntax)\") for syntax/edition: \(proto.name)")
  233. }
  234. }
  235. // TODO: Revsit capturing the error here and see about exposing it out
  236. // to be reported via plugins.
  237. let featureResolver: FeatureResolver
  238. do {
  239. featureResolver = try FeatureResolver(edition: self.edition,
  240. featureSetDefaults: featureSetDefaults,
  241. featureExtensions: featureExtensions)
  242. } catch let e {
  243. fatalError("Failed to make a FeatureResolver for \(self.name): \(e)")
  244. }
  245. let resolvedFeatures = featureResolver.resolve(proto.options)
  246. self.features = resolvedFeatures
  247. self.options = proto.options
  248. let protoPackage = proto.package
  249. self.enums = proto.enumType.enumerated().map {
  250. return EnumDescriptor(proto: $0.element,
  251. index: $0.offset,
  252. parentFeatures: resolvedFeatures,
  253. featureResolver: featureResolver,
  254. registry: registry,
  255. scope: protoPackage)
  256. }
  257. self.messages = proto.messageType.enumerated().map {
  258. return Descriptor(proto: $0.element,
  259. index: $0.offset,
  260. parentFeatures: resolvedFeatures,
  261. featureResolver: featureResolver,
  262. registry: registry,
  263. scope: protoPackage)
  264. }
  265. self.extensions = proto.extension.enumerated().map {
  266. return FieldDescriptor(extension: $0.element,
  267. index: $0.offset,
  268. parentFeatures: resolvedFeatures,
  269. featureResolver: featureResolver,
  270. registry: registry)
  271. }
  272. self.services = proto.service.enumerated().map {
  273. return ServiceDescriptor(proto: $0.element,
  274. index: $0.offset,
  275. fileFeatures: resolvedFeatures,
  276. featureResolver: featureResolver,
  277. registry: registry,
  278. scope: protoPackage)
  279. }
  280. // The compiler ensures there aren't cycles between a file and dependencies, so
  281. // this doesn't run the risk of creating any retain cycles that would force these
  282. // to have to be weak.
  283. let dependencies = proto.dependency.map { return registry.fileDescriptor(named: $0)! }
  284. self.dependencies = dependencies
  285. self.publicDependencies = proto.publicDependency.map { dependencies[Int($0)] }
  286. self.weakDependencies = proto.weakDependency.map { dependencies[Int($0)] }
  287. self.sourceCodeInfo = proto.sourceCodeInfo
  288. self._proto = proto
  289. // Done initializing, register ourselves.
  290. registry.register(file: self)
  291. // descriptor.proto documents the files will be in deps order. That means we
  292. // any external reference will have been in the previous files in the set.
  293. self.enums.forEach { $0.bind(file: self, registry: registry, containingType: nil) }
  294. self.messages.forEach { $0.bind(file: self, registry: registry, containingType: nil) }
  295. self.extensions.forEach { $0.bind(file: self, registry: registry, containingType: nil) }
  296. self.services.forEach { $0.bind(file: self, registry: registry) }
  297. }
  298. /// Fetch the source information for a give path. For more details on the paths
  299. /// and what this information is, see `Google_Protobuf_SourceCodeInfo`.
  300. ///
  301. /// For simpler access to the comments for give message, fields, enums; see
  302. /// `Descriptor+Extensions.swift` and the `ProvidesLocationPath` and
  303. /// `ProvidesSourceCodeLocation` protocols.
  304. public func sourceCodeInfoLocation(path: IndexPath) -> Google_Protobuf_SourceCodeInfo.Location? {
  305. guard let location = locationMap[path] else {
  306. return nil
  307. }
  308. return location
  309. }
  310. // Lazy so this can be computed on demand, as the imported files won't need
  311. // comments during generation.
  312. private lazy var locationMap: [IndexPath:Google_Protobuf_SourceCodeInfo.Location] = {
  313. var result: [IndexPath:Google_Protobuf_SourceCodeInfo.Location] = [:]
  314. for loc in sourceCodeInfo.location {
  315. let intList = loc.path.map { return Int($0) }
  316. result[IndexPath(indexes: intList)] = loc
  317. }
  318. return result
  319. }()
  320. }
  321. /// Describes a type of protocol message, or a particular group within a
  322. /// message. `Descriptor`s are not directly created, instead they are
  323. /// constructed/fetched via the `DescriptorSet` or they are directly accessed
  324. /// via a `messageType` property on `FieldDescriptor`s, etc.
  325. public final class Descriptor {
  326. // We can't assign a value directly to `proto` in the init because we get the
  327. // deprecation warning. This private prop only exists as a workaround to avoid
  328. // this warning and preserve backwards compatibility - it should be removed
  329. // when removing `proto`.
  330. private let _proto: Google_Protobuf_DescriptorProto
  331. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  332. public var proto: Google_Protobuf_DescriptorProto {
  333. _proto
  334. }
  335. /// The type of this Message.
  336. public enum WellKnownType: String {
  337. /// An instance of google.protobuf.DoubleValue.
  338. case doubleValue = "google.protobuf.DoubleValue"
  339. /// An instance of google.protobuf.FloatValue.
  340. case floatValue = "google.protobuf.FloatValue"
  341. /// An instance of google.protobuf.Int64Value.
  342. case int64Value = "google.protobuf.Int64Value"
  343. /// An instance of google.protobuf.UInt64Value.
  344. case uint64Value = "google.protobuf.UInt64Value"
  345. /// An instance of google.protobuf.Int32Value.
  346. case int32Value = "google.protobuf.Int32Value"
  347. /// An instance of google.protobuf.UInt32Value.
  348. case uint32Value = "google.protobuf.UInt32Value"
  349. /// An instance of google.protobuf.StringValue.
  350. case stringValue = "google.protobuf.StringValue"
  351. /// An instance of google.protobuf.BytesValue.
  352. case bytesValue = "google.protobuf.BytesValue"
  353. /// An instance of google.protobuf.BoolValue.
  354. case boolValue = "google.protobuf.BoolValue"
  355. /// An instance of google.protobuf.Any.
  356. case any = "google.protobuf.Any"
  357. /// An instance of google.protobuf.FieldMask.
  358. case fieldMask = "google.protobuf.FieldMask"
  359. /// An instance of google.protobuf.Duration.
  360. case duration = "google.protobuf.Duration"
  361. /// An instance of google.protobuf.Timestamp.
  362. case timestamp = "google.protobuf.Timestamp"
  363. /// An instance of google.protobuf.Value.
  364. case value = "google.protobuf.Value"
  365. /// An instance of google.protobuf.ListValue.
  366. case listValue = "google.protobuf.ListValue"
  367. /// An instance of google.protobuf.Struct.
  368. case `struct` = "google.protobuf.Struct"
  369. }
  370. /// Describes an extension range of a message. `ExtensionRange`s are not
  371. /// directly created, instead they are constructed/fetched via the
  372. /// `Descriptor`.
  373. public final class ExtensionRange {
  374. /// The start field number of this range (inclusive).
  375. public let start: Int32
  376. // The end field number of this range (exclusive).
  377. public fileprivate(set) var end: Int32
  378. // Tndex of this extension range within the message's extension range array.
  379. public let index: Int
  380. /// The resolved features for this ExtensionRange.
  381. public let features: Google_Protobuf_FeatureSet
  382. /// The `Google_Protobuf_ExtensionRangeOptions` set on this ExtensionRange.
  383. public let options: Google_Protobuf_ExtensionRangeOptions
  384. /// The name of the containing type, not including its scope.
  385. public var name: String { return containingType.name }
  386. /// The fully-qualified name of the containing type, scope delimited by
  387. /// periods.
  388. public var fullName: String { return containingType.fullName }
  389. /// The .proto file in which this ExtensionRange was defined.
  390. public var file: FileDescriptor! { return containingType.file }
  391. /// The descriptor that owns with ExtensionRange.
  392. public var containingType: Descriptor { return _containingType! }
  393. // Storage for `containingType`, will be set by bind()
  394. private unowned var _containingType: Descriptor?
  395. fileprivate init(proto: Google_Protobuf_DescriptorProto.ExtensionRange,
  396. index: Int,
  397. features: Google_Protobuf_FeatureSet) {
  398. self.start = proto.start
  399. self.end = proto.end
  400. self.index = index
  401. self.features = features
  402. self.options = proto.options
  403. }
  404. fileprivate func bind(containingType: Descriptor, registry: Registry) {
  405. self._containingType = containingType
  406. }
  407. }
  408. /// The name of the message type, not including its scope.
  409. public let name: String
  410. /// The fully-qualified name of the message type, scope delimited by
  411. /// periods. For example, message type "Foo" which is declared in package
  412. /// "bar" has full name "bar.Foo". If a type "Baz" is nested within
  413. /// Foo, Baz's `fullName` is "bar.Foo.Baz". To get only the part that
  414. /// comes after the last '.', use name().
  415. public let fullName: String
  416. /// Index of this descriptor within the file or containing type's message
  417. /// type array.
  418. public let index: Int
  419. /// The .proto file in which this message type was defined.
  420. public var file: FileDescriptor! { return _file! }
  421. /// If this Descriptor describes a nested type, this returns the type
  422. /// in which it is nested.
  423. public private(set) unowned var containingType: Descriptor?
  424. /// The resolved features for this Descriptor.
  425. public let features: Google_Protobuf_FeatureSet
  426. /// The `Google_Protobuf_MessageOptions` set on this Message.
  427. public let options: Google_Protobuf_MessageOptions
  428. // If this descriptor represents a well known type, which type it is.
  429. public let wellKnownType: WellKnownType?
  430. /// The enum defintions under this message.
  431. public let enums: [EnumDescriptor]
  432. /// The message defintions under this message. In the C++ Descriptor this
  433. /// is `nested_type`.
  434. public let messages: [Descriptor]
  435. /// The fields of this message.
  436. public let fields: [FieldDescriptor]
  437. /// The oneofs in this message. This can include synthetic oneofs.
  438. public let oneofs: [OneofDescriptor]
  439. /// Non synthetic oneofs.
  440. ///
  441. /// These always come first (enforced by the C++ Descriptor code). So this is always a
  442. /// leading subset of `oneofs` (or the same if there are no synthetic entries).
  443. public private(set) lazy var realOneofs: [OneofDescriptor] = {
  444. // Lazy because `isSynthetic` can't be called until after `bind()`.
  445. return self.oneofs.filter { !$0._isSynthetic }
  446. }()
  447. /// The extension field defintions under this message.
  448. public let extensions: [FieldDescriptor]
  449. /// The extension ranges declared for this message. They are returned in
  450. /// the order they are defined in the .proto file.
  451. public let messageExtensionRanges: [ExtensionRange]
  452. /// The extension ranges declared for this message. They are returned in
  453. /// the order they are defined in the .proto file.
  454. @available(*, deprecated, message: "This property is now deprecated: please use protoExtensionRanges instead.")
  455. public var extensionRanges: [Google_Protobuf_DescriptorProto.ExtensionRange] {
  456. proto.extensionRange
  457. }
  458. /// The `extensionRanges` are in the order they appear in the original .proto
  459. /// file; this orders them and then merges any ranges that are actually
  460. /// contiguious (i.e. - [(21,30),(10,20)] -> [(10,30)])
  461. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  462. public private(set) lazy var normalizedExtensionRanges: [Google_Protobuf_DescriptorProto.ExtensionRange] = {
  463. var ordered = self.extensionRanges.sorted(by: { return $0.start < $1.start })
  464. if ordered.count > 1 {
  465. for i in (0..<(ordered.count - 1)).reversed() {
  466. if ordered[i].end == ordered[i+1].start {
  467. // This is why we need `end`'s setter to be `fileprivate` instead of
  468. // having it be a `let`.
  469. // We should turn it back into a let once we get rid of this prop.
  470. ordered[i].end = ordered[i+1].end
  471. ordered.remove(at: i + 1)
  472. }
  473. }
  474. }
  475. return ordered
  476. }()
  477. /// The `extensionRanges` from `normalizedExtensionRanges`, but takes a step
  478. /// further in that any ranges that do _not_ have any fields inbetween them
  479. /// are also merged together. These can then be used in context where it is
  480. /// ok to include field numbers that have to be extension or unknown fields.
  481. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  482. public private(set) lazy var ambitiousExtensionRanges: [Google_Protobuf_DescriptorProto.ExtensionRange] = {
  483. var merged = self.normalizedExtensionRanges
  484. var sortedFields = self.fields.sorted {$0.number < $1.number}
  485. if merged.count > 1 {
  486. var fieldNumbersReversedIterator =
  487. self.fields.map({ Int($0.number) }).sorted(by: { $0 > $1 }).makeIterator()
  488. var nextFieldNumber = fieldNumbersReversedIterator.next()
  489. while nextFieldNumber != nil && merged.last!.start < nextFieldNumber! {
  490. nextFieldNumber = fieldNumbersReversedIterator.next()
  491. }
  492. for i in (0..<(merged.count - 1)).reversed() {
  493. if nextFieldNumber == nil || merged[i].start > nextFieldNumber! {
  494. // No fields left or range starts after the next field, merge it with
  495. // the previous one.
  496. merged[i].end = merged[i+1].end
  497. merged.remove(at: i + 1)
  498. } else {
  499. // can't merge, find the next field number below this range.
  500. while nextFieldNumber != nil && merged[i].start < nextFieldNumber! {
  501. nextFieldNumber = fieldNumbersReversedIterator.next()
  502. }
  503. }
  504. }
  505. }
  506. return merged
  507. }()
  508. /// The reserved field number ranges for this message. These are returned
  509. /// in the order they are defined in the .proto file.
  510. public let reservedRanges: [Range<Int32>]
  511. /// The reserved field names for this message. These are returned in the
  512. /// order they are defined in the .proto file.
  513. public let reservedNames: [String]
  514. /// True/False if this Message is just for a `map<>` entry.
  515. @available(*, deprecated, renamed: "options.mapyEntry")
  516. public var isMapEntry: Bool { return options.mapEntry }
  517. /// Returns the `FieldDescriptor`s for the "key" and "value" fields. If
  518. /// this isn't a map entry field, returns nil.
  519. ///
  520. /// This is like the C++ Descriptor `map_key()` and `map_value()` methods.
  521. public var mapKeyAndValue: (key: FieldDescriptor, value: FieldDescriptor)? {
  522. guard options.mapEntry else { return nil }
  523. precondition(fields.count == 2)
  524. return (key: fields[0], value: fields[1])
  525. }
  526. // Storage for `file`, will be set by bind()
  527. private unowned var _file: FileDescriptor?
  528. @available(*, deprecated, renamed: "options.messageSetWireFormat")
  529. public var useMessageSetWireFormat: Bool { return options.messageSetWireFormat }
  530. fileprivate init(proto: Google_Protobuf_DescriptorProto,
  531. index: Int,
  532. parentFeatures: Google_Protobuf_FeatureSet,
  533. featureResolver: FeatureResolver,
  534. registry: Registry,
  535. scope: String) {
  536. self._proto = proto
  537. self.name = proto.name
  538. let fullName = scope.isEmpty ? proto.name : "\(scope).\(proto.name)"
  539. self.fullName = fullName
  540. self.index = index
  541. let resolvedFeatures = featureResolver.resolve(proto.options, resolvedParent: parentFeatures)
  542. self.features = resolvedFeatures
  543. self.options = proto.options
  544. self.wellKnownType = WellKnownType(rawValue: fullName)
  545. self.reservedRanges = proto.reservedRange.map { return $0.start ..< $0.end }
  546. self.reservedNames = proto.reservedName
  547. // TODO: This can skip the synthetic oneofs as no features can be set on
  548. // them to inherrit things.
  549. let oneofFeatures = proto.oneofDecl.map {
  550. return featureResolver.resolve($0.options, resolvedParent: resolvedFeatures)
  551. }
  552. self.messageExtensionRanges = proto.extensionRange.enumerated().map {
  553. return ExtensionRange(proto: $0.element,
  554. index: $0.offset,
  555. features: featureResolver.resolve($0.element.options,
  556. resolvedParent: resolvedFeatures))
  557. }
  558. self.enums = proto.enumType.enumerated().map {
  559. return EnumDescriptor(proto: $0.element,
  560. index: $0.offset,
  561. parentFeatures: resolvedFeatures,
  562. featureResolver: featureResolver,
  563. registry: registry,
  564. scope: fullName)
  565. }
  566. self.messages = proto.nestedType.enumerated().map {
  567. return Descriptor(proto: $0.element,
  568. index: $0.offset,
  569. parentFeatures: resolvedFeatures,
  570. featureResolver: featureResolver,
  571. registry: registry,
  572. scope: fullName)
  573. }
  574. self.fields = proto.field.enumerated().map {
  575. // For field Features inherrit from the parent oneof or message. A
  576. // synthetic oneof (for proto3 optional) can't get features, so those
  577. // don't come into play.
  578. let inRealOneof = $0.element.hasOneofIndex && !$0.element.proto3Optional
  579. return FieldDescriptor(messageField: $0.element,
  580. index: $0.offset,
  581. parentFeatures: inRealOneof ? oneofFeatures[Int($0.element.oneofIndex)] : resolvedFeatures,
  582. featureResolver: featureResolver,
  583. registry: registry)
  584. }
  585. self.oneofs = proto.oneofDecl.enumerated().map {
  586. return OneofDescriptor(proto: $0.element,
  587. index: $0.offset,
  588. features: oneofFeatures[$0.offset],
  589. registry: registry)
  590. }
  591. self.extensions = proto.extension.enumerated().map {
  592. return FieldDescriptor(extension: $0.element,
  593. index: $0.offset,
  594. parentFeatures: resolvedFeatures,
  595. featureResolver: featureResolver,
  596. registry: registry)
  597. }
  598. // Done initializing, register ourselves.
  599. registry.register(message: self)
  600. }
  601. fileprivate func bind(file: FileDescriptor, registry: Registry, containingType: Descriptor?) {
  602. _file = file
  603. self.containingType = containingType
  604. messageExtensionRanges.forEach { $0.bind(containingType: self, registry: registry) }
  605. enums.forEach { $0.bind(file: file, registry: registry, containingType: self) }
  606. messages.forEach { $0.bind(file: file, registry: registry, containingType: self) }
  607. fields.forEach { $0.bind(file: file, registry: registry, containingType: self) }
  608. oneofs.forEach { $0.bind(registry: registry, containingType: self) }
  609. extensions.forEach { $0.bind(file: file, registry: registry, containingType: self) }
  610. // Synthetic oneofs come after normal oneofs. The C++ Descriptor enforces this, only
  611. // here as a secondary validation because other code can rely on it.
  612. var seenSynthetic = false
  613. for o in oneofs {
  614. if seenSynthetic {
  615. // Once we've seen one synthetic, all the rest must also be synthetic.
  616. precondition(o._isSynthetic)
  617. } else {
  618. seenSynthetic = o._isSynthetic
  619. }
  620. }
  621. }
  622. }
  623. /// Describes a type of protocol enum. `EnumDescriptor`s are not directly
  624. /// created, instead they are constructed/fetched via the `DescriptorSet` or
  625. /// they are directly accessed via a `EnumType` property on `FieldDescriptor`s,
  626. /// etc.
  627. public final class EnumDescriptor {
  628. // We can't assign a value directly to `proto` in the init because we get the
  629. // deprecation warning. This private prop only exists as a workaround to avoid
  630. // this warning and preserve backwards compatibility - it should be removed
  631. // when removing `proto`.
  632. private let _proto: Google_Protobuf_EnumDescriptorProto
  633. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  634. public var proto: Google_Protobuf_EnumDescriptorProto {
  635. _proto
  636. }
  637. /// The name of this enum type in the containing scope.
  638. public let name: String
  639. /// The fully-qualified name of the enum type, scope delimited by periods.
  640. public let fullName: String
  641. /// Index of this enum within the file or containing message's enums.
  642. public let index: Int
  643. /// The .proto file in which this message type was defined.
  644. public var file: FileDescriptor! { return _file! }
  645. /// If this Descriptor describes a nested type, this returns the type
  646. /// in which it is nested.
  647. public private(set) unowned var containingType: Descriptor?
  648. /// The resolved features for this Enum.
  649. public let features: Google_Protobuf_FeatureSet
  650. /// The values defined for this enum. Guaranteed (by protoc) to be atleast
  651. /// one item. These are returned in the order they were defined in the .proto
  652. /// file.
  653. public let values: [EnumValueDescriptor]
  654. /// The `Google_Protobuf_MessageOptions` set on this enum.
  655. public let options: Google_Protobuf_EnumOptions
  656. /// The reserved value ranges for this enum. These are returned in the order
  657. /// they are defined in the .proto file.
  658. public let reservedRanges: [ClosedRange<Int32>]
  659. /// The reserved value names for this enum. These are returned in the order
  660. /// they are defined in the .proto file.
  661. public let reservedNames: [String]
  662. /// Returns true whether this is a "closed" enum, meaning that it:
  663. /// - Has a fixed set of named values.
  664. /// - Encountering values not in this set causes them to be treated as unknown
  665. /// fields.
  666. /// - The first value (i.e., the default) may be nonzero.
  667. public var isClosed: Bool {
  668. // Implementation comes from C++ EnumDescriptor::is_closed().
  669. return features.enumType == .closed
  670. }
  671. // Storage for `file`, will be set by bind()
  672. private unowned var _file: FileDescriptor?
  673. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  674. public var defaultValue: EnumValueDescriptor {
  675. // The compiler requires the be atleast one value, so force unwrap is safe.
  676. return values.first!
  677. }
  678. fileprivate init(proto: Google_Protobuf_EnumDescriptorProto,
  679. index: Int,
  680. parentFeatures: Google_Protobuf_FeatureSet,
  681. featureResolver: FeatureResolver,
  682. registry: Registry,
  683. scope: String) {
  684. self._proto = proto
  685. self.name = proto.name
  686. self.fullName = scope.isEmpty ? proto.name : "\(scope).\(proto.name)"
  687. self.index = index
  688. let resolvedFeatures = featureResolver.resolve(proto.options, resolvedParent: parentFeatures)
  689. self.features = resolvedFeatures
  690. self.options = proto.options
  691. self.reservedRanges = proto.reservedRange.map { return $0.start ... $0.end }
  692. self.reservedNames = proto.reservedName
  693. self.values = proto.value.enumerated().map {
  694. return EnumValueDescriptor(proto: $0.element,
  695. index: $0.offset,
  696. features: featureResolver.resolve($0.element.options,
  697. resolvedParent: resolvedFeatures),
  698. scope: scope)
  699. }
  700. // Done initializing, register ourselves.
  701. registry.register(enum: self)
  702. values.forEach { $0.bind(enumType: self) }
  703. }
  704. fileprivate func bind(file: FileDescriptor, registry: Registry, containingType: Descriptor?) {
  705. _file = file
  706. self.containingType = containingType
  707. }
  708. }
  709. /// Describes an individual enum constant of a particular type. To get the
  710. /// `EnumValueDescriptor` for a given enum value, first get the `EnumDescriptor`
  711. /// for its type.
  712. public final class EnumValueDescriptor {
  713. // We can't assign a value directly to `proto` in the init because we get the
  714. // deprecation warning. This private prop only exists as a workaround to avoid
  715. // this warning and preserve backwards compatibility - it should be removed
  716. // when removing `proto`.
  717. private let _proto: Google_Protobuf_EnumValueDescriptorProto
  718. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  719. public var proto: Google_Protobuf_EnumValueDescriptorProto {
  720. _proto
  721. }
  722. /// Name of this enum constant.
  723. public let name: String
  724. private var _fullName: String
  725. /// The full_name of an enum value is a sibling symbol of the enum type.
  726. /// e.g. the full name of FieldDescriptorProto::TYPE_INT32 is actually
  727. /// "google.protobuf.FieldDescriptorProto.TYPE_INT32", NOT
  728. /// "google.protobuf.FieldDescriptorProto.Type.TYPE_INT32". This is to conform
  729. /// with C++ scoping rules for enums.
  730. public var fullName: String {
  731. get {
  732. self._fullName
  733. }
  734. @available(*, deprecated, message: "fullName is now read-only")
  735. set {
  736. self._fullName = newValue
  737. }
  738. }
  739. /// Index within the enums's `EnumDescriptor`.
  740. public let index: Int
  741. /// Numeric value of this enum constant.
  742. public let number: Int32
  743. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  744. public private(set) weak var aliasOf: EnumValueDescriptor?
  745. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  746. public fileprivate(set) var aliases: [EnumValueDescriptor] = []
  747. /// The resolved features for this EnumValue.
  748. public let features: Google_Protobuf_FeatureSet
  749. /// The .proto file in which this message type was defined.
  750. public var file: FileDescriptor! { return enumType.file }
  751. /// The type of this value.
  752. public var enumType: EnumDescriptor! { return _enumType! }
  753. /// The `Google_Protobuf_EnumValueOptions` set on this value.
  754. public let options: Google_Protobuf_EnumValueOptions
  755. // Storage for `enumType`, will be set by bind()
  756. private unowned var _enumType: EnumDescriptor?
  757. fileprivate init(proto: Google_Protobuf_EnumValueDescriptorProto,
  758. index: Int,
  759. features: Google_Protobuf_FeatureSet,
  760. scope: String) {
  761. self._proto = proto
  762. self.name = proto.name
  763. self._fullName = scope.isEmpty ? proto.name : "\(scope).\(proto.name)"
  764. self.index = index
  765. self.features = features
  766. self.number = proto.number
  767. self.options = proto.options
  768. }
  769. fileprivate func bind(enumType: EnumDescriptor) {
  770. self._enumType = enumType
  771. }
  772. }
  773. /// Describes a oneof defined in a message type.
  774. public final class OneofDescriptor {
  775. // We can't assign a value directly to `proto` in the init because we get the
  776. // deprecation warning. This private prop only exists as a workaround to avoid
  777. // this warning and preserve backwards compatibility - it should be removed
  778. // when removing `proto`.
  779. private let _proto: Google_Protobuf_OneofDescriptorProto
  780. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  781. public var proto: Google_Protobuf_OneofDescriptorProto {
  782. _proto
  783. }
  784. /// Name of this oneof.
  785. public let name: String
  786. /// Fully-qualified name of the oneof.
  787. public var fullName: String { return "\(containingType.fullName).\(name)" }
  788. /// Index of this oneof within the message's oneofs.
  789. public let index: Int
  790. /// The resolved features for this Oneof.
  791. public let features: Google_Protobuf_FeatureSet
  792. /// Returns whether this oneof was inserted by the compiler to wrap a proto3
  793. /// optional field. If this returns true, code generators should *not* emit it.
  794. var _isSynthetic: Bool {
  795. return fields.count == 1 && fields.first!.proto3Optional
  796. }
  797. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  798. public var isSynthetic: Bool {
  799. _isSynthetic
  800. }
  801. /// The .proto file in which this oneof type was defined.
  802. public var file: FileDescriptor! { return containingType.file }
  803. /// The Descriptor of the message that defines this oneof.
  804. public var containingType: Descriptor! { return _containingType! }
  805. /// The `Google_Protobuf_OneofOptions` set on this oneof.
  806. public let options: Google_Protobuf_OneofOptions
  807. /// The members of this oneof, in the order in which they were declared in the
  808. /// .proto file.
  809. public private(set) lazy var fields: [FieldDescriptor] = {
  810. let myIndex = Int32(self.index)
  811. return containingType.fields.filter { $0.oneofIndex == myIndex }
  812. }()
  813. // Storage for `containingType`, will be set by bind()
  814. private unowned var _containingType: Descriptor?
  815. fileprivate init(proto: Google_Protobuf_OneofDescriptorProto,
  816. index: Int,
  817. features: Google_Protobuf_FeatureSet,
  818. registry: Registry) {
  819. self._proto = proto
  820. self.name = proto.name
  821. self.index = index
  822. self.features = features
  823. self.options = proto.options
  824. }
  825. fileprivate func bind(registry: Registry, containingType: Descriptor) {
  826. _containingType = containingType
  827. }
  828. }
  829. /// Describes a single field of a message. To get the descriptor for a given
  830. /// field, first get the `Descriptor` for the message in which it is defined,
  831. /// then find the field. To get a `FieldDescriptor` for an extension, get the
  832. /// `Descriptor` or `FileDescriptor` for its containing scope, find the
  833. /// extension.
  834. public final class FieldDescriptor {
  835. // We can't assign a value directly to `proto` in the init because we get the
  836. // deprecation warning. This private prop only exists as a workaround to avoid
  837. // this warning and preserve backwards compatibility - it should be removed
  838. // when removing `proto`.
  839. private let _proto: Google_Protobuf_FieldDescriptorProto
  840. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  841. public var proto: Google_Protobuf_FieldDescriptorProto {
  842. _proto
  843. }
  844. /// Name of this field within the message.
  845. public let name: String
  846. /// Fully-qualified name of the field.
  847. public var fullName: String {
  848. // Since the fullName isn't needed on fields that often, compute it on demand.
  849. guard isExtension else {
  850. // Normal field on a message.
  851. return "\(containingType.fullName).\(name)"
  852. }
  853. if let extensionScope = extensionScope {
  854. return "\(extensionScope.fullName).\(name)"
  855. }
  856. let package = file.package
  857. return package.isEmpty ? name : "\(package).\(name)"
  858. }
  859. /// JSON name of this field.
  860. public let jsonName: String?
  861. public let features: Google_Protobuf_FeatureSet
  862. /// File in which this field was defined.
  863. public var file: FileDescriptor! { return _file! }
  864. /// If this is an extension field.
  865. public let isExtension: Bool
  866. /// The field number.
  867. public let number: Int32
  868. /// Valid field numbers are positive integers up to kMaxNumber.
  869. static let kMaxNumber: Int = (1 << 29) - 1
  870. /// First field number reserved for the protocol buffer library
  871. /// implementation. Users may not declare fields that use reserved numbers.
  872. static let kFirstReservedNumber: Int = 19000
  873. /// Last field number reserved for the protocol buffer library implementation.
  874. /// Users may not declare fields that use reserved numbers.
  875. static let kLastReservedNumber: Int = 19999
  876. /// Declared type of this field.
  877. public private(set) var type: Google_Protobuf_FieldDescriptorProto.TypeEnum
  878. /// optional/required/repeated
  879. public let label: Google_Protobuf_FieldDescriptorProto.Label
  880. /// Shorthand for `label` == `.required`.
  881. ///
  882. /// NOTE: This could also be a map as the are also repeated fields.
  883. public var isRequired: Bool {
  884. // Implementation comes from FieldDescriptor::is_required()
  885. return features.fieldPresence == .legacyRequired
  886. }
  887. /// Shorthand for `label` == `.optional`
  888. public var isOptional: Bool { return label == .optional }
  889. /// Shorthand for `label` == `.repeated`
  890. public var isRepeated: Bool { return label == .repeated }
  891. /// Is this field packable.
  892. public var isPackable: Bool {
  893. // This logic comes from the C++ FieldDescriptor::is_packable() impl.
  894. return label == .repeated && FieldDescriptor.isPackable(type: type)
  895. }
  896. /// If this field is packable and packed.
  897. public var isPacked: Bool {
  898. // This logic comes from the C++ FieldDescriptor::is_packed() impl.
  899. guard isPackable else { return false }
  900. return features.repeatedFieldEncoding == .packed
  901. }
  902. /// True if this field is a map.
  903. public var isMap: Bool {
  904. // This logic comes from the C++ FieldDescriptor::is_map() impl.
  905. return type == .message && messageType!.options.mapEntry
  906. }
  907. /// Returns true if this field was syntactically written with "optional" in the
  908. /// .proto file. Excludes singular proto3 fields that do not have a label.
  909. var _hasOptionalKeyword: Bool {
  910. // This logic comes from the C++ FieldDescriptor::has_optional_keyword()
  911. // impl.
  912. return proto3Optional ||
  913. (file.edition == .proto2 && label == .optional && oneofIndex == nil)
  914. }
  915. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  916. public var hasOptionalKeyword: Bool {
  917. _hasOptionalKeyword
  918. }
  919. /// Returns true if this field tracks presence, ie. does the field
  920. /// distinguish between "unset" and "present with default value."
  921. /// This includes required, optional, and oneof fields. It excludes maps,
  922. /// repeated fields, and singular proto3 fields without "optional".
  923. public var hasPresence: Bool {
  924. // This logic comes from the C++ FieldDescriptor::has_presence() impl.
  925. guard label != .repeated else { return false }
  926. switch type {
  927. case .group, .message:
  928. // Groups/messages always get field presence.
  929. return true
  930. default:
  931. break
  932. }
  933. return isExtension || oneofIndex != nil || features.fieldPresence != .implicit
  934. }
  935. /// Returns true if this is a string field and should do UTF-8 validation.
  936. ///
  937. /// This api is for completeness, but it likely should never be used. The
  938. /// concept comes from the C++ FieldDescriptory::requires_utf8_validation(),
  939. /// but doesn't make a lot of sense for Swift Protobuf because `string` fields
  940. /// are modeled as Swift `String` objects, and thus they always have to be
  941. /// valid UTF-8. If something were to try putting something else in the field,
  942. /// the library won't be able to parse it. While that sounds bad, other
  943. /// languages have similar issues with their _string_ types and thus have the
  944. /// same issues.
  945. public var requiresUTF8Validation: Bool {
  946. return type == .string && features.utf8Validation == .verify
  947. }
  948. /// Index of this field within the message's fields, or the file or
  949. /// extension scope's extensions.
  950. public let index: Int
  951. /// The explicitly declared default value for this field.
  952. ///
  953. /// This is the *raw* string value from the .proto file that was listed as
  954. /// the default, it is up to the consumer to convert it correctly for the
  955. /// type of this field. The C++ FieldDescriptor does offer some apis to
  956. /// help with that, but at this time, that is not provided here.
  957. @available(*, deprecated, renamed: "defaultValue")
  958. public var explicitDefaultValue: String? {
  959. return defaultValue
  960. }
  961. /// The explicitly declared default value for this field.
  962. ///
  963. /// This is the *raw* string value from the .proto file that was listed as
  964. /// the default, it is up to the consumer to convert it correctly for the
  965. /// type of this field. The C++ FieldDescriptor does offer some apis to
  966. /// help with that, but at this time, that is not provided here.
  967. public let defaultValue: String?
  968. /// The `Descriptor` of the message which this is a field of. For extensions,
  969. /// this is the extended type.
  970. public var containingType: Descriptor! { return _containingType! }
  971. /// The oneof this field is a member of.
  972. @available(*, deprecated, renamed: "containingOneof")
  973. public var oneof: OneofDescriptor? {
  974. return containingOneof
  975. }
  976. /// The oneof this field is a member of.
  977. public var containingOneof: OneofDescriptor? {
  978. guard let oneofIndex = oneofIndex else { return nil }
  979. return containingType.oneofs[Int(oneofIndex)]
  980. }
  981. /// The non synthetic oneof this field is a member of.
  982. @available(*, deprecated, renamed: "realContainingOneof")
  983. public var realOneof: OneofDescriptor? {
  984. return realContainingOneof
  985. }
  986. /// The non synthetic oneof this field is a member of.
  987. public var realContainingOneof: OneofDescriptor? {
  988. guard let oneof = containingOneof, !oneof._isSynthetic else { return nil }
  989. return oneof
  990. }
  991. /// The index in a oneof this field is in.
  992. public let oneofIndex: Int32?
  993. // This builds basically a union for the storage for `extensionScope`
  994. // and the value to look it up with.
  995. private enum ExtensionScopeStorage {
  996. case extendee(String) // The value to be used for looked up during `bind()`.
  997. case message(UnownedBox<Descriptor>)
  998. }
  999. private var _extensionScopeStorage: ExtensionScopeStorage?
  1000. /// Extensions can be declared within the scope of another message. If this
  1001. /// is an extension field, then this will be the scope it was declared in
  1002. /// nil if was declared at a global scope.
  1003. public var extensionScope: Descriptor? {
  1004. guard case .message(let boxed) = _extensionScopeStorage else { return nil }
  1005. return boxed.value
  1006. }
  1007. // This builds basically a union for the storage for `messageType`
  1008. // and `enumType` since only one can needed at a time.
  1009. private enum FieldTypeStorage {
  1010. case typeName(String) // The value to be looked up during `bind()`.
  1011. case message(UnownedBox<Descriptor>)
  1012. case `enum`(UnownedBox<EnumDescriptor>)
  1013. }
  1014. private var _fieldTypeStorage: FieldTypeStorage?
  1015. /// When this is a message/group field, that message's `Descriptor`.
  1016. public var messageType: Descriptor! {
  1017. guard case .message(let boxed) = _fieldTypeStorage else { return nil }
  1018. return boxed.value
  1019. }
  1020. /// When this is a enum field, that enum's `EnumDescriptor`.
  1021. public var enumType: EnumDescriptor! {
  1022. guard case .enum(let boxed) = _fieldTypeStorage else { return nil }
  1023. return boxed.value
  1024. }
  1025. /// The FieldOptions for this field.
  1026. public var options: Google_Protobuf_FieldOptions
  1027. let proto3Optional: Bool
  1028. // Storage for `containingType`, will be set by bind()
  1029. private unowned var _containingType: Descriptor?
  1030. // Storage for `file`, will be set by bind()
  1031. private unowned var _file: FileDescriptor?
  1032. fileprivate convenience init(messageField proto: Google_Protobuf_FieldDescriptorProto,
  1033. index: Int,
  1034. parentFeatures: Google_Protobuf_FeatureSet,
  1035. featureResolver: FeatureResolver,
  1036. registry: Registry) {
  1037. precondition(proto.extendee.isEmpty) // Only for extensions
  1038. // On regular fields, it only makes sense to get `.proto3Optional`
  1039. // when also in a (synthetic) oneof. So...no oneof index, it better
  1040. // not be `.proto3Optional`
  1041. precondition(proto.hasOneofIndex || !proto.proto3Optional)
  1042. self.init(proto: proto,
  1043. index: index,
  1044. parentFeatures: parentFeatures,
  1045. featureResolver: featureResolver,
  1046. registry: registry,
  1047. isExtension: false)
  1048. }
  1049. fileprivate convenience init(extension proto: Google_Protobuf_FieldDescriptorProto,
  1050. index: Int,
  1051. parentFeatures: Google_Protobuf_FeatureSet,
  1052. featureResolver: FeatureResolver,
  1053. registry: Registry) {
  1054. precondition(!proto.extendee.isEmpty) // Required for extensions
  1055. // FieldDescriptorProto is used for fields or extensions, generally
  1056. // .proto3Optional only makes sense on fields if it is in a oneof. But,
  1057. // it is allowed on extensions. For information on that, see
  1058. // https://github.com/protocolbuffers/protobuf/issues/8234#issuecomment-774224376
  1059. // The C++ Descriptor code encorces the field/oneof part, but nothing
  1060. // is checked on the oneof side.
  1061. precondition(!proto.hasOneofIndex)
  1062. self.init(proto: proto,
  1063. index: index,
  1064. parentFeatures: parentFeatures,
  1065. featureResolver: featureResolver,
  1066. registry: registry,
  1067. isExtension: true)
  1068. }
  1069. private init(proto: Google_Protobuf_FieldDescriptorProto,
  1070. index: Int,
  1071. parentFeatures: Google_Protobuf_FeatureSet,
  1072. featureResolver: FeatureResolver,
  1073. registry: Registry,
  1074. isExtension: Bool) {
  1075. self._proto = proto
  1076. self.name = proto.name
  1077. self.index = index
  1078. self.features = featureResolver.resolve(proto, resolvedParent: parentFeatures)
  1079. self.defaultValue = proto.hasDefaultValue ? proto.defaultValue : nil
  1080. precondition(proto.hasJsonName) // protoc should always set the name
  1081. self.jsonName = proto.jsonName
  1082. self.isExtension = isExtension
  1083. self.number = proto.number
  1084. // This remapping is based follow part of what upstream
  1085. // `DescriptorBuilder::PostProcessFieldFeatures()` does. It is needed to
  1086. // help ensure basic transforms from .proto2 to .edition2023 generate the
  1087. // same code/behaviors.
  1088. if proto.type == .message && self.features.messageEncoding == .delimited {
  1089. self.type = .group
  1090. } else {
  1091. self.type = proto.type
  1092. }
  1093. // This remapping is based follow part of what upstream
  1094. // `DescriptorBuilder::PostProcessFieldFeatures()` does. If generators use
  1095. // helper instead of access `label` directly, they won't need this, but for
  1096. // consistency, remap `label` to expose the pre Editions/Features value.
  1097. if self.features.fieldPresence == .legacyRequired && proto.label == .optional {
  1098. self.label = .required
  1099. } else {
  1100. self.label = proto.label
  1101. }
  1102. self.options = proto.options
  1103. self.oneofIndex = proto.hasOneofIndex ? proto.oneofIndex : nil
  1104. self.proto3Optional = proto.proto3Optional
  1105. self._extensionScopeStorage = isExtension ? .extendee(proto.extendee) : nil
  1106. switch type {
  1107. case .group, .message, .enum:
  1108. _fieldTypeStorage = .typeName(proto.typeName)
  1109. default:
  1110. _fieldTypeStorage = nil
  1111. }
  1112. }
  1113. fileprivate func bind(file: FileDescriptor, registry: Registry, containingType: Descriptor?) {
  1114. _file = file
  1115. // See the defintions of `containingType` and `extensionScope`, this
  1116. // dance can otherwise be a little confusing.
  1117. if case .extendee(let extendee) = _extensionScopeStorage {
  1118. _containingType = registry.descriptor(named: extendee)!
  1119. if let containingType = containingType {
  1120. _extensionScopeStorage = .message(UnownedBox(value: containingType))
  1121. } else {
  1122. _extensionScopeStorage = nil // Top level
  1123. }
  1124. } else {
  1125. _containingType = containingType
  1126. }
  1127. if case .typeName(let typeName) = _fieldTypeStorage {
  1128. if type == .enum {
  1129. _fieldTypeStorage = .enum(UnownedBox(value: registry.enumDescriptor(named: typeName)!))
  1130. } else {
  1131. let msgtype = registry.descriptor(named: typeName)!
  1132. _fieldTypeStorage = .message(UnownedBox(value: msgtype))
  1133. if type == .group && (
  1134. msgtype.options.mapEntry ||
  1135. (_containingType != nil && _containingType!.options.mapEntry)
  1136. ) {
  1137. type = .message
  1138. }
  1139. }
  1140. }
  1141. }
  1142. }
  1143. /// Describes an RPC service.
  1144. ///
  1145. /// SwiftProtobuf does *not* generate anything for these (or methods), but
  1146. /// they are here to support things that generate based off RPCs defined in
  1147. /// .proto file (gRPC, etc.).
  1148. public final class ServiceDescriptor {
  1149. // We can't assign a value directly to `proto` in the init because we get the
  1150. // deprecation warning. This private prop only exists as a workaround to avoid
  1151. // this warning and preserve backwards compatibility - it should be removed
  1152. // when removing `proto`.
  1153. private let _proto: Google_Protobuf_ServiceDescriptorProto
  1154. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  1155. public var proto: Google_Protobuf_ServiceDescriptorProto {
  1156. _proto
  1157. }
  1158. /// The name of the service, not including its containing scope.
  1159. public let name: String
  1160. /// The fully-qualified name of the service, scope delimited by periods.
  1161. public let fullName: String
  1162. /// Index of this service within the file's services.
  1163. public let index: Int
  1164. /// The .proto file in which this service was defined
  1165. public var file: FileDescriptor! { return _file! }
  1166. /// The resolved features for this Service.
  1167. public let features: Google_Protobuf_FeatureSet
  1168. /// Get `Google_Protobuf_ServiceOptions` for this service.
  1169. public let options: Google_Protobuf_ServiceOptions
  1170. /// The methods defined on this service. These are returned in the order they
  1171. /// were defined in the .proto file.
  1172. public let methods: [MethodDescriptor]
  1173. // Storage for `file`, will be set by bind()
  1174. private unowned var _file: FileDescriptor?
  1175. fileprivate init(proto: Google_Protobuf_ServiceDescriptorProto,
  1176. index: Int,
  1177. fileFeatures: Google_Protobuf_FeatureSet,
  1178. featureResolver: FeatureResolver,
  1179. registry: Registry,
  1180. scope: String) {
  1181. self._proto = proto
  1182. self.name = proto.name
  1183. self.fullName = scope.isEmpty ? proto.name : "\(scope).\(proto.name)"
  1184. self.index = index
  1185. let resolvedFeatures = featureResolver.resolve(proto.options, resolvedParent: fileFeatures)
  1186. self.features = resolvedFeatures
  1187. self.options = proto.options
  1188. self.methods = proto.method.enumerated().map {
  1189. return MethodDescriptor(proto: $0.element,
  1190. index: $0.offset,
  1191. features: featureResolver.resolve($0.element.options, resolvedParent: resolvedFeatures),
  1192. registry: registry)
  1193. }
  1194. // Done initializing, register ourselves.
  1195. registry.register(service: self)
  1196. }
  1197. fileprivate func bind(file: FileDescriptor, registry: Registry) {
  1198. _file = file
  1199. methods.forEach { $0.bind(service: self, registry: registry) }
  1200. }
  1201. }
  1202. /// Describes an individual service method.
  1203. ///
  1204. /// SwiftProtobuf does *not* generate anything for these (or services), but
  1205. /// they are here to support things that generate based off RPCs defined in
  1206. /// .proto file (gRPC, etc.).
  1207. public final class MethodDescriptor {
  1208. /// The name of the method, not including its containing scope.
  1209. public let name: String
  1210. /// The fully-qualified name of the method, scope delimited by periods.
  1211. public var fullName: String { return "\(service.fullName).\(name)" }
  1212. /// Index of this service within the file's services.
  1213. public let index: Int
  1214. /// The .proto file in which this service was defined
  1215. public var file: FileDescriptor! { return service.file }
  1216. /// The service tha defines this method.
  1217. public var service: ServiceDescriptor! { return _service! }
  1218. /// The resolved features for this Method.
  1219. public let features: Google_Protobuf_FeatureSet
  1220. /// Get `Google_Protobuf_MethodOptions` for this method.
  1221. public let options: Google_Protobuf_MethodOptions
  1222. /// The type of protocol message which this method accepts as input.
  1223. public private(set) var inputType: Descriptor!
  1224. /// The type of protocol message which this message produces as output.
  1225. public private(set) var outputType: Descriptor!
  1226. /// Whether the client streams multiple requests.
  1227. public let clientStreaming: Bool
  1228. // Whether the server streams multiple responses.
  1229. public let serverStreaming: Bool
  1230. /// The proto version of the descriptor that defines this method.
  1231. @available(*, deprecated,
  1232. message: "Use the properties directly or open a GitHub issue for something missing")
  1233. public var proto: Google_Protobuf_MethodDescriptorProto { return _proto }
  1234. private let _proto: Google_Protobuf_MethodDescriptorProto
  1235. // Storage for `service`, will be set by bind()
  1236. private unowned var _service: ServiceDescriptor?
  1237. fileprivate init(proto: Google_Protobuf_MethodDescriptorProto,
  1238. index: Int,
  1239. features: Google_Protobuf_FeatureSet,
  1240. registry: Registry) {
  1241. self.name = proto.name
  1242. self.index = index
  1243. self.features = features
  1244. self.options = proto.options
  1245. self.clientStreaming = proto.clientStreaming
  1246. self.serverStreaming = proto.serverStreaming
  1247. // Can look these up because all the Descriptors are already registered
  1248. self.inputType = registry.descriptor(named: proto.inputType)!
  1249. self.outputType = registry.descriptor(named: proto.outputType)!
  1250. self._proto = proto
  1251. }
  1252. fileprivate func bind(service: ServiceDescriptor, registry: Registry) {
  1253. self._service = service
  1254. }
  1255. }
  1256. /// Helper used under the hood to build the mapping tables and look things up.
  1257. ///
  1258. /// All fullNames are like defined in descriptor.proto, they start with a
  1259. /// leading '.'. This simplifies the string ops when assembling the message
  1260. /// graph.
  1261. fileprivate final class Registry {
  1262. private var fileMap = [String:FileDescriptor]()
  1263. // These three are all keyed by the full_name prefixed with a '.'.
  1264. private var messageMap = [String:Descriptor]()
  1265. private var enumMap = [String:EnumDescriptor]()
  1266. private var serviceMap = [String:ServiceDescriptor]()
  1267. init() {}
  1268. func register(file: FileDescriptor) {
  1269. fileMap[file.name] = file
  1270. }
  1271. func register(message: Descriptor) {
  1272. messageMap[".\(message.fullName)"] = message
  1273. }
  1274. func register(enum e: EnumDescriptor) {
  1275. enumMap[".\(e.fullName)"] = e
  1276. }
  1277. func register(service: ServiceDescriptor) {
  1278. serviceMap[".\(service.fullName)"] = service
  1279. }
  1280. func fileDescriptor(named name: String) -> FileDescriptor? {
  1281. return fileMap[name]
  1282. }
  1283. func descriptor(named fullName: String) -> Descriptor? {
  1284. return messageMap[fullName]
  1285. }
  1286. func enumDescriptor(named fullName: String) -> EnumDescriptor? {
  1287. return enumMap[fullName]
  1288. }
  1289. func serviceDescriptor(named fullName: String) -> ServiceDescriptor? {
  1290. return serviceMap[fullName]
  1291. }
  1292. }
  1293. /// Helper for making an enum associated value `unowned`.
  1294. fileprivate struct UnownedBox<T: AnyObject> {
  1295. unowned let value: T
  1296. }