diff options
author | Jorge Canizales <jcanizales@google.com> | 2015-06-02 12:01:16 -0700 |
---|---|---|
committer | Jorge Canizales <jcanizales@google.com> | 2015-06-02 13:10:20 -0700 |
commit | b9692ca809e4318ae87995cae771e40c04f7c27f (patch) | |
tree | 925b2c9ff6a728e59daa41e86ea100c657fb0388 /src/objective-c | |
parent | 86686746f6b3fc095cdf94868b4d9d82a86275c8 (diff) |
Fix NSDictionary <-> metadata codec
Diffstat (limited to 'src/objective-c')
-rw-r--r-- | src/objective-c/GRPCClient/private/NSDictionary+GRPC.m | 73 |
1 files changed, 63 insertions, 10 deletions
diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m index c350f32f2a..7705aa46a1 100644 --- a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m @@ -35,21 +35,77 @@ #include <grpc/support/alloc.h> +#pragma mark Category for binary metadata elements + +@interface NSData (GRPCMetadata) ++ (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata; + +// Fill a metadata object with the binary value in this NSData and the given key. +- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key; +@end + +@implementation NSData (GRPCMetadata) ++ (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata { + // TODO(jcanizales): Should we use a non-copy constructor? + return [self dataWithBytes:metadata->value length:metadata->value_length]; +} + +- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key { + // TODO(jcanizales): Encode Unicode chars as ASCII. + metadata->key = [key stringByAppendingString:@"-bin"].UTF8String; + metadata->value = self.bytes; + metadata->value_length = self.length; +} +@end + +#pragma mark Category for textual metadata elements + +@interface NSString (GRPCMetadata) ++ (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata; + +// Fill a metadata object with the textual value in this NSString and the given key. +- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key; +@end + +@implementation NSString (GRPCMetadata) ++ (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata { + return [[self alloc] initWithBytes:metadata->value + length:metadata->value_length + encoding:NSASCIIStringEncoding]; +} + +- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key { + // TODO(jcanizales): Encode Unicode chars as ASCII. + metadata->key = key.UTF8String; + metadata->value = self.UTF8String; + metadata->value_length = self.length; +} +@end + +#pragma mark Category for metadata arrays + @implementation NSDictionary (GRPC) + (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count { NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count]; for (grpc_metadata *entry = entries; entry < entries + count; entry++) { - // TODO(jcanizales): Verify in a C library test that it's converting header names to lower case automatically. - NSString *name = [NSString stringWithUTF8String:entry->key]; + // TODO(jcanizales): Verify in a C library test that it's converting header names to lower case + // automatically. + NSString *name = [NSString stringWithCString:entry->key encoding:NSASCIIStringEncoding]; if (!name) { + // log? continue; } + id value; + if ([name hasSuffix:@"-bin"]) { + name = [name substringToIndex:name.length - 4]; + value = [NSData grpc_dataFromMetadataValue:entry]; + } else { + value = [NSString grpc_stringFromMetadataValue:entry]; + } if (!metadata[name]) { metadata[name] = [NSMutableArray array]; } - // TODO(jcanizales): Should we use a non-copy constructor? - [metadata[name] addObject:[NSData dataWithBytes:entry->value - length:entry->value_length]]; + [metadata[name] addObject:value]; } return metadata; } @@ -60,11 +116,8 @@ for (id key in self) { id value = self[key]; grpc_metadata *current = &metadata[i]; - current->key = [key UTF8String]; - if ([value isKindOfClass:[NSData class]]) { - current->value = [value bytes]; - } else if ([value isKindOfClass:[NSString class]]) { - current->value = [value UTF8String]; + if ([value respondsToSelector:@selector(grpc_initMetadata:withKey:)]) { + [value grpc_initMetadata:current withKey:key]; } else { [NSException raise:NSInvalidArgumentException format:@"Metadata values must be NSString or NSData."]; |