Descriptor.swift 64 KB

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