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 31 // This header is private to the ProtobolBuffers library and must NOT be 32 // included by any sources outside this library. The contents of this file are 33 // subject to change at any time without notice. 34 35 #import "GPBDescriptor.h" 36 #import "GPBWireFormat.h" 37 38 // Describes attributes of the field. 39 typedef NS_OPTIONS(uint16_t, GPBFieldFlags) { 40 // These map to standard protobuf concepts. 41 GPBFieldRequired = 1 << 0, 42 GPBFieldRepeated = 1 << 1, 43 GPBFieldPacked = 1 << 2, 44 GPBFieldOptional = 1 << 3, 45 GPBFieldHasDefaultValue = 1 << 4, 46 47 // Indicates the field needs custom handling for the TextFormat name, if not 48 // set, the name can be derived from the ObjC name. 49 GPBFieldTextFormatNameCustom = 1 << 6, 50 // Indicates the field has an enum descriptor. 51 GPBFieldHasEnumDescriptor = 1 << 7, 52 53 // These are not standard protobuf concepts, they are specific to the 54 // Objective C runtime. 55 56 // These bits are used to mark the field as a map and what the key 57 // type is. 58 GPBFieldMapKeyMask = 0xF << 8, 59 GPBFieldMapKeyInt32 = 1 << 8, 60 GPBFieldMapKeyInt64 = 2 << 8, 61 GPBFieldMapKeyUInt32 = 3 << 8, 62 GPBFieldMapKeyUInt64 = 4 << 8, 63 GPBFieldMapKeySInt32 = 5 << 8, 64 GPBFieldMapKeySInt64 = 6 << 8, 65 GPBFieldMapKeyFixed32 = 7 << 8, 66 GPBFieldMapKeyFixed64 = 8 << 8, 67 GPBFieldMapKeySFixed32 = 9 << 8, 68 GPBFieldMapKeySFixed64 = 10 << 8, 69 GPBFieldMapKeyBool = 11 << 8, 70 GPBFieldMapKeyString = 12 << 8, 71 }; 72 73 // NOTE: The structures defined here have their members ordered to minimize 74 // their size. This directly impacts the size of apps since these exist per 75 // field/extension. 76 77 // Describes a single field in a protobuf as it is represented as an ivar. 78 typedef struct GPBMessageFieldDescription { 79 // Name of ivar. 80 const char *name; 81 union { 82 const char *className; // Name for message class. 83 // For enums only: If EnumDescriptors are compiled in, it will be that, 84 // otherwise it will be the verifier. 85 GPBEnumDescriptorFunc enumDescFunc; 86 GPBEnumValidationFunc enumVerifier; 87 } dataTypeSpecific; 88 // The field number for the ivar. 89 uint32_t number; 90 // The index (in bits) into _has_storage_. 91 // >= 0: the bit to use for a value being set. 92 // = GPBNoHasBit(INT32_MAX): no storage used. 93 // < 0: in a oneOf, use a full int32 to record the field active. 94 int32_t hasIndex; 95 // Offset of the variable into it's structure struct. 96 uint32_t offset; 97 // Field flags. Use accessor functions below. 98 GPBFieldFlags flags; 99 // Data type of the ivar. 100 GPBDataType dataType; 101 } GPBMessageFieldDescription; 102 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 109 GPBMessageFieldDescription core; 110 } GPBMessageFieldDescriptionWithDefault; 111 112 // Describes attributes of the extension. 113 typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) { 114 // These map to standard protobuf concepts. 115 GPBExtensionRepeated = 1 << 0, 116 GPBExtensionPacked = 1 << 1, 117 GPBExtensionSetWireFormat = 1 << 2, 118 }; 119 120 // An extension 121 typedef struct GPBExtensionDescription { 122 GPBGenericValue defaultValue; 123 const char *singletonName; 124 const char *extendedClass; 125 const char *messageOrGroupClassName; 126 GPBEnumDescriptorFunc enumDescriptorFunc; 127 int32_t fieldNumber; 128 GPBDataType dataType; 129 GPBExtensionOptions options; 130 } GPBExtensionDescription; 131 132 typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { 133 GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0, 134 GPBDescriptorInitializationFlag_WireFormat = 1 << 1, 135 }; 136 137 @interface GPBDescriptor () { 138 @package 139 NSArray *fields_; 140 NSArray *oneofs_; 141 uint32_t storageSize_; 142 } 143 144 // fieldDescriptions have to be long lived, they are held as raw pointers. 145 + (instancetype) 146 allocDescriptorForClass:(Class)messageClass 147 rootClass:(Class)rootClass 148 file:(GPBFileDescriptor *)file 149 fields:(void *)fieldDescriptions 150 fieldCount:(uint32_t)fieldCount 151 storageSize:(uint32_t)storageSize 152 flags:(GPBDescriptorInitializationFlags)flags; 153 154 - (instancetype)initWithClass:(Class)messageClass 155 file:(GPBFileDescriptor *)file 156 fields:(NSArray *)fields 157 storageSize:(uint32_t)storage 158 wireFormat:(BOOL)wireFormat; 159 160 // Called right after init to provide extra information to avoid init having 161 // an explosion of args. These pointers are recorded, so they are expected 162 // to live for the lifetime of the app. 163 - (void)setupOneofs:(const char **)oneofNames 164 count:(uint32_t)count 165 firstHasIndex:(int32_t)firstHasIndex; 166 - (void)setupExtraTextInfo:(const char *)extraTextFormatInfo; 167 - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count; 168 169 @end 170 171 @interface GPBFileDescriptor () 172 - (instancetype)initWithPackage:(NSString *)package 173 syntax:(GPBFileSyntax)syntax; 174 @end 175 176 @interface GPBOneofDescriptor () { 177 @package 178 const char *name_; 179 NSArray *fields_; 180 SEL caseSel_; 181 } 182 // name must be long lived. 183 - (instancetype)initWithName:(const char *)name fields:(NSArray *)fields; 184 @end 185 186 @interface GPBFieldDescriptor () { 187 @package 188 GPBMessageFieldDescription *description_; 189 GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_; 190 191 SEL getSel_; 192 SEL setSel_; 193 SEL hasOrCountSel_; // *Count for map<>/repeated fields, has* otherwise. 194 SEL setHasSel_; 195 } 196 197 // Single initializer 198 // description has to be long lived, it is held as a raw pointer. 199 - (instancetype)initWithFieldDescription:(void *)description 200 includesDefault:(BOOL)includesDefault 201 syntax:(GPBFileSyntax)syntax; 202 @end 203 204 @interface GPBEnumDescriptor () 205 // valueNames, values and extraTextFormatInfo have to be long lived, they are 206 // held as raw pointers. 207 + (instancetype) 208 allocDescriptorForName:(NSString *)name 209 valueNames:(const char *)valueNames 210 values:(const int32_t *)values 211 count:(uint32_t)valueCount 212 enumVerifier:(GPBEnumValidationFunc)enumVerifier; 213 + (instancetype) 214 allocDescriptorForName:(NSString *)name 215 valueNames:(const char *)valueNames 216 values:(const int32_t *)values 217 count:(uint32_t)valueCount 218 enumVerifier:(GPBEnumValidationFunc)enumVerifier 219 extraTextFormatInfo:(const char *)extraTextFormatInfo; 220 221 - (instancetype)initWithName:(NSString *)name 222 valueNames:(const char *)valueNames 223 values:(const int32_t *)values 224 count:(uint32_t)valueCount 225 enumVerifier:(GPBEnumValidationFunc)enumVerifier; 226 @end 227 228 @interface GPBExtensionDescriptor () { 229 @package 230 GPBExtensionDescription *description_; 231 } 232 @property(nonatomic, readonly) GPBWireFormat wireType; 233 234 // For repeated extensions, alternateWireType is the wireType with the opposite 235 // value for the packable property. i.e. - if the extension was marked packed 236 // it would be the wire type for unpacked; if the extension was marked unpacked, 237 // it would be the wire type for packed. 238 @property(nonatomic, readonly) GPBWireFormat alternateWireType; 239 240 // description has to be long lived, it is held as a raw pointer. 241 - (instancetype)initWithExtensionDescription: 242 (GPBExtensionDescription *)description; 243 - (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other; 244 @end 245 246 CF_EXTERN_C_BEGIN 247 248 GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) { 249 return (field->description_->flags & 250 (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0; 251 } 252 253 GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) { 254 return field->description_->dataType; 255 } 256 257 GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) { 258 return field->description_->hasIndex; 259 } 260 261 GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) { 262 return field->description_->number; 263 } 264 265 uint32_t GPBFieldTag(GPBFieldDescriptor *self); 266 267 // For repeated fields, alternateWireType is the wireType with the opposite 268 // value for the packable property. i.e. - if the field was marked packed it 269 // would be the wire type for unpacked; if the field was marked unpacked, it 270 // would be the wire type for packed. 271 uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self); 272 273 GPB_INLINE BOOL GPBPreserveUnknownFields(GPBFileSyntax syntax) { 274 return syntax != GPBFileSyntaxProto3; 275 } 276 277 GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) { 278 return syntax == GPBFileSyntaxProto3; 279 } 280 281 GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) { 282 return (description->options & GPBExtensionRepeated) != 0; 283 } 284 285 GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) { 286 return (description->options & GPBExtensionPacked) != 0; 287 } 288 289 GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) { 290 return (description->options & GPBExtensionSetWireFormat) != 0; 291 } 292 293 // Helper for compile time assets. 294 #ifndef _GPBCompileAssert 295 #if __has_feature(c_static_assert) || __has_extension(c_static_assert) 296 #define _GPBCompileAssert(test, msg) _Static_assert((test), #msg) 297 #else 298 // Pre-Xcode 7 support. 299 #define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ## __ ## msg 300 #define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line, msg) 301 #define _GPBCompileAssert(test, msg) \ 302 typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] 303 #endif // __has_feature(c_static_assert) || __has_extension(c_static_assert) 304 #endif // _GPBCompileAssert 305 306 // Sanity check that there isn't padding between the field description 307 // structures with and without a default. 308 _GPBCompileAssert(sizeof(GPBMessageFieldDescriptionWithDefault) == 309 (sizeof(GPBGenericValue) + 310 sizeof(GPBMessageFieldDescription)), 311 DescriptionsWithDefault_different_size_than_expected); 312 313 CF_EXTERN_C_END 314