GPBDescriptor_PackagePrivate.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. //
  4. // Use of this source code is governed by a BSD-style
  5. // license that can be found in the LICENSE file or at
  6. // https://developers.google.com/open-source/licenses/bsd
  7. // This header is private to the ProtobolBuffers library and must NOT be
  8. // included by any sources outside this library. The contents of this file are
  9. // subject to change at any time without notice.
  10. #import "GPBDescriptor.h"
  11. #import "GPBWireFormat.h"
  12. // Describes attributes of the field.
  13. typedef NS_OPTIONS(uint16_t, GPBFieldFlags) {
  14. GPBFieldNone = 0,
  15. // These map to standard protobuf concepts.
  16. GPBFieldRequired = 1 << 0,
  17. GPBFieldRepeated = 1 << 1,
  18. GPBFieldPacked = 1 << 2,
  19. GPBFieldOptional = 1 << 3,
  20. GPBFieldHasDefaultValue = 1 << 4,
  21. // Indicate that the field should "clear" when set to zero value. This is the
  22. // proto3 non optional behavior for singular data (ints, data, string, enum)
  23. // fields.
  24. GPBFieldClearHasIvarOnZero = 1 << 5,
  25. // Indicates the field needs custom handling for the TextFormat name, if not
  26. // set, the name can be derived from the ObjC name.
  27. GPBFieldTextFormatNameCustom = 1 << 6,
  28. // This flag has never had any meaning, it was set on all enum fields.
  29. GPBFieldHasEnumDescriptor = 1 << 7,
  30. // These are not standard protobuf concepts, they are specific to the
  31. // Objective C runtime.
  32. // These bits are used to mark the field as a map and what the key
  33. // type is.
  34. GPBFieldMapKeyMask = 0xF << 8,
  35. GPBFieldMapKeyInt32 = 1 << 8,
  36. GPBFieldMapKeyInt64 = 2 << 8,
  37. GPBFieldMapKeyUInt32 = 3 << 8,
  38. GPBFieldMapKeyUInt64 = 4 << 8,
  39. GPBFieldMapKeySInt32 = 5 << 8,
  40. GPBFieldMapKeySInt64 = 6 << 8,
  41. GPBFieldMapKeyFixed32 = 7 << 8,
  42. GPBFieldMapKeyFixed64 = 8 << 8,
  43. GPBFieldMapKeySFixed32 = 9 << 8,
  44. GPBFieldMapKeySFixed64 = 10 << 8,
  45. GPBFieldMapKeyBool = 11 << 8,
  46. GPBFieldMapKeyString = 12 << 8,
  47. // If the enum for this field is "closed", meaning that it:
  48. // - Has a fixed set of named values.
  49. // - Encountering values not in this set causes them to be treated as unknown
  50. // fields.
  51. // - The first value (i.e., the default) may be nonzero.
  52. // NOTE: This could be tracked just on the GPBEnumDescriptor, but to support
  53. // previously generated code, there would be not data to get the behavior
  54. // correct, so instead it is tracked on the field. If old source compatibility
  55. // is removed, this could be removed and the GPBEnumDescription fetched from
  56. // the GPBFieldDescriptor instead.
  57. GPBFieldClosedEnum = 1 << 12,
  58. };
  59. // NOTE: The structures defined here have their members ordered to minimize
  60. // their size. This directly impacts the size of apps since these exist per
  61. // field/extension.
  62. typedef struct GPBFileDescription {
  63. // The proto package for the file.
  64. const char *package;
  65. // The objc_class_prefix option if present.
  66. const char *prefix;
  67. // The file's proto syntax.
  68. GPBFileSyntax syntax;
  69. } GPBFileDescription;
  70. // Describes a single field in a protobuf as it is represented as an ivar.
  71. typedef struct GPBMessageFieldDescription {
  72. // Name of ivar.
  73. // Note that we looked into using a SEL here instead (which really is just a C string)
  74. // but there is not a way to initialize an SEL with a constant (@selector is not constant) so the
  75. // additional code generated to initialize the value is actually bigger in size than just using a
  76. // C identifier for large apps.
  77. const char *name;
  78. union {
  79. // className is deprecated and will be removed in favor of clazz.
  80. // kept around right now for backwards compatibility.
  81. // clazz is used iff GPBDescriptorInitializationFlag_UsesClassRefs is set.
  82. char *className; // Name of the class of the message.
  83. Class clazz; // Class of the message.
  84. // For enums only.
  85. GPBEnumDescriptorFunc enumDescFunc;
  86. } dataTypeSpecific;
  87. // The field number for the ivar.
  88. uint32_t number;
  89. // The index (in bits) into _has_storage_.
  90. // >= 0: the bit to use for a value being set.
  91. // = GPBNoHasBit(INT32_MAX): no storage used.
  92. // < 0: in a oneOf, use a full int32 to record the field active.
  93. int32_t hasIndex;
  94. // Offset of the variable into it's structure struct.
  95. uint32_t offset;
  96. // Field flags. Use accessor functions below.
  97. GPBFieldFlags flags;
  98. // Data type of the ivar.
  99. GPBDataType dataType;
  100. } GPBMessageFieldDescription;
  101. // If a message uses fields where they provide default values that are non zero, then this
  102. // struct is used to provide the values along with the field info.
  103. typedef struct GPBMessageFieldDescriptionWithDefault {
  104. // Default value for the ivar.
  105. GPBGenericValue defaultValue;
  106. GPBMessageFieldDescription core;
  107. } GPBMessageFieldDescriptionWithDefault;
  108. // Describes attributes of the extension.
  109. typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) {
  110. GPBExtensionNone = 0,
  111. // These map to standard protobuf concepts.
  112. GPBExtensionRepeated = 1 << 0,
  113. GPBExtensionPacked = 1 << 1,
  114. GPBExtensionSetWireFormat = 1 << 2,
  115. };
  116. // An extension
  117. typedef struct GPBExtensionDescription {
  118. GPBGenericValue defaultValue;
  119. const char *singletonName;
  120. // Before 3.12, `extendedClass` was just a `const char *`. Thanks to nested
  121. // initialization
  122. // (https://en.cppreference.com/w/c/language/struct_initialization#Nested_initialization) old
  123. // generated code with `.extendedClass = GPBStringifySymbol(Something)` still works; and the
  124. // current generator can use `extendedClass.clazz`, to pass a Class reference.
  125. union {
  126. const char *name;
  127. Class clazz;
  128. } extendedClass;
  129. // Before 3.12, this was `const char *messageOrGroupClassName`. In the
  130. // initial 3.12 release, we moved the `union messageOrGroupClass`, and failed
  131. // to realize that would break existing source code for extensions. So to
  132. // keep existing source code working, we added an unnamed union (C11) to
  133. // provide both the old field name and the new union. This keeps both older
  134. // and newer code working.
  135. // Background: https://github.com/protocolbuffers/protobuf/issues/7555
  136. union {
  137. const char *messageOrGroupClassName;
  138. union {
  139. const char *name;
  140. Class clazz;
  141. } messageOrGroupClass;
  142. };
  143. GPBEnumDescriptorFunc enumDescriptorFunc;
  144. int32_t fieldNumber;
  145. GPBDataType dataType;
  146. GPBExtensionOptions options;
  147. } GPBExtensionDescription;
  148. typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
  149. GPBDescriptorInitializationFlag_None = 0,
  150. GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0,
  151. GPBDescriptorInitializationFlag_WireFormat = 1 << 1,
  152. // This is used as a stopgap as we move from using class names to class
  153. // references. The runtime needs to support both until we allow a
  154. // breaking change in the runtime.
  155. GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2,
  156. // This flag is used to indicate that the generated sources already contain
  157. // the `GPBFieldClearHasIvarOnZero` flag and it doesn't have to be computed
  158. // at startup. This allows older generated code to still work with the
  159. // current runtime library.
  160. GPBDescriptorInitializationFlag_Proto3OptionalKnown = 1 << 3,
  161. // This flag is used to indicate that the generated sources already contain
  162. // the `GPBFieldCloseEnum` flag and it doesn't have to be computed at startup.
  163. // This allows the older generated code to still work with the current runtime
  164. // library.
  165. GPBDescriptorInitializationFlag_ClosedEnumSupportKnown = 1 << 4,
  166. };
  167. @interface GPBDescriptor () {
  168. @package
  169. NSArray *fields_;
  170. NSArray *oneofs_;
  171. uint32_t storageSize_;
  172. }
  173. // fieldDescriptions and fileDescription have to be long lived, they are held as raw pointers.
  174. + (instancetype)allocDescriptorForClass:(Class)messageClass
  175. messageName:(NSString *)messageName
  176. fileDescription:(GPBFileDescription *)fileDescription
  177. fields:(void *)fieldDescriptions
  178. fieldCount:(uint32_t)fieldCount
  179. storageSize:(uint32_t)storageSize
  180. flags:(GPBDescriptorInitializationFlags)flags;
  181. // Called right after init to provide extra information to avoid init having
  182. // an explosion of args. These pointers are recorded, so they are expected
  183. // to live for the lifetime of the app.
  184. - (void)setupOneofs:(const char **)oneofNames
  185. count:(uint32_t)count
  186. firstHasIndex:(int32_t)firstHasIndex;
  187. - (void)setupExtraTextInfo:(const char *)extraTextFormatInfo;
  188. - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count;
  189. - (void)setupContainingMessageClass:(Class)msgClass;
  190. // Deprecated, these remain to support older versions of source generation.
  191. + (instancetype)allocDescriptorForClass:(Class)messageClass
  192. file:(GPBFileDescriptor *)file
  193. fields:(void *)fieldDescriptions
  194. fieldCount:(uint32_t)fieldCount
  195. storageSize:(uint32_t)storageSize
  196. flags:(GPBDescriptorInitializationFlags)flags
  197. __attribute__((deprecated("Please use a newer version of protoc to regenerate your sources. "
  198. "Support for this version will go away in the future.")));
  199. + (instancetype)allocDescriptorForClass:(Class)messageClass
  200. rootClass:(Class)rootClass
  201. file:(GPBFileDescriptor *)file
  202. fields:(void *)fieldDescriptions
  203. fieldCount:(uint32_t)fieldCount
  204. storageSize:(uint32_t)storageSize
  205. flags:(GPBDescriptorInitializationFlags)flags
  206. __attribute__((deprecated("Please use a newer version of protoc to regenerate your sources. "
  207. "Support for this version will go away in the future.")));
  208. - (void)setupContainingMessageClassName:(const char *)msgClassName
  209. __attribute__((deprecated("Please use a newer version of protoc to regenerate your sources. "
  210. "Support for this version will go away in the future.")));
  211. - (void)setupMessageClassNameSuffix:(NSString *)suffix
  212. __attribute__((deprecated("Please use a newer version of protoc to regenerate your sources. "
  213. "Support for this version will go away in the future.")));
  214. @end
  215. @interface GPBFileDescriptor ()
  216. - (instancetype)initWithPackage:(NSString *)package
  217. objcPrefix:(NSString *)objcPrefix
  218. syntax:(GPBFileSyntax)syntax;
  219. - (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax;
  220. @end
  221. @interface GPBOneofDescriptor () {
  222. @package
  223. const char *name_;
  224. NSArray *fields_;
  225. }
  226. // name must be long lived.
  227. - (instancetype)initWithName:(const char *)name fields:(NSArray *)fields;
  228. @end
  229. @interface GPBFieldDescriptor () {
  230. @package
  231. GPBMessageFieldDescription *description_;
  232. GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_;
  233. }
  234. @end
  235. typedef NS_OPTIONS(uint32_t, GPBEnumDescriptorInitializationFlags) {
  236. GPBEnumDescriptorInitializationFlag_None = 0,
  237. // Available: 1 << 0
  238. // Marks this enum as a closed enum.
  239. GPBEnumDescriptorInitializationFlag_IsClosed = 1 << 1,
  240. };
  241. @interface GPBEnumDescriptor ()
  242. // valueNames, values and extraTextFormatInfo have to be long lived, they are
  243. // held as raw pointers.
  244. + (instancetype)allocDescriptorForName:(NSString *)name
  245. valueNames:(const char *)valueNames
  246. values:(const int32_t *)values
  247. count:(uint32_t)valueCount
  248. enumVerifier:(GPBEnumValidationFunc)enumVerifier
  249. flags:(GPBEnumDescriptorInitializationFlags)flags;
  250. + (instancetype)allocDescriptorForName:(NSString *)name
  251. valueNames:(const char *)valueNames
  252. values:(const int32_t *)values
  253. count:(uint32_t)valueCount
  254. enumVerifier:(GPBEnumValidationFunc)enumVerifier
  255. flags:(GPBEnumDescriptorInitializationFlags)flags
  256. extraTextFormatInfo:(const char *)extraTextFormatInfo;
  257. // Deprecated, these remain to support older versions of source generation.
  258. + (instancetype)allocDescriptorForName:(NSString *)name
  259. valueNames:(const char *)valueNames
  260. values:(const int32_t *)values
  261. count:(uint32_t)valueCount
  262. enumVerifier:(GPBEnumValidationFunc)enumVerifier
  263. __attribute__((deprecated("Please use a newer version of protoc to regenerate your sources. "
  264. "Support for this version will go away in the future.")));
  265. + (instancetype)allocDescriptorForName:(NSString *)name
  266. valueNames:(const char *)valueNames
  267. values:(const int32_t *)values
  268. count:(uint32_t)valueCount
  269. enumVerifier:(GPBEnumValidationFunc)enumVerifier
  270. extraTextFormatInfo:(const char *)extraTextFormatInfo
  271. __attribute__((deprecated("Please use a newer version of protoc to regenerate your sources. "
  272. "Support for this version will go away in the future.")));
  273. @end
  274. @interface GPBExtensionDescriptor () {
  275. @package
  276. GPBExtensionDescription *description_;
  277. }
  278. @property(nonatomic, readonly) GPBWireFormat wireType;
  279. // For repeated extensions, alternateWireType is the wireType with the opposite
  280. // value for the packable property. i.e. - if the extension was marked packed
  281. // it would be the wire type for unpacked; if the extension was marked unpacked,
  282. // it would be the wire type for packed.
  283. @property(nonatomic, readonly) GPBWireFormat alternateWireType;
  284. // description has to be long lived, it is held as a raw pointer.
  285. - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc
  286. usesClassRefs:(BOOL)usesClassRefs;
  287. // Deprecated. Calls above with `usesClassRefs = NO`
  288. - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc
  289. __attribute__((deprecated("Please use a newer version of protoc to regenerate your sources. "
  290. "Support for this version will go away in the future.")));
  291. - (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other;
  292. @end
  293. CF_EXTERN_C_BEGIN
  294. // Direct access is use for speed, to avoid even internally declaring things
  295. // read/write, etc. The warning is enabled in the project to ensure code calling
  296. // protos can turn on -Wdirect-ivar-access without issues.
  297. #pragma clang diagnostic push
  298. #pragma clang diagnostic ignored "-Wdirect-ivar-access"
  299. GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) {
  300. return (field->description_->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
  301. }
  302. GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) {
  303. return field->description_->dataType;
  304. }
  305. GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) {
  306. return field->description_->hasIndex;
  307. }
  308. GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) {
  309. return field->description_->number;
  310. }
  311. GPB_INLINE BOOL GPBFieldIsClosedEnum(GPBFieldDescriptor *field) {
  312. return (field->description_->flags & GPBFieldClosedEnum) != 0;
  313. }
  314. #pragma clang diagnostic pop
  315. uint32_t GPBFieldTag(GPBFieldDescriptor *self);
  316. // For repeated fields, alternateWireType is the wireType with the opposite
  317. // value for the packable property. i.e. - if the field was marked packed it
  318. // would be the wire type for unpacked; if the field was marked unpacked, it
  319. // would be the wire type for packed.
  320. uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self);
  321. GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) {
  322. return (description->options & GPBExtensionRepeated) != 0;
  323. }
  324. GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) {
  325. return (description->options & GPBExtensionPacked) != 0;
  326. }
  327. GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) {
  328. return (description->options & GPBExtensionSetWireFormat) != 0;
  329. }
  330. // Helper for compile time assets.
  331. #ifndef GPBInternalCompileAssert
  332. #define GPBInternalCompileAssert(test, msg) _Static_assert((test), #msg)
  333. #endif // GPBInternalCompileAssert
  334. // Sanity check that there isn't padding between the field description
  335. // structures with and without a default.
  336. GPBInternalCompileAssert(sizeof(GPBMessageFieldDescriptionWithDefault) ==
  337. (sizeof(GPBGenericValue) + sizeof(GPBMessageFieldDescription)),
  338. DescriptionsWithDefault_different_size_than_expected);
  339. CF_EXTERN_C_END