• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GPBDescriptor()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 
GPBOneofDescriptor()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 
GPBFieldDescriptor()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 
GPBExtensionDescriptor()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 
GPBFieldIsMapOrArray(GPBFieldDescriptor * field)248 GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) {
249   return (field->description_->flags &
250           (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
251 }
252 
GPBGetFieldDataType(GPBFieldDescriptor * field)253 GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) {
254   return field->description_->dataType;
255 }
256 
GPBFieldHasIndex(GPBFieldDescriptor * field)257 GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) {
258   return field->description_->hasIndex;
259 }
260 
GPBFieldNumber(GPBFieldDescriptor * field)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 
GPBPreserveUnknownFields(GPBFileSyntax syntax)273 GPB_INLINE BOOL GPBPreserveUnknownFields(GPBFileSyntax syntax) {
274   return syntax != GPBFileSyntaxProto3;
275 }
276 
GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax)277 GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) {
278   return syntax == GPBFileSyntaxProto3;
279 }
280 
GPBExtensionIsRepeated(GPBExtensionDescription * description)281 GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) {
282   return (description->options & GPBExtensionRepeated) != 0;
283 }
284 
GPBExtensionIsPacked(GPBExtensionDescription * description)285 GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) {
286   return (description->options & GPBExtensionPacked) != 0;
287 }
288 
GPBExtensionIsWireFormat(GPBExtensionDescription * description)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