Descriptor.swift 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596
  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. /// This should never be called directly. Use isRequired and isRepeated
  966. /// helper methods instead.
  967. @available(*, deprecated, message: "Use isRequired or isRepeated instead.")
  968. public var label: Google_Protobuf_FieldDescriptorProto.Label {
  969. if isRepeated {
  970. return .repeated
  971. } else if isRequired {
  972. return .required
  973. } else {
  974. return .optional
  975. }
  976. }
  977. // Storage for `label`, used by other apis.
  978. private var _label: Google_Protobuf_FieldDescriptorProto.Label
  979. /// Whether or not the field is required. For proto2 required fields and
  980. /// Editions `LEGACY_REQUIRED` fields.
  981. public var isRequired: Bool {
  982. // Implementation comes from FieldDescriptor::is_required()
  983. features.fieldPresence == .legacyRequired
  984. }
  985. /// Whether or not the field is repeated/map field.
  986. public var isRepeated: Bool { _label == .repeated }
  987. /// Use !isRequired() && !isRepeated() instead.
  988. @available(*, deprecated, message: "Use !isRequired && !isRepeated instead.")
  989. public var isOptional: Bool { label == .optional }
  990. /// Is this field packable.
  991. public var isPackable: Bool {
  992. // This logic comes from the C++ FieldDescriptor::is_packable() impl.
  993. isRepeated && FieldDescriptor.isPackable(type: type)
  994. }
  995. /// If this field is packable and packed.
  996. public var isPacked: Bool {
  997. // This logic comes from the C++ FieldDescriptor::is_packed() impl.
  998. guard isPackable else { return false }
  999. return features.repeatedFieldEncoding == .packed
  1000. }
  1001. /// True if this field is a map.
  1002. public var isMap: Bool {
  1003. // This logic comes from the C++ FieldDescriptor::is_map() impl.
  1004. type == .message && messageType!.options.mapEntry
  1005. }
  1006. /// Returns true if this field was syntactically written with "optional" in the
  1007. /// .proto file. Excludes singular proto3 fields that do not have a label.
  1008. package var _hasOptionalKeyword: Bool {
  1009. // This logic comes from the C++ FieldDescriptor::has_optional_keyword()
  1010. // impl.
  1011. proto3Optional || (file.edition == .proto2 && !isRequired && !isRepeated && oneofIndex == nil)
  1012. }
  1013. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  1014. public var hasOptionalKeyword: Bool {
  1015. _hasOptionalKeyword
  1016. }
  1017. /// Returns true if this field tracks presence, ie. does the field
  1018. /// distinguish between "unset" and "present with default value."
  1019. /// This includes required, optional, and oneof fields. It excludes maps,
  1020. /// repeated fields, and singular proto3 fields without "optional".
  1021. public var hasPresence: Bool {
  1022. // This logic comes from the C++ FieldDescriptor::has_presence() impl.
  1023. guard !isRepeated else { return false }
  1024. switch type {
  1025. case .group, .message:
  1026. // Groups/messages always get field presence.
  1027. return true
  1028. default:
  1029. break
  1030. }
  1031. return isExtension || oneofIndex != nil || features.fieldPresence != .implicit
  1032. }
  1033. /// Returns true if this is a string field and should do UTF-8 validation.
  1034. ///
  1035. /// This api is for completeness, but it likely should never be used. The
  1036. /// concept comes from the C++ FieldDescriptory::requires_utf8_validation(),
  1037. /// but doesn't make a lot of sense for Swift Protobuf because `string` fields
  1038. /// are modeled as Swift `String` objects, and thus they always have to be
  1039. /// valid UTF-8. If something were to try putting something else in the field,
  1040. /// the library won't be able to parse it. While that sounds bad, other
  1041. /// languages have similar issues with their _string_ types and thus have the
  1042. /// same issues.
  1043. public var requiresUTF8Validation: Bool {
  1044. type == .string && features.utf8Validation == .verify
  1045. }
  1046. /// Index of this field within the message's fields, or the file or
  1047. /// extension scope's extensions.
  1048. public let index: Int
  1049. /// The explicitly declared default value for this field.
  1050. ///
  1051. /// This is the *raw* string value from the .proto file that was listed as
  1052. /// the default, it is up to the consumer to convert it correctly for the
  1053. /// type of this field. The C++ FieldDescriptor does offer some apis to
  1054. /// help with that, but at this time, that is not provided here.
  1055. @available(*, deprecated, renamed: "defaultValue")
  1056. public var explicitDefaultValue: String? {
  1057. defaultValue
  1058. }
  1059. /// The explicitly declared default value for this field.
  1060. ///
  1061. /// This is the *raw* string value from the .proto file that was listed as
  1062. /// the default, it is up to the consumer to convert it correctly for the
  1063. /// type of this field. The C++ FieldDescriptor does offer some apis to
  1064. /// help with that, but at this time, that is not provided here.
  1065. public let defaultValue: String?
  1066. /// The `Descriptor` of the message which this is a field of. For extensions,
  1067. /// this is the extended type.
  1068. public var containingType: Descriptor! { _containingType! }
  1069. /// The oneof this field is a member of.
  1070. @available(*, deprecated, renamed: "containingOneof")
  1071. public var oneof: OneofDescriptor? {
  1072. containingOneof
  1073. }
  1074. /// The oneof this field is a member of.
  1075. public var containingOneof: OneofDescriptor? {
  1076. guard let oneofIndex = oneofIndex else { return nil }
  1077. return containingType.oneofs[Int(oneofIndex)]
  1078. }
  1079. /// The non synthetic oneof this field is a member of.
  1080. @available(*, deprecated, renamed: "realContainingOneof")
  1081. public var realOneof: OneofDescriptor? {
  1082. realContainingOneof
  1083. }
  1084. /// The non synthetic oneof this field is a member of.
  1085. public var realContainingOneof: OneofDescriptor? {
  1086. guard let oneof = containingOneof, !oneof._isSynthetic else { return nil }
  1087. return oneof
  1088. }
  1089. /// The index in a oneof this field is in.
  1090. public let oneofIndex: Int32?
  1091. // This builds basically a union for the storage for `extensionScope`
  1092. // and the value to look it up with.
  1093. private enum ExtensionScopeStorage {
  1094. case extendee(String) // The value to be used for looked up during `bind()`.
  1095. case message(UnownedBox<Descriptor>)
  1096. }
  1097. private var _extensionScopeStorage: ExtensionScopeStorage?
  1098. /// Extensions can be declared within the scope of another message. If this
  1099. /// is an extension field, then this will be the scope it was declared in
  1100. /// nil if was declared at a global scope.
  1101. public var extensionScope: Descriptor? {
  1102. guard case .message(let boxed) = _extensionScopeStorage else { return nil }
  1103. return boxed.value
  1104. }
  1105. // This builds basically a union for the storage for `messageType`
  1106. // and `enumType` since only one can needed at a time.
  1107. private enum FieldTypeStorage {
  1108. case typeName(String) // The value to be looked up during `bind()`.
  1109. case message(UnownedBox<Descriptor>)
  1110. case `enum`(UnownedBox<EnumDescriptor>)
  1111. }
  1112. private var _fieldTypeStorage: FieldTypeStorage?
  1113. /// When this is a message/group field, that message's `Descriptor`.
  1114. public var messageType: Descriptor! {
  1115. guard case .message(let boxed) = _fieldTypeStorage else { return nil }
  1116. return boxed.value
  1117. }
  1118. /// When this is a enum field, that enum's `EnumDescriptor`.
  1119. public var enumType: EnumDescriptor! {
  1120. guard case .enum(let boxed) = _fieldTypeStorage else { return nil }
  1121. return boxed.value
  1122. }
  1123. /// The FieldOptions for this field.
  1124. public var options: Google_Protobuf_FieldOptions
  1125. let proto3Optional: Bool
  1126. // Storage for `containingType`, will be set by bind()
  1127. private unowned var _containingType: Descriptor?
  1128. // Storage for `file`, will be set by bind()
  1129. private unowned var _file: FileDescriptor?
  1130. fileprivate convenience init(
  1131. messageField proto: Google_Protobuf_FieldDescriptorProto,
  1132. index: Int,
  1133. parentFeatures: Google_Protobuf_FeatureSet,
  1134. featureResolver: FeatureResolver,
  1135. registry: Registry
  1136. ) {
  1137. precondition(proto.extendee.isEmpty) // Only for extensions
  1138. // On regular fields, it only makes sense to get `.proto3Optional`
  1139. // when also in a (synthetic) oneof. So...no oneof index, it better
  1140. // not be `.proto3Optional`
  1141. precondition(proto.hasOneofIndex || !proto.proto3Optional)
  1142. self.init(
  1143. proto: proto,
  1144. index: index,
  1145. parentFeatures: parentFeatures,
  1146. featureResolver: featureResolver,
  1147. registry: registry,
  1148. isExtension: false
  1149. )
  1150. }
  1151. fileprivate convenience init(
  1152. extension proto: Google_Protobuf_FieldDescriptorProto,
  1153. index: Int,
  1154. parentFeatures: Google_Protobuf_FeatureSet,
  1155. featureResolver: FeatureResolver,
  1156. registry: Registry
  1157. ) {
  1158. precondition(!proto.extendee.isEmpty) // Required for extensions
  1159. // FieldDescriptorProto is used for fields or extensions, generally
  1160. // .proto3Optional only makes sense on fields if it is in a oneof. But,
  1161. // it is allowed on extensions. For information on that, see
  1162. // https://github.com/protocolbuffers/protobuf/issues/8234#issuecomment-774224376
  1163. // The C++ Descriptor code encorces the field/oneof part, but nothing
  1164. // is checked on the oneof side.
  1165. precondition(!proto.hasOneofIndex)
  1166. self.init(
  1167. proto: proto,
  1168. index: index,
  1169. parentFeatures: parentFeatures,
  1170. featureResolver: featureResolver,
  1171. registry: registry,
  1172. isExtension: true
  1173. )
  1174. }
  1175. private init(
  1176. proto: Google_Protobuf_FieldDescriptorProto,
  1177. index: Int,
  1178. parentFeatures: Google_Protobuf_FeatureSet,
  1179. featureResolver: FeatureResolver,
  1180. registry: Registry,
  1181. isExtension: Bool
  1182. ) {
  1183. self._proto = proto
  1184. self.name = proto.name
  1185. self.index = index
  1186. self.features = featureResolver.resolve(proto, resolvedParent: parentFeatures)
  1187. self.defaultValue = proto.hasDefaultValue ? proto.defaultValue : nil
  1188. precondition(proto.hasJsonName) // protoc should always set the name
  1189. self.jsonName = proto.jsonName
  1190. self.isExtension = isExtension
  1191. self.number = proto.number
  1192. // This remapping is based follow part of what upstream
  1193. // `DescriptorBuilder::PostProcessFieldFeatures()` does. It is needed to
  1194. // help ensure basic transforms from .proto2 to .edition2023 generate the
  1195. // same code/behaviors.
  1196. if proto.type == .message && self.features.messageEncoding == .delimited {
  1197. self.type = .group
  1198. } else {
  1199. self.type = proto.type
  1200. }
  1201. // This remapping is based follow part of what upstream
  1202. // `DescriptorBuilder::PostProcessFieldFeatures()` does. If generators use
  1203. // helper instead of access `label` directly, they won't need this, but for
  1204. // consistency, remap `label` to expose the pre Editions/Features value.
  1205. if self.features.fieldPresence == .legacyRequired && proto.label == .optional {
  1206. self._label = .required
  1207. } else {
  1208. self._label = proto.label
  1209. }
  1210. self.options = proto.options
  1211. self.oneofIndex = proto.hasOneofIndex ? proto.oneofIndex : nil
  1212. self.proto3Optional = proto.proto3Optional
  1213. self._extensionScopeStorage = isExtension ? .extendee(proto.extendee) : nil
  1214. switch type {
  1215. case .group, .message, .enum:
  1216. _fieldTypeStorage = .typeName(proto.typeName)
  1217. default:
  1218. _fieldTypeStorage = nil
  1219. }
  1220. }
  1221. fileprivate func bind(file: FileDescriptor, registry: Registry, containingType: Descriptor?) {
  1222. _file = file
  1223. // See the defintions of `containingType` and `extensionScope`, this
  1224. // dance can otherwise be a little confusing.
  1225. if case .extendee(let extendee) = _extensionScopeStorage {
  1226. _containingType = registry.descriptor(named: extendee)!
  1227. if let containingType = containingType {
  1228. _extensionScopeStorage = .message(UnownedBox(value: containingType))
  1229. } else {
  1230. _extensionScopeStorage = nil // Top level
  1231. }
  1232. } else {
  1233. _containingType = containingType
  1234. }
  1235. if case .typeName(let typeName) = _fieldTypeStorage {
  1236. if type == .enum {
  1237. _fieldTypeStorage = .enum(UnownedBox(value: registry.enumDescriptor(named: typeName)!))
  1238. } else {
  1239. let msgtype = registry.descriptor(named: typeName)!
  1240. _fieldTypeStorage = .message(UnownedBox(value: msgtype))
  1241. if type == .group
  1242. && (msgtype.options.mapEntry || (_containingType != nil && _containingType!.options.mapEntry))
  1243. {
  1244. type = .message
  1245. }
  1246. }
  1247. }
  1248. }
  1249. }
  1250. /// Describes an RPC service.
  1251. ///
  1252. /// SwiftProtobuf does *not* generate anything for these (or methods), but
  1253. /// they are here to support things that generate based off RPCs defined in
  1254. /// .proto file (gRPC, etc.).
  1255. public final class ServiceDescriptor {
  1256. // We can't assign a value directly to `proto` in the init because we get the
  1257. // deprecation warning. This private prop only exists as a workaround to avoid
  1258. // this warning and preserve backwards compatibility - it should be removed
  1259. // when removing `proto`.
  1260. private let _proto: Google_Protobuf_ServiceDescriptorProto
  1261. @available(*, deprecated, message: "Please open a GitHub issue if you think functionality is missing.")
  1262. public var proto: Google_Protobuf_ServiceDescriptorProto {
  1263. _proto
  1264. }
  1265. /// The name of the service, not including its containing scope.
  1266. public let name: String
  1267. /// The fully-qualified name of the service, scope delimited by periods.
  1268. public let fullName: String
  1269. /// Index of this service within the file's services.
  1270. public let index: Int
  1271. /// The .proto file in which this service was defined
  1272. public var file: FileDescriptor! { _file! }
  1273. /// The resolved features for this Service.
  1274. public let features: Google_Protobuf_FeatureSet
  1275. /// Get `Google_Protobuf_ServiceOptions` for this service.
  1276. public let options: Google_Protobuf_ServiceOptions
  1277. /// The methods defined on this service. These are returned in the order they
  1278. /// were defined in the .proto file.
  1279. public let methods: [MethodDescriptor]
  1280. // Storage for `file`, will be set by bind()
  1281. private unowned var _file: FileDescriptor?
  1282. fileprivate init(
  1283. proto: Google_Protobuf_ServiceDescriptorProto,
  1284. index: Int,
  1285. fileFeatures: Google_Protobuf_FeatureSet,
  1286. featureResolver: FeatureResolver,
  1287. registry: Registry,
  1288. scope: String
  1289. ) {
  1290. self._proto = proto
  1291. self.name = proto.name
  1292. self.fullName = scope.isEmpty ? proto.name : "\(scope).\(proto.name)"
  1293. self.index = index
  1294. let resolvedFeatures = featureResolver.resolve(proto.options, resolvedParent: fileFeatures)
  1295. self.features = resolvedFeatures
  1296. self.options = proto.options
  1297. self.methods = proto.method.enumerated().map {
  1298. MethodDescriptor(
  1299. proto: $0.element,
  1300. index: $0.offset,
  1301. features: featureResolver.resolve($0.element.options, resolvedParent: resolvedFeatures),
  1302. registry: registry
  1303. )
  1304. }
  1305. // Done initializing, register ourselves.
  1306. registry.register(service: self)
  1307. }
  1308. fileprivate func bind(file: FileDescriptor, registry: Registry) {
  1309. _file = file
  1310. for m in methods { m.bind(service: self, registry: registry) }
  1311. }
  1312. }
  1313. /// Describes an individual service method.
  1314. ///
  1315. /// SwiftProtobuf does *not* generate anything for these (or services), but
  1316. /// they are here to support things that generate based off RPCs defined in
  1317. /// .proto file (gRPC, etc.).
  1318. public final class MethodDescriptor {
  1319. /// The name of the method, not including its containing scope.
  1320. public let name: String
  1321. /// The fully-qualified name of the method, scope delimited by periods.
  1322. public var fullName: String { "\(service.fullName).\(name)" }
  1323. /// Index of this service within the file's services.
  1324. public let index: Int
  1325. /// The .proto file in which this service was defined
  1326. public var file: FileDescriptor! { service.file }
  1327. /// The service tha defines this method.
  1328. public var service: ServiceDescriptor! { _service! }
  1329. /// The resolved features for this Method.
  1330. public let features: Google_Protobuf_FeatureSet
  1331. /// Get `Google_Protobuf_MethodOptions` for this method.
  1332. public let options: Google_Protobuf_MethodOptions
  1333. /// The type of protocol message which this method accepts as input.
  1334. public private(set) var inputType: Descriptor!
  1335. /// The type of protocol message which this message produces as output.
  1336. public private(set) var outputType: Descriptor!
  1337. /// Whether the client streams multiple requests.
  1338. public let clientStreaming: Bool
  1339. // Whether the server streams multiple responses.
  1340. public let serverStreaming: Bool
  1341. /// The proto version of the descriptor that defines this method.
  1342. @available(
  1343. *,
  1344. deprecated,
  1345. message: "Use the properties directly or open a GitHub issue for something missing"
  1346. )
  1347. public var proto: Google_Protobuf_MethodDescriptorProto { _proto }
  1348. private let _proto: Google_Protobuf_MethodDescriptorProto
  1349. // Storage for `service`, will be set by bind()
  1350. private unowned var _service: ServiceDescriptor?
  1351. fileprivate init(
  1352. proto: Google_Protobuf_MethodDescriptorProto,
  1353. index: Int,
  1354. features: Google_Protobuf_FeatureSet,
  1355. registry: Registry
  1356. ) {
  1357. self.name = proto.name
  1358. self.index = index
  1359. self.features = features
  1360. self.options = proto.options
  1361. self.clientStreaming = proto.clientStreaming
  1362. self.serverStreaming = proto.serverStreaming
  1363. // Can look these up because all the Descriptors are already registered
  1364. self.inputType = registry.descriptor(named: proto.inputType)!
  1365. self.outputType = registry.descriptor(named: proto.outputType)!
  1366. self._proto = proto
  1367. }
  1368. fileprivate func bind(service: ServiceDescriptor, registry: Registry) {
  1369. self._service = service
  1370. }
  1371. }
  1372. /// Helper used under the hood to build the mapping tables and look things up.
  1373. ///
  1374. /// All fullNames are like defined in descriptor.proto, they start with a
  1375. /// leading '.'. This simplifies the string ops when assembling the message
  1376. /// graph.
  1377. private final class Registry {
  1378. private var fileMap = [String: FileDescriptor]()
  1379. // These three are all keyed by the full_name prefixed with a '.'.
  1380. private var messageMap = [String: Descriptor]()
  1381. private var enumMap = [String: EnumDescriptor]()
  1382. private var serviceMap = [String: ServiceDescriptor]()
  1383. init() {}
  1384. func register(file: FileDescriptor) {
  1385. fileMap[file.name] = file
  1386. }
  1387. func register(message: Descriptor) {
  1388. messageMap[".\(message.fullName)"] = message
  1389. }
  1390. func register(enum e: EnumDescriptor) {
  1391. enumMap[".\(e.fullName)"] = e
  1392. }
  1393. func register(service: ServiceDescriptor) {
  1394. serviceMap[".\(service.fullName)"] = service
  1395. }
  1396. func fileDescriptor(named name: String) -> FileDescriptor? {
  1397. fileMap[name]
  1398. }
  1399. func descriptor(named fullName: String) -> Descriptor? {
  1400. messageMap[fullName]
  1401. }
  1402. func enumDescriptor(named fullName: String) -> EnumDescriptor? {
  1403. enumMap[fullName]
  1404. }
  1405. func serviceDescriptor(named fullName: String) -> ServiceDescriptor? {
  1406. serviceMap[fullName]
  1407. }
  1408. }
  1409. /// Helper for making an enum associated value `unowned`.
  1410. private struct UnownedBox<T: AnyObject> {
  1411. unowned let value: T
  1412. }