Skip to content

Commit

Permalink
[ObjC] Add ability to introspect list of enum values (#4678)
Browse files Browse the repository at this point in the history
Added new API to GPBEnumDescriptor to enable introspection of enum values.

Refactored implementation so that this contains a minimum of added code.

Clarified comments regarding behavior in the presence of the alias_allowed option.

Added unit tests for new functionality and for the alias case.
  • Loading branch information
leovitch authored and thomasvl committed May 29, 2018
1 parent 264e615 commit 2804902
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 14 deletions.
34 changes: 32 additions & 2 deletions objectivec/GPBDescriptor.h
Expand Up @@ -223,9 +223,12 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
/**
* Returns the enum value name for the given raw enum.
*
* Note that there can be more than one name corresponding to a given value
* if the allow_alias option is used.
*
* @param number The raw enum value.
*
* @return The name of the enum value passed, or nil if not valid.
* @return The first name that matches the enum value passed, or nil if not valid.
**/
- (nullable NSString *)enumNameForValue:(int32_t)number;

Expand All @@ -244,7 +247,7 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
*
* @param number The raw enum value.
*
* @return The text format name for the raw enum value, or nil if not valid.
* @return The first text format name which matches the enum value, or nil if not valid.
**/
- (nullable NSString *)textFormatNameForValue:(int32_t)number;

Expand All @@ -258,6 +261,33 @@ typedef NS_ENUM(uint8_t, GPBFieldType) {
**/
- (BOOL)getValue:(nullable int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName;

/**
* Gets the number of defined enum names.
*
* @return Count of the number of enum names, including any aliases.
*/
@property(nonatomic, readonly) uint32_t enumNameCount;

/**
* Gets the enum name corresponding to the given index.
*
* @param index Index into the available names. The defined range is from 0
* to self.enumNameCount - 1.
*
* @returns The enum name at the given index, or nil if the index is out of range.
*/
- (nullable NSString *)getEnumNameForIndex:(uint32_t)index;

/**
* Gets the enum text format name corresponding to the given index.
*
* @param index Index into the available names. The defined range is from 0
* to self.enumNameCount - 1.
*
* @returns The text format name at the given index, or nil if the index is out of range.
*/
- (nullable NSString *)getEnumTextFormatNameForIndex:(uint32_t)index;

@end

/**
Expand Down
35 changes: 26 additions & 9 deletions objectivec/GPBDescriptor.m
Expand Up @@ -830,13 +830,9 @@ - (void)calcValueNameOffsets {
}

- (NSString *)enumNameForValue:(int32_t)number {
if (nameOffsets_ == NULL) [self calcValueNameOffsets];

for (uint32_t i = 0; i < valueCount_; ++i) {
if (values_[i] == number) {
const char *valueName = valueNames_ + nameOffsets_[i];
NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName];
return fullName;
return [self getEnumNameForIndex:i];
}
}
return nil;
Expand Down Expand Up @@ -886,8 +882,6 @@ - (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textForma
}

- (NSString *)textFormatNameForValue:(int32_t)number {
if (nameOffsets_ == NULL) [self calcValueNameOffsets];

// Find the EnumValue descriptor and its index.
BOOL foundIt = NO;
uint32_t valueDescriptorIndex;
Expand All @@ -902,16 +896,39 @@ - (NSString *)textFormatNameForValue:(int32_t)number {
if (!foundIt) {
return nil;
}
return [self getEnumTextFormatNameForIndex:valueDescriptorIndex];
}

- (uint32_t)enumNameCount {
return valueCount_;
}

- (NSString *)getEnumNameForIndex:(uint32_t)index {
if (nameOffsets_ == NULL) [self calcValueNameOffsets];

if (index >= valueCount_) {
return nil;
}
const char *valueName = valueNames_ + nameOffsets_[index];
NSString *fullName = [NSString stringWithFormat:@"%@_%s", name_, valueName];
return fullName;
}

- (NSString *)getEnumTextFormatNameForIndex:(uint32_t)index {
if (nameOffsets_ == NULL) [self calcValueNameOffsets];

if (index >= valueCount_) {
return nil;
}
NSString *result = nil;
// Naming adds an underscore between enum name and value name, skip that also.
const char *valueName = valueNames_ + nameOffsets_[valueDescriptorIndex];
const char *valueName = valueNames_ + nameOffsets_[index];
NSString *shortName = @(valueName);

// See if it is in the map of special format handling.
if (extraTextFormatInfo_) {
result = GPBDecodeTextFormatName(extraTextFormatInfo_,
(int32_t)valueDescriptorIndex, shortName);
(int32_t)index, shortName);
}
// Logic here needs to match what objectivec_enum.cc does in the proto
// compiler.
Expand Down
7 changes: 4 additions & 3 deletions objectivec/README.md
Expand Up @@ -20,9 +20,10 @@ The Objective C implementation requires:
Installation
------------

The full distribution pulled from github includes the sources for both the
compiler (protoc) and the runtime (this directory). To build the compiler
and run the runtime tests, you can use:
The distribution pulled from github includes the sources for both the
compiler (protoc) and the runtime (this directory). After cloning the distribution
and needed submodules ([see the src directory's README](../src/README.md)),
to build the compiler and run the runtime tests, you can use:

$ objectivec/DevTools/full_mac_build.sh

Expand Down
57 changes: 57 additions & 0 deletions objectivec/Tests/GPBDescriptorTests.m
Expand Up @@ -190,6 +190,63 @@ - (void)testEnumDescriptor {
XCTAssertFalse([descriptor getValue:&value forEnumTextFormatName:@"Unknown"]);
}

- (void)testEnumDescriptorIntrospection {
GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();

XCTAssertEqual(descriptor.enumNameCount, 4U);
XCTAssertEqualObjects([descriptor getEnumNameForIndex:0],
@"TestAllTypes_NestedEnum_Foo");
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO");
XCTAssertEqualObjects([descriptor getEnumNameForIndex:1],
@"TestAllTypes_NestedEnum_Bar");
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR");
XCTAssertEqualObjects([descriptor getEnumNameForIndex:2],
@"TestAllTypes_NestedEnum_Baz");
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ");
XCTAssertEqualObjects([descriptor getEnumNameForIndex:3],
@"TestAllTypes_NestedEnum_Neg");
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"NEG");
}

- (void)testEnumDescriptorIntrospectionWithAlias {
GPBEnumDescriptor *descriptor = TestEnumWithDupValue_EnumDescriptor();
NSString *enumName;
int32_t value;

XCTAssertEqual(descriptor.enumNameCount, 5U);

enumName = [descriptor getEnumNameForIndex:0];
XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Foo1");
XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
XCTAssertEqual(value, 1);
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO1");

enumName = [descriptor getEnumNameForIndex:1];
XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Bar1");
XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
XCTAssertEqual(value, 2);
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR1");

enumName = [descriptor getEnumNameForIndex:2];
XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Baz");
XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
XCTAssertEqual(value, 3);
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ");

enumName = [descriptor getEnumNameForIndex:3];
XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Foo2");
XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
XCTAssertEqual(value, 1);
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"FOO2");

enumName = [descriptor getEnumNameForIndex:4];
XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Bar2");
XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
XCTAssertEqual(value, 2);
XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:4], @"BAR2");

}

- (void)testEnumValueValidator {
GPBDescriptor *descriptor = [TestAllTypes descriptor];
GPBFieldDescriptor *fieldDescriptor =
Expand Down

0 comments on commit 2804902

Please sign in to comment.