Merge pull request #2488 from jcanizales/subclass-grxwriter

Subclass GRXWriter instead of conforming to its protocol
pull/2470/head^2
Michael Lumish 9 years ago
commit 048fc2f04f
  1. 2
      src/compiler/objective_c_generator.cc
  2. 4
      src/objective-c/GRPCClient/GRPCCall.h
  3. 4
      src/objective-c/GRPCClient/GRPCCall.m
  4. 5
      src/objective-c/GRPCClient/private/GRPCDelegateWrapper.h
  5. 4
      src/objective-c/GRPCClient/private/GRPCDelegateWrapper.m
  6. 2
      src/objective-c/ProtoRPC/ProtoRPC.h
  7. 16
      src/objective-c/ProtoRPC/ProtoRPC.m
  8. 4
      src/objective-c/ProtoRPC/ProtoService.h
  9. 2
      src/objective-c/ProtoRPC/ProtoService.m
  10. 2
      src/objective-c/RxLibrary/GRXBufferedPipe.h
  11. 43
      src/objective-c/RxLibrary/GRXForwardingWriter.h
  12. 112
      src/objective-c/RxLibrary/GRXForwardingWriter.m
  13. 14
      src/objective-c/RxLibrary/GRXImmediateWriter.h
  14. 12
      src/objective-c/RxLibrary/GRXImmediateWriter.m
  15. 12
      src/objective-c/RxLibrary/GRXWriter+Immediate.m
  16. 11
      src/objective-c/RxLibrary/GRXWriter.h
  17. 76
      src/objective-c/RxLibrary/GRXWriter.m
  18. 6
      src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
  19. 6
      src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
  20. 4
      src/objective-c/tests/GRPCClientTests.m
  21. 2
      src/objective-c/tests/InteropTests.m
  22. 6
      src/objective-c/tests/LocalClearTextTests.m

@ -67,7 +67,7 @@ void PrintMethodSignature(Printer *printer, const MethodDescriptor *method,
printer->Print(vars, "- ($return_type$)$method_name$With"); printer->Print(vars, "- ($return_type$)$method_name$With");
if (method->client_streaming()) { if (method->client_streaming()) {
printer->Print("RequestsWriter:(id<GRXWriter>)requestWriter"); printer->Print("RequestsWriter:(GRXWriter *)requestWriter");
} else { } else {
printer->Print(vars, "Request:($request_class$ *)request"); printer->Print(vars, "Request:($request_class$ *)request");
} }

@ -52,7 +52,7 @@
extern id const kGRPCStatusMetadataKey; extern id const kGRPCStatusMetadataKey;
// Represents a single gRPC remote call. // Represents a single gRPC remote call.
@interface GRPCCall : NSObject<GRXWriter> @interface GRPCCall : GRXWriter
// These HTTP headers will be passed to the server as part of this call. Each HTTP header is a // 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. // name-value pair with string names and either string or binary values.
@ -89,7 +89,7 @@ extern id const kGRPCStatusMetadataKey;
// To finish a call right away, invoke cancel. // To finish a call right away, invoke cancel.
- (instancetype)initWithHost:(NSString *)host - (instancetype)initWithHost:(NSString *)host
path:(NSString *)path path:(NSString *)path
requestsWriter:(id<GRXWriter>)requestsWriter NS_DESIGNATED_INITIALIZER; requestsWriter:(GRXWriter *)requestsWriter NS_DESIGNATED_INITIALIZER;
// Finishes the request side of this call, notifies the server that the RPC // Finishes the request side of this call, notifies the server that the RPC
// should be cancelled, and finishes the response side of the call with an error // should be cancelled, and finishes the response side of the call with an error

@ -79,7 +79,7 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
// all. This wrapper over our actual writeable ensures thread-safety and // all. This wrapper over our actual writeable ensures thread-safety and
// correct ordering. // correct ordering.
GRPCDelegateWrapper *_responseWriteable; GRPCDelegateWrapper *_responseWriteable;
id<GRXWriter> _requestWriter; GRXWriter *_requestWriter;
NSMutableDictionary *_requestMetadata; NSMutableDictionary *_requestMetadata;
NSMutableDictionary *_responseMetadata; NSMutableDictionary *_responseMetadata;
@ -94,7 +94,7 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey";
// Designated initializer // Designated initializer
- (instancetype)initWithHost:(NSString *)host - (instancetype)initWithHost:(NSString *)host
path:(NSString *)path path:(NSString *)path
requestsWriter:(id<GRXWriter>)requestWriter { requestsWriter:(GRXWriter *)requestWriter {
if (!host || !path) { if (!host || !path) {
[NSException raise:NSInvalidArgumentException format:@"Neither host nor method can be nil."]; [NSException raise:NSInvalidArgumentException format:@"Neither host nor method can be nil."];
} }

@ -33,8 +33,9 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <RxLibrary/GRXWriter.h>
@protocol GRXWriteable; @protocol GRXWriteable;
@protocol GRXWriter;
// This is a thread-safe wrapper over a GRXWriteable instance. It lets one // This is a thread-safe wrapper over a GRXWriteable instance. It lets one
// enqueue calls to a GRXWriteable instance for the main thread, guaranteeing // enqueue calls to a GRXWriteable instance for the main thread, guaranteeing
@ -54,7 +55,7 @@
// writesFinishedWithError: is sent to the writeable, and released after that. // writesFinishedWithError: is sent to the writeable, and released after that.
// This is used to create a retain cycle that keeps both objects alive until the // This is used to create a retain cycle that keeps both objects alive until the
// writing is explicitly finished. // writing is explicitly finished.
- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(id<GRXWriter>)writer - (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(GRXWriter *)writer
NS_DESIGNATED_INITIALIZER; NS_DESIGNATED_INITIALIZER;
// Enqueues writeValue: to be sent to the writeable in the main thread. // Enqueues writeValue: to be sent to the writeable in the main thread.

@ -38,7 +38,7 @@
@interface GRPCDelegateWrapper () @interface GRPCDelegateWrapper ()
// These are atomic so that cancellation can nillify them from any thread. // These are atomic so that cancellation can nillify them from any thread.
@property(atomic, strong) id<GRXWriteable> writeable; @property(atomic, strong) id<GRXWriteable> writeable;
@property(atomic, strong) id<GRXWriter> writer; @property(atomic, strong) GRXWriter *writer;
@end @end
@implementation GRPCDelegateWrapper { @implementation GRPCDelegateWrapper {
@ -52,7 +52,7 @@
} }
// Designated initializer // Designated initializer
- (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(id<GRXWriter>)writer { - (instancetype)initWithWriteable:(id<GRXWriteable>)writeable writer:(GRXWriter *)writer {
if (self = [super init]) { if (self = [super init]) {
_writeableQueue = dispatch_get_main_queue(); _writeableQueue = dispatch_get_main_queue();
_writeable = writeable; _writeable = writeable;

@ -40,7 +40,7 @@
- (instancetype)initWithHost:(NSString *)host - (instancetype)initWithHost:(NSString *)host
method:(ProtoMethod *)method method:(ProtoMethod *)method
requestsWriter:(id<GRXWriter>)requestsWriter requestsWriter:(GRXWriter *)requestsWriter
responseClass:(Class)responseClass responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable NS_DESIGNATED_INITIALIZER; responsesWriteable:(id<GRXWriteable>)responsesWriteable NS_DESIGNATED_INITIALIZER;

@ -35,7 +35,6 @@
#import <GPBProtocolBuffers.h> #import <GPBProtocolBuffers.h>
#import <RxLibrary/GRXWriteable.h> #import <RxLibrary/GRXWriteable.h>
#import <RxLibrary/GRXWriter.h>
#import <RxLibrary/GRXWriter+Transformations.h> #import <RxLibrary/GRXWriter+Transformations.h>
@implementation ProtoRPC { @implementation ProtoRPC {
@ -46,7 +45,7 @@
#pragma clang diagnostic ignored "-Wobjc-designated-initializers" #pragma clang diagnostic ignored "-Wobjc-designated-initializers"
- (instancetype)initWithHost:(NSString *)host - (instancetype)initWithHost:(NSString *)host
path:(NSString *)path path:(NSString *)path
requestsWriter:(id<GRXWriter>)requestsWriter { requestsWriter:(GRXWriter *)requestsWriter {
[NSException raise:NSInvalidArgumentException [NSException raise:NSInvalidArgumentException
format:@"Please use ProtoRPC's designated initializer instead."]; format:@"Please use ProtoRPC's designated initializer instead."];
return nil; return nil;
@ -56,7 +55,7 @@
// Designated initializer // Designated initializer
- (instancetype)initWithHost:(NSString *)host - (instancetype)initWithHost:(NSString *)host
method:(ProtoMethod *)method method:(ProtoMethod *)method
requestsWriter:(id<GRXWriter>)requestsWriter requestsWriter:(GRXWriter *)requestsWriter
responseClass:(Class)responseClass responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable { responsesWriteable:(id<GRXWriteable>)responsesWriteable {
// Because we can't tell the type system to constrain the class, we need to check at runtime: // Because we can't tell the type system to constrain the class, we need to check at runtime:
@ -65,12 +64,11 @@
format:@"A protobuf class to parse the responses must be provided."]; format:@"A protobuf class to parse the responses must be provided."];
} }
// A writer that serializes the proto messages to send. // A writer that serializes the proto messages to send.
id<GRXWriter> bytesWriter = GRXWriter *bytesWriter = [requestsWriter map:^id(GPBMessage *proto) {
[[[GRXWriter alloc] initWithWriter:requestsWriter] map:^id(GPBMessage *proto) { // TODO(jcanizales): Fail with an understandable error message if the requestsWriter isn't
// TODO(jcanizales): Fail with an understandable error message if the requestsWriter isn't // sending GPBMessages.
// sending GPBMessages. return [proto data];
return [proto data]; }];
}];
if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) { if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) {
// A writeable that parses the proto messages received. // A writeable that parses the proto messages received.
_responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { _responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {

@ -35,7 +35,7 @@
@class ProtoRPC; @class ProtoRPC;
@protocol GRXWriteable; @protocol GRXWriteable;
@protocol GRXWriter; @class GRXWriter;
@interface ProtoService : NSObject @interface ProtoService : NSObject
- (instancetype)initWithHost:(NSString *)host - (instancetype)initWithHost:(NSString *)host
@ -43,7 +43,7 @@
serviceName:(NSString *)serviceName NS_DESIGNATED_INITIALIZER; serviceName:(NSString *)serviceName NS_DESIGNATED_INITIALIZER;
- (ProtoRPC *)RPCToMethod:(NSString *)method - (ProtoRPC *)RPCToMethod:(NSString *)method
requestsWriter:(id<GRXWriter>)requestsWriter requestsWriter:(GRXWriter *)requestsWriter
responseClass:(Class)responseClass responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable; responsesWriteable:(id<GRXWriteable>)responsesWriteable;
@end @end

@ -66,7 +66,7 @@
} }
- (ProtoRPC *)RPCToMethod:(NSString *)method - (ProtoRPC *)RPCToMethod:(NSString *)method
requestsWriter:(id<GRXWriter>)requestsWriter requestsWriter:(GRXWriter *)requestsWriter
responseClass:(Class)responseClass responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable { responsesWriteable:(id<GRXWriteable>)responsesWriteable {
ProtoMethod *methodName = [[ProtoMethod alloc] initWithPackage:_packageName ProtoMethod *methodName = [[ProtoMethod alloc] initWithPackage:_packageName

@ -51,7 +51,7 @@
// pipe will keep buffering all data written to it, your application could run out of memory and // pipe will keep buffering all data written to it, your application could run out of memory and
// crash. If you want to react to flow control signals to prevent that, instead of using this class // crash. If you want to react to flow control signals to prevent that, instead of using this class
// you can implement an object that conforms to GRXWriter. // you can implement an object that conforms to GRXWriter.
@interface GRXBufferedPipe : NSObject<GRXWriteable, GRXWriter> @interface GRXBufferedPipe : GRXWriter<GRXWriteable>
// Convenience constructor. // Convenience constructor.
+ (instancetype)pipe; + (instancetype)pipe;

@ -0,0 +1,43 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* 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.
*
*/
#import "GRXWriter.h"
// A "proxy" class that simply forwards values, completion, and errors from its
// input writer to its writeable.
// It is useful as a superclass for pipes that act as a transformation of their
// input writer, and for classes that represent objects with input and
// output sequences of values, like an RPC.
@interface GRXForwardingWriter : GRXWriter
- (instancetype)initWithWriter:(GRXWriter *)writer NS_DESIGNATED_INITIALIZER;
@end

@ -0,0 +1,112 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* 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.
*
*/
#import "GRXForwardingWriter.h"
@interface GRXForwardingWriter () <GRXWriteable>
@end
@implementation GRXForwardingWriter {
GRXWriter *_writer;
id<GRXWriteable> _writeable;
}
- (instancetype)init {
return [self initWithWriter:nil];
}
// Designated initializer
- (instancetype)initWithWriter:(GRXWriter *)writer {
if (!writer) {
[NSException raise:NSInvalidArgumentException format:@"writer can't be nil."];
}
if ((self = [super init])) {
_writer = writer;
}
return self;
}
// This is used to send a completion or an error to the writeable. It nillifies
// our reference to it in order to guarantee no more messages are sent to it,
// and to release it.
- (void)finishOutputWithError:(NSError *)errorOrNil {
id<GRXWriteable> writeable = _writeable;
_writeable = nil;
[writeable writesFinishedWithError:errorOrNil];
}
// This is used to stop the input writer. It nillifies our reference to it
// to release it.
- (void)finishInput {
GRXWriter *writer = _writer;
_writer = nil;
writer.state = GRXWriterStateFinished;
}
#pragma mark GRXWriteable implementation
- (void)writeValue:(id)value {
[_writeable writeValue:value];
}
- (void)writesFinishedWithError:(NSError *)errorOrNil {
_writer = nil;
[self finishOutputWithError:errorOrNil];
}
#pragma mark GRXWriter implementation
- (GRXWriterState)state {
return _writer ? _writer.state : GRXWriterStateFinished;
}
- (void)setState:(GRXWriterState)state {
if (state == GRXWriterStateFinished) {
_writeable = nil;
[self finishInput];
} else {
_writer.state = state;
}
}
- (void)startWithWriteable:(id<GRXWriteable>)writeable {
_writeable = writeable;
[_writer startWithWriteable:self];
}
- (void)finishWithError:(NSError *)errorOrNil {
[self finishOutputWithError:errorOrNil];
[self finishInput];
}
@end

@ -40,15 +40,15 @@
// //
// Unless the writeable callback pauses them or stops them early, these writers will do all their // Unless the writeable callback pauses them or stops them early, these writers will do all their
// interactions with the writeable before the start method returns. // interactions with the writeable before the start method returns.
@interface GRXImmediateWriter : NSObject<GRXWriter> @interface GRXImmediateWriter : GRXWriter
// Returns a writer that pulls values from the passed NSEnumerator instance and pushes them to // Returns a writer that pulls values from the passed NSEnumerator instance and pushes them to
// its writeable. The NSEnumerator is released when it finishes. // its writeable. The NSEnumerator is released when it finishes.
+ (id<GRXWriter>)writerWithEnumerator:(NSEnumerator *)enumerator; + (GRXWriter *)writerWithEnumerator:(NSEnumerator *)enumerator;
// Returns a writer that pushes to its writeable the successive values returned by the passed // Returns a writer that pushes to its writeable the successive values returned by the passed
// block. When the block first returns nil, it is released. // block. When the block first returns nil, it is released.
+ (id<GRXWriter>)writerWithValueSupplier:(id (^)())block; + (GRXWriter *)writerWithValueSupplier:(id (^)())block;
// Returns a writer that iterates over the values of the passed container and pushes them to // Returns a writer that iterates over the values of the passed container and pushes them to
// its writeable. The container is released when the iteration is over. // its writeable. The container is released when the iteration is over.
@ -56,18 +56,18 @@
// Note that the usual speed gain of NSFastEnumeration over NSEnumerator results from not having to // Note that the usual speed gain of NSFastEnumeration over NSEnumerator results from not having to
// call one method per element. Because GRXWriteable instances accept values one by one, that speed // call one method per element. Because GRXWriteable instances accept values one by one, that speed
// gain doesn't happen here. // gain doesn't happen here.
+ (id<GRXWriter>)writerWithContainer:(id<NSFastEnumeration>)container; + (GRXWriter *)writerWithContainer:(id<NSFastEnumeration>)container;
// Returns a writer that sends the passed value to its writeable and then finishes (releasing the // Returns a writer that sends the passed value to its writeable and then finishes (releasing the
// value). // value).
+ (id<GRXWriter>)writerWithValue:(id)value; + (GRXWriter *)writerWithValue:(id)value;
// Returns a writer that, as part of its start method, sends the passed error to the writeable // Returns a writer that, as part of its start method, sends the passed error to the writeable
// (then releasing the error). // (then releasing the error).
+ (id<GRXWriter>)writerWithError:(NSError *)error; + (GRXWriter *)writerWithError:(NSError *)error;
// Returns a writer that, as part of its start method, finishes immediately without sending any // Returns a writer that, as part of its start method, finishes immediately without sending any
// values to its writeable. // values to its writeable.
+ (id<GRXWriter>)emptyWriter; + (GRXWriter *)emptyWriter;
@end @end

@ -63,19 +63,19 @@
return [[self alloc] initWithEnumerator:enumerator error:errorOrNil]; return [[self alloc] initWithEnumerator:enumerator error:errorOrNil];
} }
+ (id<GRXWriter>)writerWithEnumerator:(NSEnumerator *)enumerator { + (GRXWriter *)writerWithEnumerator:(NSEnumerator *)enumerator {
return [self writerWithEnumerator:enumerator error:nil]; return [self writerWithEnumerator:enumerator error:nil];
} }
+ (id<GRXWriter>)writerWithValueSupplier:(id (^)())block { + (GRXWriter *)writerWithValueSupplier:(id (^)())block {
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithValueSupplier:block]]; return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithValueSupplier:block]];
} }
+ (id<GRXWriter>)writerWithContainer:(id<NSFastEnumeration>)container { + (GRXWriter *)writerWithContainer:(id<NSFastEnumeration>)container {
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithContainer:container]];; return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithContainer:container]];;
} }
+ (id<GRXWriter>)writerWithValue:(id)value { + (GRXWriter *)writerWithValue:(id)value {
if (value) { if (value) {
return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithSingleValue:value]]; return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithSingleValue:value]];
} else { } else {
@ -83,7 +83,7 @@
} }
} }
+ (id<GRXWriter>)writerWithError:(NSError *)error { + (GRXWriter *)writerWithError:(NSError *)error {
if (error) { if (error) {
return [self writerWithEnumerator:nil error:error]; return [self writerWithEnumerator:nil error:error];
} else { } else {
@ -91,7 +91,7 @@
} }
} }
+ (id<GRXWriter>)emptyWriter { + (GRXWriter *)emptyWriter {
static GRXImmediateWriter *emptyWriter; static GRXImmediateWriter *emptyWriter;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{

@ -38,27 +38,27 @@
@implementation GRXWriter (Immediate) @implementation GRXWriter (Immediate)
+ (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator { + (instancetype)writerWithEnumerator:(NSEnumerator *)enumerator {
return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithEnumerator:enumerator]]; return [GRXImmediateWriter writerWithEnumerator:enumerator];
} }
+ (instancetype)writerWithValueSupplier:(id (^)())block { + (instancetype)writerWithValueSupplier:(id (^)())block {
return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithValueSupplier:block]]; return [GRXImmediateWriter writerWithValueSupplier:block];
} }
+ (instancetype)writerWithContainer:(id<NSFastEnumeration>)container { + (instancetype)writerWithContainer:(id<NSFastEnumeration>)container {
return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithContainer:container]]; return [GRXImmediateWriter writerWithContainer:container];
} }
+ (instancetype)writerWithValue:(id)value { + (instancetype)writerWithValue:(id)value {
return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithValue:value]]; return [GRXImmediateWriter writerWithValue:value];
} }
+ (instancetype)writerWithError:(NSError *)error { + (instancetype)writerWithError:(NSError *)error {
return [[self alloc] initWithWriter:[GRXImmediateWriter writerWithError:error]]; return [GRXImmediateWriter writerWithError:error];
} }
+ (instancetype)emptyWriter { + (instancetype)emptyWriter {
return [[self alloc] initWithWriter:[GRXImmediateWriter emptyWriter]]; return [GRXImmediateWriter emptyWriter];
} }
@end @end

@ -85,7 +85,7 @@ typedef NS_ENUM(NSInteger, GRXWriterState) {
// Unless otherwise indicated by a conforming class, no messages should be sent // Unless otherwise indicated by a conforming class, no messages should be sent
// concurrently to a GRXWriter. I.e., conforming classes aren't required to // concurrently to a GRXWriter. I.e., conforming classes aren't required to
// be thread-safe. // be thread-safe.
@protocol GRXWriter <NSObject> @interface GRXWriter : NSObject
// This property can be used to query the current state of the writer, which // This property can be used to query the current state of the writer, which
// determines how it might currently use its writeable. Some state transitions can // determines how it might currently use its writeable. Some state transitions can
@ -116,12 +116,3 @@ typedef NS_ENUM(NSInteger, GRXWriterState) {
// can't remember the details in the presence of concurrency. // can't remember the details in the presence of concurrency.
- (void)finishWithError:(NSError *)errorOrNil; - (void)finishWithError:(NSError *)errorOrNil;
@end @end
// A "proxy" class that simply forwards values, completion, and errors from its
// input writer to its writeable.
// It is useful as a superclass for pipes that act as a transformation of their
// input writer, and for classes that represent objects with input and
// output sequences of values, like an RPC.
@interface GRXWriter : NSObject<GRXWriter>
- (instancetype)initWithWriter:(id<GRXWriter>)writer NS_DESIGNATED_INITIALIZER;
@end

@ -33,80 +33,6 @@
#import "GRXWriter.h" #import "GRXWriter.h"
@interface GRXWriter () <GRXWriteable> @implementation GRXWriter
@end
@implementation GRXWriter {
id<GRXWriter> _writer;
id<GRXWriteable> _writeable;
}
- (instancetype)init {
return [self initWithWriter:nil];
}
// Designated initializer
- (instancetype)initWithWriter:(id<GRXWriter>)writer {
if (!writer) {
[NSException raise:NSInvalidArgumentException format:@"writer can't be nil."];
}
if ((self = [super init])) {
_writer = writer;
}
return self;
}
// This is used to send a completion or an error to the writeable. It nillifies
// our reference to it in order to guarantee no more messages are sent to it,
// and to release it.
- (void)finishOutputWithError:(NSError *)errorOrNil {
id<GRXWriteable> writeable = _writeable;
_writeable = nil;
[writeable writesFinishedWithError:errorOrNil];
}
// This is used to stop the input writer. It nillifies our reference to it
// to release it.
- (void)finishInput {
id<GRXWriter> writer = _writer;
_writer = nil;
writer.state = GRXWriterStateFinished;
}
#pragma mark GRXWriteable implementation
- (void)writeValue:(id)value {
[_writeable writeValue:value];
}
- (void)writesFinishedWithError:(NSError *)errorOrNil {
_writer = nil;
[self finishOutputWithError:errorOrNil];
}
#pragma mark GRXWriter implementation
- (GRXWriterState)state {
return _writer ? _writer.state : GRXWriterStateFinished;
}
- (void)setState:(GRXWriterState)state {
if (state == GRXWriterStateFinished) {
_writeable = nil;
[self finishInput];
} else {
_writer.state = state;
}
}
- (void)startWithWriteable:(id<GRXWriteable>)writeable {
_writeable = writeable;
[_writer startWithWriteable:self];
}
- (void)finishWithError:(NSError *)errorOrNil {
[self finishOutputWithError:errorOrNil];
[self finishInput];
}
@end @end

@ -31,10 +31,10 @@
* *
*/ */
#import "RxLibrary/GRXWriter.h" #import "RxLibrary/GRXForwardingWriter.h"
// A "proxy" writer that transforms all the values of its input writer by using a mapping function. // A "proxy" writer that transforms all the values of its input writer by using a mapping function.
@interface GRXMappingWriter : GRXWriter @interface GRXMappingWriter : GRXForwardingWriter
- (instancetype)initWithWriter:(id<GRXWriter>)writer map:(id (^)(id value))map - (instancetype)initWithWriter:(GRXWriter *)writer map:(id (^)(id value))map
NS_DESIGNATED_INITIALIZER; NS_DESIGNATED_INITIALIZER;
@end @end

@ -37,19 +37,19 @@ static id (^kIdentity)(id value) = ^id(id value) {
return value; return value;
}; };
@interface GRXWriter () <GRXWriteable> @interface GRXForwardingWriter () <GRXWriteable>
@end @end
@implementation GRXMappingWriter { @implementation GRXMappingWriter {
id (^_map)(id value); id (^_map)(id value);
} }
- (instancetype)initWithWriter:(id<GRXWriter>)writer { - (instancetype)initWithWriter:(GRXWriter *)writer {
return [self initWithWriter:writer map:nil]; return [self initWithWriter:writer map:nil];
} }
// Designated initializer // Designated initializer
- (instancetype)initWithWriter:(id<GRXWriter>)writer map:(id (^)(id value))map { - (instancetype)initWithWriter:(GRXWriter *)writer map:(id (^)(id value))map {
if ((self = [super initWithWriter:writer])) { if ((self = [super initWithWriter:writer])) {
_map = map ?: kIdentity; _map = map ?: kIdentity;
} }

@ -120,7 +120,7 @@ static ProtoMethod *kUnaryCallMethod;
request.responseSize = 100; request.responseSize = 100;
request.fillUsername = YES; request.fillUsername = YES;
request.fillOauthScope = YES; request.fillOauthScope = YES;
id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[request data]]; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
path:kUnaryCallMethod.HTTPPath path:kUnaryCallMethod.HTTPPath
@ -150,7 +150,7 @@ static ProtoMethod *kUnaryCallMethod;
RMTSimpleRequest *request = [RMTSimpleRequest message]; RMTSimpleRequest *request = [RMTSimpleRequest message];
request.fillUsername = YES; request.fillUsername = YES;
request.fillOauthScope = YES; request.fillOauthScope = YES;
id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[request data]]; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
path:kUnaryCallMethod.HTTPPath path:kUnaryCallMethod.HTTPPath

@ -143,7 +143,7 @@
RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message]; RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message];
request4.payload.body = [NSMutableData dataWithLength:45904]; request4.payload.body = [NSMutableData dataWithLength:45904];
id<GRXWriter> writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]]; GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]];
[_service streamingInputCallWithRequestsWriter:writer [_service streamingInputCallWithRequestsWriter:writer
handler:^(RMTStreamingInputCallResponse *response, handler:^(RMTStreamingInputCallResponse *response,

@ -64,7 +64,7 @@ static NSString * const kService = @"RouteGuide";
// interface:kService // interface:kService
// method:@"EmptyCall"]; // method:@"EmptyCall"];
// //
// id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[NSData data]]; // GRXWriter *requestsWriter = [GRXWriter writerWithValue:[NSData data]];
// //
// GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost // GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost
// method:method // method:method
@ -91,7 +91,7 @@ static NSString * const kService = @"RouteGuide";
service:kService service:kService
method:@"RecordRoute"]; method:@"RecordRoute"];
id<GRXWriter> requestsWriter = [GRXWriter emptyWriter]; GRXWriter *requestsWriter = [GRXWriter emptyWriter];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost
path:method.HTTPPath path:method.HTTPPath
@ -122,7 +122,7 @@ static NSString * const kService = @"RouteGuide";
RGDPoint *point = [RGDPoint message]; RGDPoint *point = [RGDPoint message];
point.latitude = 28E7; point.latitude = 28E7;
point.longitude = -15E7; point.longitude = -15E7;
id<GRXWriter> requestsWriter = [GRXWriter writerWithValue:[point data]]; GRXWriter *requestsWriter = [GRXWriter writerWithValue:[point data]];
GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost GRPCCall *call = [[GRPCCall alloc] initWithHost:kRouteGuideHost
path:method.HTTPPath path:method.HTTPPath

Loading…
Cancel
Save