Descriptor.swift 62 KB

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