Merge pull request #4282 from jcanizales/custom-mutable-dict

Use a custom NSMutableDictionary subclass for request headers
pull/4290/head
Michael Lumish 9 years ago
commit 98ee61f68c
  1. 43
      src/objective-c/GRPCClient/GRPCCall.h
  2. 2
      src/objective-c/GRPCClient/GRPCCall.m
  3. 13
      src/objective-c/GRPCClient/private/GRPCRequestHeaders.h
  4. 43
      src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
  5. 2
      src/objective-c/GRPCClient/private/GRPCWrappedCall.h
  6. 2
      src/objective-c/GRPCClient/private/GRPCWrappedCall.m

@ -50,6 +50,8 @@
#import <Foundation/Foundation.h>
#import <RxLibrary/GRXWriter.h>
#include <AvailabilityMacros.h>
#pragma mark gRPC errors
/** Domain of NSError objects produced by gRPC. */
@ -161,6 +163,9 @@ extern id const kGRPCTrailersKey;
#pragma mark GRPCCall
/** Represents a single gRPC remote call. */
@interface GRPCCall : GRXWriter
/**
* The container of the request headers of an RPC conforms to this protocol, which is a subset of
* NSMutableDictionary's interface. It will become a NSMutableDictionary later on.
@ -170,21 +175,6 @@ extern id const kGRPCTrailersKey;
* A header value is a NSString object (with only ASCII characters), unless the header name has the
* suffix "-bin", in which case the value has to be a NSData object.
*/
@protocol GRPCRequestHeaders <NSObject>
@property(nonatomic, readonly) NSUInteger count;
- (id)objectForKeyedSubscript:(NSString *)key;
- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key;
- (void)removeAllObjects;
- (void)removeObjectForKey:(NSString *)key;
@end
/** Represents a single gRPC remote call. */
@interface GRPCCall : GRXWriter
/**
* These HTTP headers will be passed to the server as part of this call. Each HTTP header is a
* name-value pair with string names and either string or binary values.
@ -200,7 +190,7 @@ extern id const kGRPCTrailersKey;
*
* The property is initialized to an empty NSMutableDictionary.
*/
@property(atomic, readonly) id<GRPCRequestHeaders> requestHeaders;
@property(atomic, readonly) NSMutableDictionary *requestHeaders;
/**
* This dictionary is populated with the HTTP headers received from the server. This happens before
@ -243,3 +233,24 @@ extern id const kGRPCTrailersKey;
// TODO(jcanizales): Let specify a deadline. As a category of GRXWriter?
@end
#pragma mark Backwards compatibiity
/** This protocol is kept for backwards compatibility with existing code. */
DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.")
@protocol GRPCRequestHeaders <NSObject>
@property(nonatomic, readonly) NSUInteger count;
- (id)objectForKeyedSubscript:(NSString *)key;
- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key;
- (void)removeAllObjects;
- (void)removeObjectForKey:(NSString *)key;
@end
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
/** This is only needed for backwards-compatibility. */
@interface NSMutableDictionary (GRPCRequestHeaders) <GRPCRequestHeaders>
@end
#pragma clang diagnostic pop

@ -221,7 +221,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
#pragma mark Send headers
- (void)sendHeaders:(id<GRPCRequestHeaders>)headers {
- (void)sendHeaders:(NSDictionary *)headers {
// TODO(jcanizales): Add error handlers for async failures
[_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers
handler:nil]]];

@ -32,21 +32,14 @@
*/
#import <Foundation/Foundation.h>
#include <grpc/grpc.h>
#import "../GRPCCall.h"
@interface GRPCRequestHeaders : NSObject<GRPCRequestHeaders>
@property(nonatomic, readonly) NSUInteger count;
@property(nonatomic, readonly) grpc_metadata *grpc_metadataArray;
@interface GRPCRequestHeaders : NSMutableDictionary
- (instancetype)initWithCall:(GRPCCall *)call;
- (id)objectForKeyedSubscript:(NSString *)key;
- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key;
- (void)removeAllObjects;
- (void)removeObjectForKey:(NSString *)key;
- (instancetype)initWithCall:(GRPCCall *)call
storage:(NSMutableDictionary *)storage NS_DESIGNATED_INITIALIZER;
@end

@ -68,17 +68,44 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
@implementation GRPCRequestHeaders {
__weak GRPCCall *_call;
// The NSMutableDictionary superclass doesn't hold any storage (so that people can implement their
// own in subclasses). As that's not the reason we're subclassing, we just delegate storage to the
// default NSMutableDictionary subclass returned by the cluster (e.g. __NSDictionaryM on iOS 9).
NSMutableDictionary *_delegate;
}
- (instancetype)init {
return [self initWithCall:nil];
}
- (instancetype)initWithCapacity:(NSUInteger)numItems {
return [self init];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
return [self init];
}
- (instancetype)initWithCall:(GRPCCall *)call {
return [self initWithCall:call storage:[NSMutableDictionary dictionary]];
}
// Designated initializer
- (instancetype)initWithCall:(GRPCCall *)call storage:(NSMutableDictionary *)storage {
// TODO(jcanizales): Throw if call or storage are nil.
if ((self = [super init])) {
_call = call;
_delegate = [NSMutableDictionary dictionary];
_delegate = storage;
}
return self;
}
- (instancetype)initWithObjects:(const id _Nonnull __unsafe_unretained *)objects
forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys
count:(NSUInteger)cnt {
return [self init];
}
- (void)checkCallIsNotStarted {
if (_call.state != GRXWriterStateNotStarted) {
[NSException raise:@"Invalid modification"
@ -86,11 +113,11 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
}
}
- (id)objectForKeyedSubscript:(NSString *)key {
- (id)objectForKey:(NSString *)key {
return _delegate[key.lowercaseString];
}
- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key {
- (void)setObject:(id)obj forKey:(NSString *)key {
[self checkCallIsNotStarted];
CheckIsNonNilASCII(@"Header name", key);
key = key.lowercaseString;
@ -103,16 +130,12 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) {
[_delegate removeObjectForKey:key.lowercaseString];
}
- (void)removeAllObjects {
[self checkCallIsNotStarted];
[_delegate removeAllObjects];
}
- (NSUInteger)count {
return _delegate.count;
}
- (grpc_metadata *)grpc_metadataArray {
return _delegate.grpc_metadataArray;
- (NSEnumerator * _Nonnull)keyEnumerator {
return [_delegate keyEnumerator];
}
@end

@ -45,7 +45,7 @@
@interface GRPCOpSendMetadata : GRPCOperation
- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata
- (instancetype)initWithMetadata:(NSDictionary *)metadata
handler:(void(^)())handler NS_DESIGNATED_INITIALIZER;
@end

@ -65,7 +65,7 @@
return [self initWithMetadata:nil handler:nil];
}
- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata handler:(void (^)())handler {
- (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)())handler {
if (self = [super init]) {
_op.op = GRPC_OP_SEND_INITIAL_METADATA;
_op.data.send_initial_metadata.count = metadata.count;

Loading…
Cancel
Save