Created
February 21, 2018 21:52
-
-
Save MrMage/bf10b504ec02c558f0b3a1a01b5d25e9 to your computer and use it in GitHub Desktop.
Result of exploratory codegen changes to improve the testability of SwiftGRPC generated code (see https://github.com/grpc/grpc-swift/issues/120).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* DO NOT EDIT. | |
* | |
* Generated by the protocol buffer compiler. | |
* Source: Sync/Proto/echo.proto | |
* | |
*/ | |
/* | |
* Copyright 2018, SwiftGRPC Authors All rights reserved. | |
* | |
* 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 Foundation | |
import Dispatch | |
import SwiftGRPC | |
import SwiftProtobuf | |
/// Type for errors thrown from generated client code. | |
public enum Echo_EchoClientError : Error { | |
case endOfStream | |
case invalidMessageReceived | |
case error(c: CallResult) | |
} | |
/// Get (Unary) | |
public protocol Echo_EchoGetCall { | |
/// Cancel the call. | |
func cancel() | |
} | |
/// Get (Unary) | |
fileprivate final class Echo_EchoGetCallImpl: Echo_EchoGetCall { | |
private var call : Call | |
/// Create a call. | |
init(_ channel: Channel) { | |
self.call = channel.makeCall("/echo.Echo/Get") | |
} | |
/// Run the call. Blocks until the reply is received. | |
/// - Throws: `BinaryEncodingError` if encoding fails. `CallError` if fails to call. `Echo_EchoClientError` if receives no response. | |
func run(request: Echo_EchoRequest, | |
metadata: Metadata) throws -> Echo_EchoResponse { | |
let sem = DispatchSemaphore(value: 0) | |
var returnCallResult : CallResult! | |
var returnResponse : Echo_EchoResponse? | |
_ = try start(request:request, metadata:metadata) {response, callResult in | |
returnResponse = response | |
returnCallResult = callResult | |
sem.signal() | |
} | |
_ = sem.wait(timeout: DispatchTime.distantFuture) | |
if let returnResponse = returnResponse { | |
return returnResponse | |
} else { | |
throw Echo_EchoClientError.error(c: returnCallResult) | |
} | |
} | |
/// Start the call. Nonblocking. | |
/// - Throws: `BinaryEncodingError` if encoding fails. `CallError` if fails to call. | |
func start(request: Echo_EchoRequest, | |
metadata: Metadata, | |
completion: @escaping (Echo_EchoResponse?, CallResult)->()) | |
throws -> Echo_EchoGetCall { | |
let requestData = try request.serializedData() | |
try call.start(.unary, | |
metadata:metadata, | |
message:requestData) | |
{(callResult) in | |
if let responseData = callResult.resultData, | |
let response = try? Echo_EchoResponse(serializedData:responseData) { | |
completion(response, callResult) | |
} else { | |
completion(nil, callResult) | |
} | |
} | |
return self | |
} | |
func cancel() { | |
call.cancel() | |
} | |
} | |
/// Expand (Server Streaming) | |
public protocol Echo_EchoExpandCall { | |
/// Call this to wait for a result. Blocking. | |
func receive() throws -> Echo_EchoResponse | |
/// Call this to wait for a result. Nonblocking. | |
func receive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws | |
/// Cancel the call. | |
func cancel() | |
} | |
public extension Echo_EchoExpandCall { | |
func receive() throws -> Echo_EchoResponse { | |
var returnError : Echo_EchoClientError? | |
var returnResponse : Echo_EchoResponse! | |
let sem = DispatchSemaphore(value: 0) | |
do { | |
try receive() {response, error in | |
returnResponse = response | |
returnError = error | |
sem.signal() | |
} | |
_ = sem.wait(timeout: DispatchTime.distantFuture) | |
} | |
if let returnError = returnError { | |
throw returnError | |
} | |
return returnResponse | |
} | |
} | |
fileprivate final class Echo_EchoExpandCallImpl: Echo_EchoExpandCall { | |
private var call : Call | |
/// Create a call. | |
init(_ channel: Channel) { | |
self.call = channel.makeCall("/echo.Echo/Expand") | |
} | |
/// Call this once with the message to send. Nonblocking. | |
func start(request: Echo_EchoRequest, | |
metadata: Metadata, | |
completion: @escaping (CallResult) -> ()) | |
throws -> Echo_EchoExpandCall { | |
let requestData = try request.serializedData() | |
try call.start(.serverStreaming, | |
metadata:metadata, | |
message:requestData, | |
completion:completion) | |
return self | |
} | |
func receive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws { | |
do { | |
try call.receiveMessage() {(responseData) in | |
if let responseData = responseData { | |
if let response = try? Echo_EchoResponse(serializedData:responseData) { | |
completion(response, nil) | |
} else { | |
completion(nil, Echo_EchoClientError.invalidMessageReceived) | |
} | |
} else { | |
completion(nil, Echo_EchoClientError.endOfStream) | |
} | |
} | |
} | |
} | |
/// Cancel the call. | |
func cancel() { | |
call.cancel() | |
} | |
} | |
/// Simple fake implementation of Echo_EchoExpandCall that returns a previously-defined set of results. | |
class Echo_EchoExpandCallStub: Echo_EchoExpandCall { | |
var outputs: [Echo_EchoResponse] = [] | |
func receive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws { | |
if let output = outputs.first { | |
outputs.removeFirst() | |
completion(output, nil) | |
} else { | |
completion(nil, Echo_EchoClientError.endOfStream) | |
} | |
} | |
func cancel() { } | |
} | |
/// Collect (Client Streaming) | |
public protocol Echo_EchoCollectCall { | |
/// Call this to send each message in the request stream. Nonblocking. | |
func send(_ message:Echo_EchoRequest, errorHandler:@escaping (Error)->()) throws | |
/// Call this to close the connection and wait for a response. Blocking. | |
func closeAndReceive() throws -> Echo_EchoResponse | |
/// Call this to close the connection and wait for a response. Nonblocking. | |
func closeAndReceive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws | |
/// Cancel the call. | |
func cancel() | |
} | |
public extension Echo_EchoCollectCall { | |
func closeAndReceive() throws -> Echo_EchoResponse { | |
var returnError : Echo_EchoClientError? | |
var returnResponse : Echo_EchoResponse! | |
let sem = DispatchSemaphore(value: 0) | |
do { | |
try closeAndReceive() {response, error in | |
returnResponse = response | |
returnError = error | |
sem.signal() | |
} | |
_ = sem.wait(timeout: DispatchTime.distantFuture) | |
} catch (let error) { | |
throw error | |
} | |
if let returnError = returnError { | |
throw returnError | |
} | |
return returnResponse | |
} | |
} | |
fileprivate final class Echo_EchoCollectCallImpl: Echo_EchoCollectCall { | |
private var call : Call | |
/// Create a call. | |
init(_ channel: Channel) { | |
self.call = channel.makeCall("/echo.Echo/Collect") | |
} | |
/// Call this to start a call. Nonblocking. | |
func start(metadata:Metadata, completion:@escaping (CallResult)->()) | |
throws -> Echo_EchoCollectCall { | |
try self.call.start(.clientStreaming, metadata:metadata, completion:completion) | |
return self | |
} | |
func send(_ message:Echo_EchoRequest, errorHandler:@escaping (Error)->()) throws { | |
let messageData = try message.serializedData() | |
try call.sendMessage(data:messageData, errorHandler:errorHandler) | |
} | |
func closeAndReceive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws { | |
do { | |
try call.receiveMessage() {(responseData) in | |
if let responseData = responseData, | |
let response = try? Echo_EchoResponse(serializedData:responseData) { | |
completion(response, nil) | |
} else { | |
completion(nil, Echo_EchoClientError.invalidMessageReceived) | |
} | |
} | |
try call.close(completion:{}) | |
} catch (let error) { | |
throw error | |
} | |
} | |
func cancel() { | |
call.cancel() | |
} | |
} | |
/// Simple fake implementation of Echo_EchoCollectCall | |
/// stores sent values for later verification and finall returns a previously-defined result. | |
class Echo_EchoCollectCallStub: Echo_EchoCollectCall { | |
var inputs: [Echo_EchoRequest] = [] | |
var output: Echo_EchoResponse? | |
func send(_ message:Echo_EchoRequest, errorHandler:@escaping (Error)->()) throws { | |
inputs.append(message) | |
} | |
func closeAndReceive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws { | |
completion(output!, nil) | |
} | |
func cancel() { } | |
} | |
/// Update (Bidirectional Streaming) | |
public protocol Echo_EchoUpdateCall { | |
/// Call this to wait for a result. Blocking. | |
func receive() throws -> Echo_EchoResponse | |
/// Call this to wait for a result. Nonblocking. | |
func receive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws | |
/// Call this to send each message in the request stream. | |
func send(_ message:Echo_EchoRequest, errorHandler:@escaping (Error)->()) throws | |
/// Call this to close the sending connection. Blocking. | |
func closeSend() throws | |
/// Call this to close the sending connection. Nonblocking. | |
func closeSend(completion:@escaping ()->()) throws | |
/// Cancel the call. | |
func cancel() | |
} | |
public extension Echo_EchoUpdateCall { | |
func receive() throws -> Echo_EchoResponse { | |
var returnError : Echo_EchoClientError? | |
var returnMessage : Echo_EchoResponse! | |
let sem = DispatchSemaphore(value: 0) | |
do { | |
try receive() {response, error in | |
returnMessage = response | |
returnError = error | |
sem.signal() | |
} | |
_ = sem.wait(timeout: DispatchTime.distantFuture) | |
} | |
if let returnError = returnError { | |
throw returnError | |
} | |
return returnMessage | |
} | |
func closeSend() throws { | |
let sem = DispatchSemaphore(value: 0) | |
try closeSend() { | |
sem.signal() | |
} | |
_ = sem.wait(timeout: DispatchTime.distantFuture) | |
} | |
} | |
fileprivate final class Echo_EchoUpdateCallImpl: Echo_EchoUpdateCall { | |
private var call : Call | |
/// Create a call. | |
init(_ channel: Channel) { | |
self.call = channel.makeCall("/echo.Echo/Update") | |
} | |
/// Call this to start a call. Nonblocking. | |
func start(metadata:Metadata, completion:@escaping (CallResult)->()) | |
throws -> Echo_EchoUpdateCall { | |
try self.call.start(.bidiStreaming, metadata:metadata, completion:completion) | |
return self | |
} | |
func receive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws { | |
do { | |
try call.receiveMessage() {(data) in | |
if let data = data { | |
if let returnMessage = try? Echo_EchoResponse(serializedData:data) { | |
completion(returnMessage, nil) | |
} else { | |
completion(nil, Echo_EchoClientError.invalidMessageReceived) | |
} | |
} else { | |
completion(nil, Echo_EchoClientError.endOfStream) | |
} | |
} | |
} | |
} | |
func send(_ message:Echo_EchoRequest, errorHandler:@escaping (Error)->()) throws { | |
let messageData = try message.serializedData() | |
try call.sendMessage(data:messageData, errorHandler:errorHandler) | |
} | |
func closeSend(completion:@escaping ()->()) throws { | |
try call.close() { | |
completion() | |
} | |
} | |
func cancel() { | |
call.cancel() | |
} | |
} | |
/// Simple fake implementation of Echo_EchoUpdateCall that returns a previously-defined set of results | |
/// and stores sent values for later verification. | |
class Echo_EchoUpdateCallStub: Echo_EchoUpdateCall { | |
var inputs: [Echo_EchoRequest] = [] | |
var outputs: [Echo_EchoResponse] = [] | |
func receive(completion:@escaping (Echo_EchoResponse?, Echo_EchoClientError?)->()) throws { | |
if let output = outputs.first { | |
outputs.removeFirst() | |
completion(output, nil) | |
} else { | |
completion(nil, Echo_EchoClientError.endOfStream) | |
} | |
} | |
func send(_ message:Echo_EchoRequest, errorHandler:@escaping (Error)->()) throws { | |
inputs.append(message) | |
} | |
func closeSend(completion:@escaping ()->()) throws { completion() } | |
func cancel() { } | |
} | |
/// Instantiate Echo_EchoServiceImpl, then call methods of this protocol to make API calls. | |
public protocol Echo_EchoService { | |
var channel: Channel { get } | |
/// This metadata will be sent with all requests. | |
var metadata: Metadata { get } | |
/// This property allows the service host name to be overridden. | |
/// For example, it can be used to make calls to "localhost:8080" | |
/// appear to be to "example.com". | |
var host : String { get } | |
/// This property allows the service timeout to be overridden. | |
var timeout : TimeInterval { get } | |
/// Synchronous. Unary. | |
func get(_ request: Echo_EchoRequest) throws -> Echo_EchoResponse | |
/// Asynchronous. Unary. | |
func get(_ request: Echo_EchoRequest, | |
completion: @escaping (Echo_EchoResponse?, CallResult)->()) throws -> Echo_EchoGetCall | |
/// Asynchronous. Server-streaming. | |
/// Send the initial message. | |
/// Use methods on the returned object to get streamed responses. | |
func expand(_ request: Echo_EchoRequest, completion: @escaping (CallResult)->()) | |
throws -> Echo_EchoExpandCall | |
/// Asynchronous. Client-streaming. | |
/// Use methods on the returned object to stream messages and | |
/// to close the connection and wait for a final response. | |
func collect(completion: @escaping (CallResult)->()) | |
throws -> Echo_EchoCollectCall | |
/// Asynchronous. Bidirectional-streaming. | |
/// Use methods on the returned object to stream messages, | |
/// to wait for replies, and to close the connection. | |
func update(completion: @escaping (CallResult)->()) | |
throws -> Echo_EchoUpdateCall | |
} | |
public final class Echo_EchoServiceImpl: Echo_EchoService { | |
public private(set) var channel: Channel | |
public var metadata : Metadata | |
public var host : String { | |
get { | |
return self.channel.host | |
} | |
set { | |
self.channel.host = newValue | |
} | |
} | |
public var timeout : TimeInterval { | |
get { | |
return self.channel.timeout | |
} | |
set { | |
self.channel.timeout = newValue | |
} | |
} | |
/// Create a client. | |
public init(address: String, secure: Bool = true) { | |
SwiftGRPC.initialize() | |
channel = Channel(address:address, secure:secure) | |
metadata = Metadata() | |
} | |
/// Create a client that makes secure connections with a custom certificate and (optional) hostname. | |
public init(address: String, certificates: String, host: String?) { | |
SwiftGRPC.initialize() | |
channel = Channel(address:address, certificates:certificates, host:host) | |
metadata = Metadata() | |
} | |
/// Synchronous. Unary. | |
public func get(_ request: Echo_EchoRequest) | |
throws | |
-> Echo_EchoResponse { | |
return try Echo_EchoGetCallImpl(channel).run(request:request, metadata:metadata) | |
} | |
/// Asynchronous. Unary. | |
public func get(_ request: Echo_EchoRequest, | |
completion: @escaping (Echo_EchoResponse?, CallResult)->()) | |
throws | |
-> Echo_EchoGetCall { | |
return try Echo_EchoGetCallImpl(channel).start(request:request, | |
metadata:metadata, | |
completion:completion) | |
} | |
/// Asynchronous. Server-streaming. | |
/// Send the initial message. | |
/// Use methods on the returned object to get streamed responses. | |
public func expand(_ request: Echo_EchoRequest, completion: @escaping (CallResult)->()) | |
throws | |
-> Echo_EchoExpandCall { | |
return try Echo_EchoExpandCallImpl(channel).start(request:request, metadata:metadata, completion:completion) | |
} | |
/// Asynchronous. Client-streaming. | |
/// Use methods on the returned object to stream messages and | |
/// to close the connection and wait for a final response. | |
public func collect(completion: @escaping (CallResult)->()) | |
throws | |
-> Echo_EchoCollectCall { | |
return try Echo_EchoCollectCallImpl(channel).start(metadata:metadata, completion:completion) | |
} | |
/// Asynchronous. Bidirectional-streaming. | |
/// Use methods on the returned object to stream messages, | |
/// to wait for replies, and to close the connection. | |
public func update(completion: @escaping (CallResult)->()) | |
throws | |
-> Echo_EchoUpdateCall { | |
return try Echo_EchoUpdateCallImpl(channel).start(metadata:metadata, completion:completion) | |
} | |
} | |
/// Simple fake implementation of Echo_EchoService that returns a previously-defined set of results | |
/// and stores request values passed into it for later verification. | |
/// Note: completion blocks are NOT called with this default implementation, and asynchronous unary calls are NOT implemented! | |
class Echo_EchoServiceStub: Echo_EchoService { | |
var channel: Channel { fatalError("not implemented") } | |
var metadata = Metadata() | |
var host = "" | |
var timeout: TimeInterval = 0 | |
var getRequests: [Echo_EchoRequest] = [] | |
var getResponses: [Echo_EchoResponse] = [] | |
func get(_ request: Echo_EchoRequest) throws -> Echo_EchoResponse { | |
getRequests.append(request) | |
defer { getResponses.removeFirst() } | |
return getResponses.first! | |
} | |
func get(_ request: Echo_EchoRequest, | |
completion: @escaping (Echo_EchoResponse?, CallResult)->()) throws -> Echo_EchoGetCall { | |
fatalError("not implemented") | |
} | |
var expandRequests: [Echo_EchoRequest] = [] | |
var expandCalls: [Echo_EchoExpandCall] = [] | |
func expand(_ request: Echo_EchoRequest, completion: @escaping (CallResult)->()) | |
throws -> Echo_EchoExpandCall { | |
expandRequests.append(request) | |
defer { expandCalls.removeFirst() } | |
return expandCalls.first! | |
} | |
var collectCalls: [Echo_EchoCollectCall] = [] | |
func collect(completion: @escaping (CallResult)->()) | |
throws -> Echo_EchoCollectCall { | |
defer { collectCalls.removeFirst() } | |
return collectCalls.first! | |
} | |
var updateCalls: [Echo_EchoUpdateCall] = [] | |
func update(completion: @escaping (CallResult)->()) | |
throws -> Echo_EchoUpdateCall { | |
defer { updateCalls.removeFirst() } | |
return updateCalls.first! | |
} | |
} | |
/// Type for errors thrown from generated server code. | |
public enum Echo_EchoServerError : Error { | |
case endOfStream | |
} | |
/// To build a server, implement a class that conforms to this protocol. | |
public protocol Echo_EchoProvider { | |
func get(request : Echo_EchoRequest, session : Echo_EchoGetSession) throws -> Echo_EchoResponse | |
func expand(request : Echo_EchoRequest, session : Echo_EchoExpandSession) throws | |
func collect(session : Echo_EchoCollectSession) throws | |
func update(session : Echo_EchoUpdateSession) throws | |
} | |
/// Common properties available in each service session. | |
public protocol Echo_EchoSession { | |
var requestMetadata : Metadata { get } | |
var statusCode : StatusCode { get } | |
var statusMessage : String { get } | |
var initialMetadata : Metadata { get } | |
var trailingMetadata : Metadata { get } | |
} | |
fileprivate class Echo_EchoSessionImpl: Echo_EchoSession { | |
var handler : SwiftGRPC.Handler | |
var requestMetadata : Metadata { return handler.requestMetadata } | |
var statusCode : StatusCode = .ok | |
var statusMessage : String = "OK" | |
var initialMetadata : Metadata = Metadata() | |
var trailingMetadata : Metadata = Metadata() | |
init(handler:SwiftGRPC.Handler) { | |
self.handler = handler | |
} | |
} | |
class Echo_EchoSessionStub: Echo_EchoSession { | |
var requestMetadata = Metadata() | |
var statusCode = StatusCode.ok | |
var statusMessage = "OK" | |
var initialMetadata = Metadata() | |
var trailingMetadata = Metadata() | |
} | |
// Get (Unary Streaming) | |
public protocol Echo_EchoGetSession : Echo_EchoSession { } | |
fileprivate final class Echo_EchoGetSessionImpl : Echo_EchoSessionImpl, Echo_EchoGetSession { | |
private var provider : Echo_EchoProvider | |
/// Create a session. | |
init(handler:SwiftGRPC.Handler, provider: Echo_EchoProvider) { | |
self.provider = provider | |
super.init(handler:handler) | |
} | |
/// Run the session. Internal. | |
func run(queue:DispatchQueue) throws { | |
try handler.receiveMessage(initialMetadata:initialMetadata) {(requestData) in | |
if let requestData = requestData { | |
let requestMessage = try Echo_EchoRequest(serializedData:requestData) | |
let replyMessage = try self.provider.get(request:requestMessage, session: self) | |
try self.handler.sendResponse(message:replyMessage.serializedData(), | |
statusCode:self.statusCode, | |
statusMessage:self.statusMessage, | |
trailingMetadata:self.trailingMetadata) | |
} | |
} | |
} | |
} | |
/// Trivial fake implementation of Echo_EchoGetSession. | |
class Echo_EchoGetSessionStub : Echo_EchoSessionStub, Echo_EchoGetSession { } | |
// Expand (Server Streaming) | |
public protocol Echo_EchoExpandSession : Echo_EchoSession { | |
/// Send a message. Nonblocking. | |
func send(_ response: Echo_EchoResponse, completion: @escaping ()->()) throws | |
} | |
fileprivate final class Echo_EchoExpandSessionImpl : Echo_EchoSessionImpl, Echo_EchoExpandSession { | |
private var provider : Echo_EchoProvider | |
/// Create a session. | |
init(handler:SwiftGRPC.Handler, provider: Echo_EchoProvider) { | |
self.provider = provider | |
super.init(handler:handler) | |
} | |
func send(_ response: Echo_EchoResponse, completion: @escaping ()->()) throws { | |
try handler.sendResponse(message:response.serializedData()) {completion()} | |
} | |
/// Run the session. Internal. | |
func run(queue:DispatchQueue) throws { | |
try self.handler.receiveMessage(initialMetadata:initialMetadata) {(requestData) in | |
if let requestData = requestData { | |
do { | |
let requestMessage = try Echo_EchoRequest(serializedData:requestData) | |
// to keep providers from blocking the server thread, | |
// we dispatch them to another queue. | |
queue.async { | |
do { | |
try self.provider.expand(request:requestMessage, session: self) | |
try self.handler.sendStatus(statusCode:self.statusCode, | |
statusMessage:self.statusMessage, | |
trailingMetadata:self.trailingMetadata, | |
completion:{}) | |
} catch (let error) { | |
print("error: \(error)") | |
} | |
} | |
} catch (let error) { | |
print("error: \(error)") | |
} | |
} | |
} | |
} | |
} | |
/// Simple fake implementation of Echo_EchoExpandSession that returns a previously-defined set of results | |
/// and stores sent values for later verification. | |
class Echo_EchoExpandSessionStub : Echo_EchoSessionStub, Echo_EchoExpandSession { | |
var outputs: [Echo_EchoResponse] = [] | |
func send(_ response: Echo_EchoResponse, completion: @escaping ()->()) throws { | |
outputs.append(response) | |
} | |
func close() throws { } | |
} | |
// Collect (Client Streaming) | |
public protocol Echo_EchoCollectSession : Echo_EchoSession { | |
/// Receive a message. Blocks until a message is received or the client closes the connection. | |
func receive() throws -> Echo_EchoRequest | |
/// Send a response and close the connection. | |
func sendAndClose(_ response: Echo_EchoResponse) throws | |
} | |
fileprivate final class Echo_EchoCollectSessionImpl : Echo_EchoSessionImpl, Echo_EchoCollectSession { | |
private var provider : Echo_EchoProvider | |
/// Create a session. | |
init(handler:SwiftGRPC.Handler, provider: Echo_EchoProvider) { | |
self.provider = provider | |
super.init(handler:handler) | |
} | |
func receive() throws -> Echo_EchoRequest { | |
let sem = DispatchSemaphore(value: 0) | |
var requestMessage : Echo_EchoRequest? | |
try self.handler.receiveMessage() {(requestData) in | |
if let requestData = requestData { | |
requestMessage = try? Echo_EchoRequest(serializedData:requestData) | |
} | |
sem.signal() | |
} | |
_ = sem.wait(timeout: DispatchTime.distantFuture) | |
if requestMessage == nil { | |
throw Echo_EchoServerError.endOfStream | |
} | |
return requestMessage! | |
} | |
func sendAndClose(_ response: Echo_EchoResponse) throws { | |
try self.handler.sendResponse(message:response.serializedData(), | |
statusCode:self.statusCode, | |
statusMessage:self.statusMessage, | |
trailingMetadata:self.trailingMetadata) | |
} | |
/// Run the session. Internal. | |
func run(queue:DispatchQueue) throws { | |
try self.handler.sendMetadata(initialMetadata:initialMetadata) { | |
queue.async { | |
do { | |
try self.provider.collect(session:self) | |
} catch (let error) { | |
print("error \(error)") | |
} | |
} | |
} | |
} | |
} | |
/// Simple fake implementation of Echo_EchoCollectSession that returns a previously-defined set of results | |
/// and stores sent values for later verification. | |
class Echo_EchoCollectSessionStub: Echo_EchoSessionStub, Echo_EchoCollectSession { | |
var inputs: [Echo_EchoRequest] = [] | |
var output: Echo_EchoResponse? | |
func receive() throws -> Echo_EchoRequest { | |
if let input = inputs.first { | |
inputs.removeFirst() | |
return input | |
} else { | |
throw Echo_EchoClientError.endOfStream | |
} | |
} | |
func sendAndClose(_ response: Echo_EchoResponse) throws { | |
output = response | |
} | |
func close() throws { } | |
} | |
// Update (Bidirectional Streaming) | |
public protocol Echo_EchoUpdateSession : Echo_EchoSession { | |
/// Receive a message. Blocks until a message is received or the client closes the connection. | |
func receive() throws -> Echo_EchoRequest | |
/// Send a message. Nonblocking. | |
func send(_ response: Echo_EchoResponse, completion: @escaping ()->()) throws | |
/// Close a connection. Blocks until the connection is closed. | |
func close() throws | |
} | |
fileprivate final class Echo_EchoUpdateSessionImpl : Echo_EchoSessionImpl, Echo_EchoUpdateSession { | |
private var provider : Echo_EchoProvider | |
/// Create a session. | |
init(handler:SwiftGRPC.Handler, provider: Echo_EchoProvider) { | |
self.provider = provider | |
super.init(handler:handler) | |
} | |
func receive() throws -> Echo_EchoRequest { | |
let sem = DispatchSemaphore(value: 0) | |
var requestMessage : Echo_EchoRequest? | |
try self.handler.receiveMessage() {(requestData) in | |
if let requestData = requestData { | |
do { | |
requestMessage = try Echo_EchoRequest(serializedData:requestData) | |
} catch (let error) { | |
print("error \(error)") | |
} | |
} | |
sem.signal() | |
} | |
_ = sem.wait(timeout: DispatchTime.distantFuture) | |
if let requestMessage = requestMessage { | |
return requestMessage | |
} else { | |
throw Echo_EchoServerError.endOfStream | |
} | |
} | |
func send(_ response: Echo_EchoResponse, completion: @escaping ()->()) throws { | |
try handler.sendResponse(message:response.serializedData()) {completion()} | |
} | |
func close() throws { | |
let sem = DispatchSemaphore(value: 0) | |
try self.handler.sendStatus(statusCode:self.statusCode, | |
statusMessage:self.statusMessage, | |
trailingMetadata:self.trailingMetadata) { | |
sem.signal() | |
} | |
_ = sem.wait(timeout: DispatchTime.distantFuture) | |
} | |
/// Run the session. Internal. | |
func run(queue:DispatchQueue) throws { | |
try self.handler.sendMetadata(initialMetadata:initialMetadata) { | |
queue.async { | |
do { | |
try self.provider.update(session:self) | |
} catch (let error) { | |
print("error \(error)") | |
} | |
} | |
} | |
} | |
} | |
/// Simple fake implementation of Echo_EchoUpdateSession that returns a previously-defined set of results | |
/// and stores sent values for later verification. | |
class Echo_EchoUpdateSessionStub : Echo_EchoSessionStub, Echo_EchoUpdateSession { | |
var inputs: [Echo_EchoRequest] = [] | |
var outputs: [Echo_EchoResponse] = [] | |
func receive() throws -> Echo_EchoRequest { | |
if let input = inputs.first { | |
inputs.removeFirst() | |
return input | |
} else { | |
throw Echo_EchoClientError.endOfStream | |
} | |
} | |
func send(_ response: Echo_EchoResponse, completion: @escaping ()->()) throws { | |
outputs.append(response) | |
} | |
func close() throws { } | |
} | |
/// Main server for generated service | |
public final class Echo_EchoServer { | |
private var address: String | |
private var server: SwiftGRPC.Server | |
private var provider: Echo_EchoProvider? | |
/// Create a server that accepts insecure connections. | |
public init(address:String, | |
provider:Echo_EchoProvider) { | |
SwiftGRPC.initialize() | |
self.address = address | |
self.provider = provider | |
self.server = SwiftGRPC.Server(address:address) | |
} | |
/// Create a server that accepts secure connections. | |
public init?(address:String, | |
certificateURL:URL, | |
keyURL:URL, | |
provider:Echo_EchoProvider) { | |
SwiftGRPC.initialize() | |
self.address = address | |
self.provider = provider | |
guard | |
let certificate = try? String(contentsOf: certificateURL, encoding: .utf8), | |
let key = try? String(contentsOf: keyURL, encoding: .utf8) | |
else { | |
return nil | |
} | |
self.server = SwiftGRPC.Server(address:address, key:key, certs:certificate) | |
} | |
/// Start the server. | |
public func start(queue:DispatchQueue = DispatchQueue.global()) { | |
guard let provider = self.provider else { | |
fatalError() // the server requires a provider | |
} | |
server.run {(handler) in | |
print("Server received request to " + handler.host | |
+ " calling " + handler.method | |
+ " from " + handler.caller | |
+ " with " + String(describing:handler.requestMetadata) ) | |
do { | |
switch handler.method { | |
case "/echo.Echo/Get": | |
try Echo_EchoGetSessionImpl(handler:handler, provider:provider).run(queue:queue) | |
case "/echo.Echo/Expand": | |
try Echo_EchoExpandSessionImpl(handler:handler, provider:provider).run(queue:queue) | |
case "/echo.Echo/Collect": | |
try Echo_EchoCollectSessionImpl(handler:handler, provider:provider).run(queue:queue) | |
case "/echo.Echo/Update": | |
try Echo_EchoUpdateSessionImpl(handler:handler, provider:provider).run(queue:queue) | |
default: | |
// handle unknown requests | |
try handler.receiveMessage(initialMetadata:Metadata()) {(requestData) in | |
try handler.sendResponse(statusCode:.unimplemented, | |
statusMessage:"unknown method " + handler.method, | |
trailingMetadata:Metadata()) | |
} | |
} | |
} catch (let error) { | |
print("Server error: \(error)") | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment