mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.7 KiB
107 lines
3.7 KiB
/* |
|
* |
|
* Copyright 2015 gRPC authors. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
*/ |
|
|
|
#import "GRXWriteable.h" |
|
|
|
@implementation GRXWriteable { |
|
GRXValueHandler _valueHandler; |
|
GRXCompletionHandler _completionHandler; |
|
} |
|
|
|
+ (instancetype)writeableWithSingleHandler:(GRXSingleHandler)handler { |
|
if (!handler) { |
|
return [[self alloc] init]; |
|
} |
|
// We nilify this variable when the block is invoked, so that handler is only invoked once even if |
|
// the writer tries to write multiple values. |
|
__block GRXEventHandler eventHandler = ^(BOOL done, id value, NSError *error) { |
|
// Nillify eventHandler before invoking handler, in case the latter causes the former to be |
|
// executed recursively. Because blocks can be deallocated even during execution, we have to |
|
// first retain handler locally to guarantee it's valid. |
|
// TODO(jcanizales): Just turn this craziness into a simple subclass of GRXWriteable. |
|
GRXSingleHandler singleHandler = handler; |
|
eventHandler = nil; |
|
|
|
if (value) { |
|
singleHandler(value, nil); |
|
} else if (error) { |
|
singleHandler(nil, error); |
|
} else { |
|
NSDictionary *userInfo = |
|
@{NSLocalizedDescriptionKey : @"The writer finished without producing any value."}; |
|
// Even though RxLibrary is independent of gRPC, the domain and code here are, for the moment, |
|
// set to the values of kGRPCErrorDomain and GRPCErrorCodeInternal. This way, the error formed |
|
// is the one user of gRPC would expect if the server failed to produce a response. |
|
// |
|
// TODO(jcanizales): Figure out a way to keep errors of RxLibrary generic without making users |
|
// of gRPC take care of two different error domains and error code enums. A possibility is to |
|
// add error handling to GRXWriters or GRXWriteables, and use them to translate errors between |
|
// the two domains. |
|
static NSString *kGRPCErrorDomain = @"io.grpc"; |
|
static NSUInteger kGRPCErrorCodeInternal = 13; |
|
singleHandler(nil, [NSError errorWithDomain:kGRPCErrorDomain |
|
code:kGRPCErrorCodeInternal |
|
userInfo:userInfo]); |
|
} |
|
}; |
|
return [self writeableWithEventHandler:^(BOOL done, id value, NSError *error) { |
|
if (eventHandler) { |
|
eventHandler(done, value, error); |
|
} |
|
}]; |
|
} |
|
|
|
+ (instancetype)writeableWithEventHandler:(GRXEventHandler)handler { |
|
if (!handler) { |
|
return [[self alloc] init]; |
|
} |
|
return [[self alloc] |
|
initWithValueHandler:^(id value) { |
|
handler(NO, value, nil); |
|
} |
|
completionHandler:^(NSError *errorOrNil) { |
|
handler(YES, nil, errorOrNil); |
|
}]; |
|
} |
|
|
|
- (instancetype)init { |
|
return [self initWithValueHandler:nil completionHandler:nil]; |
|
} |
|
|
|
// Designated initializer |
|
- (instancetype)initWithValueHandler:(GRXValueHandler)valueHandler |
|
completionHandler:(GRXCompletionHandler)completionHandler { |
|
if ((self = [super init])) { |
|
_valueHandler = valueHandler; |
|
_completionHandler = completionHandler; |
|
} |
|
return self; |
|
} |
|
|
|
- (void)writeValue:(id)value { |
|
if (_valueHandler) { |
|
_valueHandler(value); |
|
} |
|
} |
|
|
|
- (void)writesFinishedWithError:(NSError *)errorOrNil { |
|
if (_completionHandler) { |
|
_completionHandler(errorOrNil); |
|
} |
|
} |
|
@end
|
|
|