mirror of
https://github.com/protocolbuffers/protobuf
synced 2026-08-26 02:23:14 -04:00
Scrub all the objc related sources for references to "syntax" and update them to no longer tie things accordingly. The ObjC Protos `GPBFileDescriptor` concept still exposes the `syntax`, but it was already marked as deprecated. This will be removed in the future as nothing should need to look at the value. Validate that all generation calls are on the helpers to get the editions support from the C++ code. PiperOrigin-RevId: 555971288
401 lines
16 KiB
Objective-C
401 lines
16 KiB
Objective-C
// Protocol Buffers - Google's data interchange format
|
|
// Copyright 2008 Google Inc. All rights reserved.
|
|
// https://developers.google.com/protocol-buffers/
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following disclaimer
|
|
// in the documentation and/or other materials provided with the
|
|
// distribution.
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
// contributors may be used to endorse or promote products derived from
|
|
// this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
// This header is private to the ProtobolBuffers library and must NOT be
|
|
// included by any sources outside this library. The contents of this file are
|
|
// subject to change at any time without notice.
|
|
|
|
#import "GPBDescriptor.h"
|
|
#import "GPBWireFormat.h"
|
|
|
|
// Describes attributes of the field.
|
|
typedef NS_OPTIONS(uint16_t, GPBFieldFlags) {
|
|
GPBFieldNone = 0,
|
|
// These map to standard protobuf concepts.
|
|
GPBFieldRequired = 1 << 0,
|
|
GPBFieldRepeated = 1 << 1,
|
|
GPBFieldPacked = 1 << 2,
|
|
GPBFieldOptional = 1 << 3,
|
|
GPBFieldHasDefaultValue = 1 << 4,
|
|
|
|
// Indicate that the field should "clear" when set to zero value. This is the
|
|
// proto3 non optional behavior for singular data (ints, data, string, enum)
|
|
// fields.
|
|
GPBFieldClearHasIvarOnZero = 1 << 5,
|
|
// Indicates the field needs custom handling for the TextFormat name, if not
|
|
// set, the name can be derived from the ObjC name.
|
|
GPBFieldTextFormatNameCustom = 1 << 6,
|
|
// This flag has never had any meaning, it was set on all enum fields.
|
|
GPBFieldHasEnumDescriptor = 1 << 7,
|
|
|
|
// These are not standard protobuf concepts, they are specific to the
|
|
// Objective C runtime.
|
|
|
|
// These bits are used to mark the field as a map and what the key
|
|
// type is.
|
|
GPBFieldMapKeyMask = 0xF << 8,
|
|
GPBFieldMapKeyInt32 = 1 << 8,
|
|
GPBFieldMapKeyInt64 = 2 << 8,
|
|
GPBFieldMapKeyUInt32 = 3 << 8,
|
|
GPBFieldMapKeyUInt64 = 4 << 8,
|
|
GPBFieldMapKeySInt32 = 5 << 8,
|
|
GPBFieldMapKeySInt64 = 6 << 8,
|
|
GPBFieldMapKeyFixed32 = 7 << 8,
|
|
GPBFieldMapKeyFixed64 = 8 << 8,
|
|
GPBFieldMapKeySFixed32 = 9 << 8,
|
|
GPBFieldMapKeySFixed64 = 10 << 8,
|
|
GPBFieldMapKeyBool = 11 << 8,
|
|
GPBFieldMapKeyString = 12 << 8,
|
|
|
|
// If the enum for this field is "closed", meaning that it:
|
|
// - Has a fixed set of named values.
|
|
// - Encountering values not in this set causes them to be treated as unknown
|
|
// fields.
|
|
// - The first value (i.e., the default) may be nonzero.
|
|
// NOTE: This could be tracked just on the GPBEnumDescriptor, but to support
|
|
// previously generated code, there would be not data to get the behavior
|
|
// correct, so instead it is tracked on the field. If old source compatibility
|
|
// is removed, this could be removed and the GPBEnumDescription fetched from
|
|
// the GPBFieldDescriptor instead.
|
|
GPBFieldClosedEnum = 1 << 12,
|
|
};
|
|
|
|
// NOTE: The structures defined here have their members ordered to minimize
|
|
// their size. This directly impacts the size of apps since these exist per
|
|
// field/extension.
|
|
|
|
typedef struct GPBFileDescription {
|
|
// The proto package for the file.
|
|
const char *package;
|
|
// The objc_class_prefix option if present.
|
|
const char *prefix;
|
|
// The file's proto syntax.
|
|
GPBFileSyntax syntax;
|
|
} GPBFileDescription;
|
|
|
|
// Describes a single field in a protobuf as it is represented as an ivar.
|
|
typedef struct GPBMessageFieldDescription {
|
|
// Name of ivar.
|
|
const char *name;
|
|
union {
|
|
// className is deprecated and will be removed in favor of clazz.
|
|
// kept around right now for backwards compatibility.
|
|
// clazz is used iff GPBDescriptorInitializationFlag_UsesClassRefs is set.
|
|
char *className; // Name of the class of the message.
|
|
Class clazz; // Class of the message.
|
|
// For enums only.
|
|
GPBEnumDescriptorFunc enumDescFunc;
|
|
} dataTypeSpecific;
|
|
// The field number for the ivar.
|
|
uint32_t number;
|
|
// The index (in bits) into _has_storage_.
|
|
// >= 0: the bit to use for a value being set.
|
|
// = GPBNoHasBit(INT32_MAX): no storage used.
|
|
// < 0: in a oneOf, use a full int32 to record the field active.
|
|
int32_t hasIndex;
|
|
// Offset of the variable into it's structure struct.
|
|
uint32_t offset;
|
|
// Field flags. Use accessor functions below.
|
|
GPBFieldFlags flags;
|
|
// Data type of the ivar.
|
|
GPBDataType dataType;
|
|
} GPBMessageFieldDescription;
|
|
|
|
// If a message uses fields where they provide default values that are non zero, then this
|
|
// struct is used to provide the values along with the field info.
|
|
typedef struct GPBMessageFieldDescriptionWithDefault {
|
|
// Default value for the ivar.
|
|
GPBGenericValue defaultValue;
|
|
|
|
GPBMessageFieldDescription core;
|
|
} GPBMessageFieldDescriptionWithDefault;
|
|
|
|
// Describes attributes of the extension.
|
|
typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) {
|
|
GPBExtensionNone = 0,
|
|
// These map to standard protobuf concepts.
|
|
GPBExtensionRepeated = 1 << 0,
|
|
GPBExtensionPacked = 1 << 1,
|
|
GPBExtensionSetWireFormat = 1 << 2,
|
|
};
|
|
|
|
// An extension
|
|
typedef struct GPBExtensionDescription {
|
|
GPBGenericValue defaultValue;
|
|
const char *singletonName;
|
|
// Before 3.12, `extendedClass` was just a `const char *`. Thanks to nested
|
|
// initialization
|
|
// (https://en.cppreference.com/w/c/language/struct_initialization#Nested_initialization) old
|
|
// generated code with `.extendedClass = GPBStringifySymbol(Something)` still works; and the
|
|
// current generator can use `extendedClass.clazz`, to pass a Class reference.
|
|
union {
|
|
const char *name;
|
|
Class clazz;
|
|
} extendedClass;
|
|
// Before 3.12, this was `const char *messageOrGroupClassName`. In the
|
|
// initial 3.12 release, we moved the `union messageOrGroupClass`, and failed
|
|
// to realize that would break existing source code for extensions. So to
|
|
// keep existing source code working, we added an unnamed union (C11) to
|
|
// provide both the old field name and the new union. This keeps both older
|
|
// and newer code working.
|
|
// Background: https://github.com/protocolbuffers/protobuf/issues/7555
|
|
union {
|
|
const char *messageOrGroupClassName;
|
|
union {
|
|
const char *name;
|
|
Class clazz;
|
|
} messageOrGroupClass;
|
|
};
|
|
GPBEnumDescriptorFunc enumDescriptorFunc;
|
|
int32_t fieldNumber;
|
|
GPBDataType dataType;
|
|
GPBExtensionOptions options;
|
|
} GPBExtensionDescription;
|
|
|
|
typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
|
|
GPBDescriptorInitializationFlag_None = 0,
|
|
GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0,
|
|
GPBDescriptorInitializationFlag_WireFormat = 1 << 1,
|
|
|
|
// This is used as a stopgap as we move from using class names to class
|
|
// references. The runtime needs to support both until we allow a
|
|
// breaking change in the runtime.
|
|
GPBDescriptorInitializationFlag_UsesClassRefs = 1 << 2,
|
|
|
|
// This flag is used to indicate that the generated sources already contain
|
|
// the `GPBFieldClearHasIvarOnZero` flag and it doesn't have to be computed
|
|
// at startup. This allows older generated code to still work with the
|
|
// current runtime library.
|
|
GPBDescriptorInitializationFlag_Proto3OptionalKnown = 1 << 3,
|
|
|
|
// This flag is used to indicate that the generated sources already contain
|
|
// the `GPBFieldCloseEnum` flag and it doesn't have to be computed at startup.
|
|
// This allows the older generated code to still work with the current runtime
|
|
// library.
|
|
GPBDescriptorInitializationFlag_ClosedEnumSupportKnown = 1 << 4,
|
|
};
|
|
|
|
@interface GPBDescriptor () {
|
|
@package
|
|
NSArray *fields_;
|
|
NSArray *oneofs_;
|
|
uint32_t storageSize_;
|
|
}
|
|
|
|
// fieldDescriptions and fileDescription have to be long lived, they are held as raw pointers.
|
|
+ (instancetype)allocDescriptorForClass:(Class)messageClass
|
|
messageName:(NSString *)messageName
|
|
fileDescription:(GPBFileDescription *)fileDescription
|
|
fields:(void *)fieldDescriptions
|
|
fieldCount:(uint32_t)fieldCount
|
|
storageSize:(uint32_t)storageSize
|
|
flags:(GPBDescriptorInitializationFlags)flags;
|
|
|
|
// Called right after init to provide extra information to avoid init having
|
|
// an explosion of args. These pointers are recorded, so they are expected
|
|
// to live for the lifetime of the app.
|
|
- (void)setupOneofs:(const char **)oneofNames
|
|
count:(uint32_t)count
|
|
firstHasIndex:(int32_t)firstHasIndex;
|
|
- (void)setupExtraTextInfo:(const char *)extraTextFormatInfo;
|
|
- (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count;
|
|
- (void)setupContainingMessageClass:(Class)msgClass;
|
|
|
|
// Deprecated, these remain to support older versions of source generation.
|
|
+ (instancetype)allocDescriptorForClass:(Class)messageClass
|
|
file:(GPBFileDescriptor *)file
|
|
fields:(void *)fieldDescriptions
|
|
fieldCount:(uint32_t)fieldCount
|
|
storageSize:(uint32_t)storageSize
|
|
flags:(GPBDescriptorInitializationFlags)flags;
|
|
+ (instancetype)allocDescriptorForClass:(Class)messageClass
|
|
rootClass:(Class)rootClass
|
|
file:(GPBFileDescriptor *)file
|
|
fields:(void *)fieldDescriptions
|
|
fieldCount:(uint32_t)fieldCount
|
|
storageSize:(uint32_t)storageSize
|
|
flags:(GPBDescriptorInitializationFlags)flags;
|
|
- (void)setupContainingMessageClassName:(const char *)msgClassName;
|
|
- (void)setupMessageClassNameSuffix:(NSString *)suffix;
|
|
|
|
@end
|
|
|
|
@interface GPBFileDescriptor ()
|
|
- (instancetype)initWithPackage:(NSString *)package
|
|
objcPrefix:(NSString *)objcPrefix
|
|
syntax:(GPBFileSyntax)syntax;
|
|
- (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax;
|
|
@end
|
|
|
|
@interface GPBOneofDescriptor () {
|
|
@package
|
|
const char *name_;
|
|
NSArray *fields_;
|
|
SEL caseSel_;
|
|
}
|
|
// name must be long lived.
|
|
- (instancetype)initWithName:(const char *)name fields:(NSArray *)fields;
|
|
@end
|
|
|
|
@interface GPBFieldDescriptor () {
|
|
@package
|
|
GPBMessageFieldDescription *description_;
|
|
GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_;
|
|
|
|
SEL getSel_;
|
|
SEL setSel_;
|
|
SEL hasOrCountSel_; // *Count for map<>/repeated fields, has* otherwise.
|
|
SEL setHasSel_;
|
|
}
|
|
@end
|
|
|
|
typedef NS_OPTIONS(uint32_t, GPBEnumDescriptorInitializationFlags) {
|
|
GPBEnumDescriptorInitializationFlag_None = 0,
|
|
|
|
// Available: 1 << 0
|
|
|
|
// Marks this enum as a closed enum.
|
|
GPBEnumDescriptorInitializationFlag_IsClosed = 1 << 1,
|
|
};
|
|
|
|
@interface GPBEnumDescriptor ()
|
|
// valueNames, values and extraTextFormatInfo have to be long lived, they are
|
|
// held as raw pointers.
|
|
+ (instancetype)allocDescriptorForName:(NSString *)name
|
|
valueNames:(const char *)valueNames
|
|
values:(const int32_t *)values
|
|
count:(uint32_t)valueCount
|
|
enumVerifier:(GPBEnumValidationFunc)enumVerifier
|
|
flags:(GPBEnumDescriptorInitializationFlags)flags;
|
|
+ (instancetype)allocDescriptorForName:(NSString *)name
|
|
valueNames:(const char *)valueNames
|
|
values:(const int32_t *)values
|
|
count:(uint32_t)valueCount
|
|
enumVerifier:(GPBEnumValidationFunc)enumVerifier
|
|
flags:(GPBEnumDescriptorInitializationFlags)flags
|
|
extraTextFormatInfo:(const char *)extraTextFormatInfo;
|
|
|
|
// Deprecated, these remain to support older versions of source generation.
|
|
+ (instancetype)allocDescriptorForName:(NSString *)name
|
|
valueNames:(const char *)valueNames
|
|
values:(const int32_t *)values
|
|
count:(uint32_t)valueCount
|
|
enumVerifier:(GPBEnumValidationFunc)enumVerifier;
|
|
+ (instancetype)allocDescriptorForName:(NSString *)name
|
|
valueNames:(const char *)valueNames
|
|
values:(const int32_t *)values
|
|
count:(uint32_t)valueCount
|
|
enumVerifier:(GPBEnumValidationFunc)enumVerifier
|
|
extraTextFormatInfo:(const char *)extraTextFormatInfo;
|
|
@end
|
|
|
|
@interface GPBExtensionDescriptor () {
|
|
@package
|
|
GPBExtensionDescription *description_;
|
|
}
|
|
@property(nonatomic, readonly) GPBWireFormat wireType;
|
|
|
|
// For repeated extensions, alternateWireType is the wireType with the opposite
|
|
// value for the packable property. i.e. - if the extension was marked packed
|
|
// it would be the wire type for unpacked; if the extension was marked unpacked,
|
|
// it would be the wire type for packed.
|
|
@property(nonatomic, readonly) GPBWireFormat alternateWireType;
|
|
|
|
// description has to be long lived, it is held as a raw pointer.
|
|
- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc
|
|
usesClassRefs:(BOOL)usesClassRefs;
|
|
// Deprecated. Calls above with `usesClassRefs = NO`
|
|
- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc;
|
|
|
|
- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other;
|
|
@end
|
|
|
|
CF_EXTERN_C_BEGIN
|
|
|
|
// Direct access is use for speed, to avoid even internally declaring things
|
|
// read/write, etc. The warning is enabled in the project to ensure code calling
|
|
// protos can turn on -Wdirect-ivar-access without issues.
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
|
|
|
|
GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) {
|
|
return (field->description_->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
|
|
}
|
|
|
|
GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) {
|
|
return field->description_->dataType;
|
|
}
|
|
|
|
GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) {
|
|
return field->description_->hasIndex;
|
|
}
|
|
|
|
GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) {
|
|
return field->description_->number;
|
|
}
|
|
|
|
GPB_INLINE BOOL GPBFieldIsClosedEnum(GPBFieldDescriptor *field) {
|
|
return (field->description_->flags & GPBFieldClosedEnum) != 0;
|
|
}
|
|
|
|
#pragma clang diagnostic pop
|
|
|
|
uint32_t GPBFieldTag(GPBFieldDescriptor *self);
|
|
|
|
// For repeated fields, alternateWireType is the wireType with the opposite
|
|
// value for the packable property. i.e. - if the field was marked packed it
|
|
// would be the wire type for unpacked; if the field was marked unpacked, it
|
|
// would be the wire type for packed.
|
|
uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self);
|
|
|
|
GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) {
|
|
return (description->options & GPBExtensionRepeated) != 0;
|
|
}
|
|
|
|
GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) {
|
|
return (description->options & GPBExtensionPacked) != 0;
|
|
}
|
|
|
|
GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) {
|
|
return (description->options & GPBExtensionSetWireFormat) != 0;
|
|
}
|
|
|
|
// Helper for compile time assets.
|
|
#ifndef GPBInternalCompileAssert
|
|
#define GPBInternalCompileAssert(test, msg) _Static_assert((test), #msg)
|
|
#endif // GPBInternalCompileAssert
|
|
|
|
// Sanity check that there isn't padding between the field description
|
|
// structures with and without a default.
|
|
GPBInternalCompileAssert(sizeof(GPBMessageFieldDescriptionWithDefault) ==
|
|
(sizeof(GPBGenericValue) + sizeof(GPBMessageFieldDescription)),
|
|
DescriptionsWithDefault_different_size_than_expected);
|
|
|
|
CF_EXTERN_C_END
|