You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

359 lines
14 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // This header is private to the ProtobolBuffers library and must NOT be
  31. // included by any sources outside this library. The contents of this file are
  32. // subject to change at any time without notice.
  33. #import "GPBDescriptor.h"
  34. #import "GPBWireFormat.h"
  35. // Describes attributes of the field.
  36. typedef NS_OPTIONS(uint16_t, GPBFieldFlags) {
  37. GPBFieldNone = 0,
  38. // These map to standard protobuf concepts.
  39. GPBFieldRequired = 1 << 0,
  40. GPBFieldRepeated = 1 << 1,
  41. GPBFieldPacked = 1 << 2,
  42. GPBFieldOptional = 1 << 3,
  43. GPBFieldHasDefaultValue = 1 << 4,
  44. // Indicate that the field should "clear" when set to zero value. This is the
  45. // proto3 non optional behavior for singular data (ints, data, string, enum)
  46. // fields.
  47. GPBFieldClearHasIvarOnZero = 1 << 5,
  48. // Indicates the field needs custom handling for the TextFormat name, if not
  49. // set, the name can be derived from the ObjC name.
  50. GPBFieldTextFormatNameCustom = 1 << 6,
  51. // Indicates the field has an enum descriptor.
  52. GPBFieldHasEnumDescriptor = 1 << 7,
  53. // These are not standard protobuf concepts, they are specific to the
  54. // Objective C runtime.
  55. // These bits are used to mark the field as a map and what the key
  56. // type is.
  57. GPBFieldMapKeyMask = 0xF << 8,
  58. GPBFieldMapKeyInt32 = 1 << 8,
  59. GPBFieldMapKeyInt64 = 2 << 8,
  60. GPBFieldMapKeyUInt32 = 3 << 8,
  61. GPBFieldMapKeyUInt64 = 4 << 8,
  62. GPBFieldMapKeySInt32 = 5 << 8,
  63. GPBFieldMapKeySInt64 = 6 << 8,
  64. GPBFieldMapKeyFixed32 = 7 << 8,
  65. GPBFieldMapKeyFixed64 = 8 << 8,
  66. GPBFieldMapKeySFixed32 = 9 << 8,
  67. GPBFieldMapKeySFixed64 = 10 << 8,
  68. GPBFieldMapKeyBool = 11 << 8,
  69. GPBFieldMapKeyString = 12 << 8,
  70. };
  71. // NOTE: The structures defined here have their members ordered to minimize
  72. // their size. This directly impacts the size of apps since these exist per
  73. // field/extension.
  74. // Describes a single field in a protobuf as it is represented as an ivar.
  75. typedef struct GPBMessageFieldDescription {
  76. // Name of ivar.
  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: If EnumDescriptors are compiled in, it will be that,
  85. // otherwise it will be the verifier.
  86. GPBEnumDescriptorFunc enumDescFunc;
  87. GPBEnumValidationFunc enumVerifier;
  88. } dataTypeSpecific;
  89. // The field number for the ivar.
  90. uint32_t number;
  91. // The index (in bits) into _has_storage_.
  92. // >= 0: the bit to use for a value being set.
  93. // = GPBNoHasBit(INT32_MAX): no storage used.
  94. // < 0: in a oneOf, use a full int32 to record the field active.
  95. int32_t hasIndex;
  96. // Offset of the variable into it's structure struct.
  97. uint32_t offset;
  98. // Field flags. Use accessor functions below.
  99. GPBFieldFlags flags;
  100. // Data type of the ivar.
  101. GPBDataType dataType;
  102. } GPBMessageFieldDescription;
  103. // Fields in messages defined in a 'proto2' syntax file can provide a default
  104. // value. This struct provides the default along with the field info.
  105. typedef struct GPBMessageFieldDescriptionWithDefault {
  106. // Default value for the ivar.
  107. GPBGenericValue defaultValue;
  108. GPBMessageFieldDescription core;
  109. } GPBMessageFieldDescriptionWithDefault;
  110. // Describes attributes of the extension.
  111. typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) {
  112. GPBExtensionNone = 0,
  113. // These map to standard protobuf concepts.
  114. GPBExtensionRepeated = 1 << 0,
  115. GPBExtensionPacked = 1 << 1,
  116. GPBExtensionSetWireFormat = 1 << 2,
  117. };
  118. // An extension
  119. typedef struct GPBExtensionDescription {
  120. GPBGenericValue defaultValue;
  121. const char *singletonName;
  122. union {
  123. const char *name;
  124. Class clazz;
  125. } extendedClass;
  126. union {
  127. const char *name;
  128. Class clazz;
  129. } messageOrGroupClass;
  130. GPBEnumDescriptorFunc enumDescriptorFunc;
  131. int32_t fieldNumber;
  132. GPBDataType dataType;
  133. GPBExtensionOptions options;
  134. } GPBExtensionDescription;
  135. typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
  136. GPBDescriptorInitializationFlag_None = 0,
  137. GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0,
  138. GPBDescriptorInitializationFlag_WireFormat = 1 << 1,
  139. // This is used as a stopgap as we move from using class names to class
  140. // references. The runtime needs to support both until we allow a
  141. // breaking change in the runtime.
  142. GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2,
  143. // This flag is used to indicate that the generated sources already contain
  144. // the `GPBFieldClearHasIvarOnZero` flag and it doesn't have to be computed
  145. // at startup. This allows older generated code to still work with the
  146. // current runtime library.
  147. GPBDescriptorInitializationFlag_Proto3OptionalKnown = 1 << 3,
  148. };
  149. @interface GPBDescriptor () {
  150. @package
  151. NSArray *fields_;
  152. NSArray *oneofs_;
  153. uint32_t storageSize_;
  154. }
  155. // fieldDescriptions have to be long lived, they are held as raw pointers.
  156. + (instancetype)
  157. allocDescriptorForClass:(Class)messageClass
  158. rootClass:(Class)rootClass
  159. file:(GPBFileDescriptor *)file
  160. fields:(void *)fieldDescriptions
  161. fieldCount:(uint32_t)fieldCount
  162. storageSize:(uint32_t)storageSize
  163. flags:(GPBDescriptorInitializationFlags)flags;
  164. - (instancetype)initWithClass:(Class)messageClass
  165. file:(GPBFileDescriptor *)file
  166. fields:(NSArray *)fields
  167. storageSize:(uint32_t)storage
  168. wireFormat:(BOOL)wireFormat;
  169. // Called right after init to provide extra information to avoid init having
  170. // an explosion of args. These pointers are recorded, so they are expected
  171. // to live for the lifetime of the app.
  172. - (void)setupOneofs:(const char **)oneofNames
  173. count:(uint32_t)count
  174. firstHasIndex:(int32_t)firstHasIndex;
  175. - (void)setupExtraTextInfo:(const char *)extraTextFormatInfo;
  176. - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count;
  177. - (void)setupContainingMessageClass:(Class)msgClass;
  178. - (void)setupMessageClassNameSuffix:(NSString *)suffix;
  179. // Deprecated. Use setupContainingMessageClass instead.
  180. - (void)setupContainingMessageClassName:(const char *)msgClassName;
  181. @end
  182. @interface GPBFileDescriptor ()
  183. - (instancetype)initWithPackage:(NSString *)package
  184. objcPrefix:(NSString *)objcPrefix
  185. syntax:(GPBFileSyntax)syntax;
  186. - (instancetype)initWithPackage:(NSString *)package
  187. syntax:(GPBFileSyntax)syntax;
  188. @end
  189. @interface GPBOneofDescriptor () {
  190. @package
  191. const char *name_;
  192. NSArray *fields_;
  193. SEL caseSel_;
  194. }
  195. // name must be long lived.
  196. - (instancetype)initWithName:(const char *)name fields:(NSArray *)fields;
  197. @end
  198. @interface GPBFieldDescriptor () {
  199. @package
  200. GPBMessageFieldDescription *description_;
  201. GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_;
  202. SEL getSel_;
  203. SEL setSel_;
  204. SEL hasOrCountSel_; // *Count for map<>/repeated fields, has* otherwise.
  205. SEL setHasSel_;
  206. }
  207. // Single initializer
  208. // description has to be long lived, it is held as a raw pointer.
  209. - (instancetype)initWithFieldDescription:(void *)description
  210. includesDefault:(BOOL)includesDefault
  211. usesClassRefs:(BOOL)usesClassRefs
  212. proto3OptionalKnown:(BOOL)proto3OptionalKnown
  213. syntax:(GPBFileSyntax)syntax;
  214. @end
  215. @interface GPBEnumDescriptor ()
  216. // valueNames, values and extraTextFormatInfo have to be long lived, they are
  217. // held as raw pointers.
  218. + (instancetype)
  219. allocDescriptorForName:(NSString *)name
  220. valueNames:(const char *)valueNames
  221. values:(const int32_t *)values
  222. count:(uint32_t)valueCount
  223. enumVerifier:(GPBEnumValidationFunc)enumVerifier;
  224. + (instancetype)
  225. allocDescriptorForName:(NSString *)name
  226. valueNames:(const char *)valueNames
  227. values:(const int32_t *)values
  228. count:(uint32_t)valueCount
  229. enumVerifier:(GPBEnumValidationFunc)enumVerifier
  230. extraTextFormatInfo:(const char *)extraTextFormatInfo;
  231. - (instancetype)initWithName:(NSString *)name
  232. valueNames:(const char *)valueNames
  233. values:(const int32_t *)values
  234. count:(uint32_t)valueCount
  235. enumVerifier:(GPBEnumValidationFunc)enumVerifier;
  236. @end
  237. @interface GPBExtensionDescriptor () {
  238. @package
  239. GPBExtensionDescription *description_;
  240. }
  241. @property(nonatomic, readonly) GPBWireFormat wireType;
  242. // For repeated extensions, alternateWireType is the wireType with the opposite
  243. // value for the packable property. i.e. - if the extension was marked packed
  244. // it would be the wire type for unpacked; if the extension was marked unpacked,
  245. // it would be the wire type for packed.
  246. @property(nonatomic, readonly) GPBWireFormat alternateWireType;
  247. // description has to be long lived, it is held as a raw pointer.
  248. - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc
  249. usesClassRefs:(BOOL)usesClassRefs;
  250. // Deprecated. Calls above with `usesClassRefs = NO`
  251. - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc;
  252. - (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other;
  253. @end
  254. CF_EXTERN_C_BEGIN
  255. // Direct access is use for speed, to avoid even internally declaring things
  256. // read/write, etc. The warning is enabled in the project to ensure code calling
  257. // protos can turn on -Wdirect-ivar-access without issues.
  258. #pragma clang diagnostic push
  259. #pragma clang diagnostic ignored "-Wdirect-ivar-access"
  260. GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) {
  261. return (field->description_->flags &
  262. (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
  263. }
  264. GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) {
  265. return field->description_->dataType;
  266. }
  267. GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) {
  268. return field->description_->hasIndex;
  269. }
  270. GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) {
  271. return field->description_->number;
  272. }
  273. #pragma clang diagnostic pop
  274. uint32_t GPBFieldTag(GPBFieldDescriptor *self);
  275. // For repeated fields, alternateWireType is the wireType with the opposite
  276. // value for the packable property. i.e. - if the field was marked packed it
  277. // would be the wire type for unpacked; if the field was marked unpacked, it
  278. // would be the wire type for packed.
  279. uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self);
  280. GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) {
  281. return syntax == GPBFileSyntaxProto3;
  282. }
  283. GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) {
  284. return (description->options & GPBExtensionRepeated) != 0;
  285. }
  286. GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) {
  287. return (description->options & GPBExtensionPacked) != 0;
  288. }
  289. GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) {
  290. return (description->options & GPBExtensionSetWireFormat) != 0;
  291. }
  292. // Helper for compile time assets.
  293. #ifndef GPBInternalCompileAssert
  294. #if __has_feature(c_static_assert) || __has_extension(c_static_assert)
  295. #define GPBInternalCompileAssert(test, msg) _Static_assert((test), #msg)
  296. #else
  297. // Pre-Xcode 7 support.
  298. #define GPBInternalCompileAssertSymbolInner(line, msg) GPBInternalCompileAssert ## line ## __ ## msg
  299. #define GPBInternalCompileAssertSymbol(line, msg) GPBInternalCompileAssertSymbolInner(line, msg)
  300. #define GPBInternalCompileAssert(test, msg) \
  301. typedef char GPBInternalCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
  302. #endif // __has_feature(c_static_assert) || __has_extension(c_static_assert)
  303. #endif // GPBInternalCompileAssert
  304. // Sanity check that there isn't padding between the field description
  305. // structures with and without a default.
  306. GPBInternalCompileAssert(sizeof(GPBMessageFieldDescriptionWithDefault) ==
  307. (sizeof(GPBGenericValue) +
  308. sizeof(GPBMessageFieldDescription)),
  309. DescriptionsWithDefault_different_size_than_expected);
  310. CF_EXTERN_C_END