ClientCallUnary.swift 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /*
  2. * Copyright 2018, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Dispatch
  17. import Foundation
  18. import SwiftProtobuf
  19. public protocol ClientCallUnary: class {
  20. static var method: String { get }
  21. /// Cancel the call.
  22. func cancel()
  23. }
  24. open class ClientCallUnaryImpl<InputType: Message, OutputType: Message>: ClientCallUnary {
  25. open class var method: String { fatalError("needs to be overridden") }
  26. private var call: Call
  27. /// Create a call.
  28. public init(_ channel: Channel) {
  29. call = channel.makeCall(type(of: self).method)
  30. }
  31. /// Run the call. Blocks until the reply is received.
  32. /// - Throws: `BinaryEncodingError` if encoding fails. `CallError` if fails to call. `ClientError` if receives no response.
  33. public func run(request: InputType, metadata: Metadata) throws -> OutputType {
  34. let sem = DispatchSemaphore(value: 0)
  35. var returnCallResult: CallResult!
  36. var returnResponse: OutputType?
  37. _ = try start(request: request, metadata: metadata) { response, callResult in
  38. returnResponse = response
  39. returnCallResult = callResult
  40. sem.signal()
  41. }
  42. _ = sem.wait(timeout: DispatchTime.distantFuture)
  43. if let returnResponse = returnResponse {
  44. return returnResponse
  45. } else {
  46. throw ClientError.error(c: returnCallResult)
  47. }
  48. }
  49. /// Start the call. Nonblocking.
  50. /// - Throws: `BinaryEncodingError` if encoding fails. `CallError` if fails to call.
  51. public func start(request: InputType,
  52. metadata: Metadata,
  53. completion: @escaping ((OutputType?, CallResult) -> Void)) throws -> Self {
  54. let requestData = try request.serializedData()
  55. try call.start(.unary, metadata: metadata, message: requestData) { callResult in
  56. if let responseData = callResult.resultData,
  57. let response = try? OutputType(serializedData: responseData) {
  58. completion(response, callResult)
  59. } else {
  60. completion(nil, callResult)
  61. }
  62. }
  63. return self
  64. }
  65. public func cancel() {
  66. call.cancel()
  67. }
  68. }