aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jorge Canizales <jcanizales@google.com>2015-06-02 12:01:16 -0700
committerGravatar Jorge Canizales <jcanizales@google.com>2015-06-02 13:10:20 -0700
commitb9692ca809e4318ae87995cae771e40c04f7c27f (patch)
tree925b2c9ff6a728e59daa41e86ea100c657fb0388
parent86686746f6b3fc095cdf94868b4d9d82a86275c8 (diff)
Fix NSDictionary <-> metadata codec
-rw-r--r--src/objective-c/GRPCClient/private/NSDictionary+GRPC.m73
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."];