Generator-Client.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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 Foundation
  17. import SwiftProtobuf
  18. import SwiftProtobufPluginLibrary
  19. extension Generator {
  20. internal func printClient() {
  21. for method in service.methods {
  22. self.method = method
  23. switch streamingType(method) {
  24. case .unary:
  25. printServiceClientMethodCallUnary()
  26. case .serverStreaming:
  27. printServiceClientMethodCallServerStreaming()
  28. case .clientStreaming:
  29. printServiceClientMethodCallClientStreaming()
  30. case .bidirectionalStreaming:
  31. printServiceClientMethodCallBidiStreaming()
  32. }
  33. }
  34. println()
  35. printServiceClientProtocol()
  36. println()
  37. printServiceClientImplementation()
  38. if options.generateTestStubs {
  39. println()
  40. printServiceClientTestStubs()
  41. }
  42. }
  43. private func printServiceClientMethodCallUnary() {
  44. println("\(access) protocol \(callName): ClientCallUnary {}")
  45. println()
  46. println("fileprivate final class \(callName)Base: ClientCallUnaryBase<\(methodInputName), \(methodOutputName)>, \(callName) {")
  47. indent()
  48. println("override class var method: String { return \(methodPath) }")
  49. outdent()
  50. println("}")
  51. println()
  52. }
  53. private func printServiceClientMethodCallServerStreaming() {
  54. println("\(access) protocol \(callName): ClientCallServerStreaming {")
  55. indent()
  56. printStreamReceiveMethods(receivedType: methodOutputName)
  57. outdent()
  58. println("}")
  59. println()
  60. println("fileprivate final class \(callName)Base: ClientCallServerStreamingBase<\(methodInputName), \(methodOutputName)>, \(callName) {")
  61. indent()
  62. println("override class var method: String { return \(methodPath) }")
  63. outdent()
  64. println("}")
  65. if options.generateTestStubs {
  66. println()
  67. println("class \(callName)TestStub: ClientCallServerStreamingTestStub<\(methodOutputName)>, \(callName) {")
  68. indent()
  69. println("override class var method: String { return \(methodPath) }")
  70. outdent()
  71. println("}")
  72. }
  73. println()
  74. }
  75. private func printServiceClientMethodCallClientStreaming() {
  76. println("\(options.visibility.sourceSnippet) protocol \(callName): ClientCallClientStreaming {")
  77. indent()
  78. println("/// Call this to send each message in the request stream. Nonblocking.")
  79. println("func send(_ message: \(methodInputName), completion: @escaping (Error?) -> Void) throws")
  80. println()
  81. println("/// Call this to close the connection and wait for a response. Blocking.")
  82. println("func closeAndReceive() throws -> \(methodOutputName)")
  83. println("/// Call this to close the connection and wait for a response. Nonblocking.")
  84. println("func closeAndReceive(completion: @escaping (ResultOrRPCError<\(methodOutputName)>) -> Void) throws")
  85. outdent()
  86. println("}")
  87. println()
  88. println("fileprivate final class \(callName)Base: ClientCallClientStreamingBase<\(methodInputName), \(methodOutputName)>, \(callName) {")
  89. indent()
  90. println("override class var method: String { return \(methodPath) }")
  91. outdent()
  92. println("}")
  93. if options.generateTestStubs {
  94. println()
  95. println("/// Simple fake implementation of \(callName)")
  96. println("/// stores sent values for later verification and finall returns a previously-defined result.")
  97. println("class \(callName)TestStub: ClientCallClientStreamingTestStub<\(methodInputName), \(methodOutputName)>, \(callName) {")
  98. indent()
  99. println("override class var method: String { return \(methodPath) }")
  100. outdent()
  101. println("}")
  102. }
  103. println()
  104. }
  105. private func printServiceClientMethodCallBidiStreaming() {
  106. println("\(access) protocol \(callName): ClientCallBidirectionalStreaming {")
  107. indent()
  108. printStreamReceiveMethods(receivedType: methodOutputName)
  109. println()
  110. println("/// Call this to send each message in the request stream.")
  111. println("func send(_ message: \(methodInputName), completion: @escaping (Error?) -> Void) throws")
  112. println()
  113. println("/// Call this to close the sending connection. Blocking.")
  114. println("func closeSend() throws")
  115. println("/// Call this to close the sending connection. Nonblocking.")
  116. println("func closeSend(completion: (() -> Void)?) throws")
  117. outdent()
  118. println("}")
  119. println()
  120. println("fileprivate final class \(callName)Base: ClientCallBidirectionalStreamingBase<\(methodInputName), \(methodOutputName)>, \(callName) {")
  121. indent()
  122. println("override class var method: String { return \(methodPath) }")
  123. outdent()
  124. println("}")
  125. if options.generateTestStubs {
  126. println()
  127. println("class \(callName)TestStub: ClientCallBidirectionalStreamingTestStub<\(methodInputName), \(methodOutputName)>, \(callName) {")
  128. indent()
  129. println("override class var method: String { return \(methodPath) }")
  130. outdent()
  131. println("}")
  132. }
  133. println()
  134. }
  135. private func printServiceClientProtocol() {
  136. println("/// Instantiate \(serviceClassName)Client, then call methods of this protocol to make API calls.")
  137. println("\(options.visibility.sourceSnippet) protocol \(serviceClassName): ServiceClient {")
  138. indent()
  139. for method in service.methods {
  140. self.method = method
  141. switch streamingType(method) {
  142. case .unary:
  143. println("/// Synchronous. Unary.")
  144. println("func \(methodFunctionName)(_ request: \(methodInputName)) throws -> \(methodOutputName)")
  145. println("/// Asynchronous. Unary.")
  146. println("func \(methodFunctionName)(_ request: \(methodInputName), completion: @escaping (\(methodOutputName)?, CallResult) -> Void) throws -> \(callName)")
  147. case .serverStreaming:
  148. println("/// Asynchronous. Server-streaming.")
  149. println("/// Send the initial message.")
  150. println("/// Use methods on the returned object to get streamed responses.")
  151. println("func \(methodFunctionName)(_ request: \(methodInputName), completion: ((CallResult) -> Void)?) throws -> \(callName)")
  152. case .clientStreaming:
  153. println("/// Asynchronous. Client-streaming.")
  154. println("/// Use methods on the returned object to stream messages and")
  155. println("/// to close the connection and wait for a final response.")
  156. println("func \(methodFunctionName)(completion: ((CallResult) -> Void)?) throws -> \(callName)")
  157. case .bidirectionalStreaming:
  158. println("/// Asynchronous. Bidirectional-streaming.")
  159. println("/// Use methods on the returned object to stream messages,")
  160. println("/// to wait for replies, and to close the connection.")
  161. println("func \(methodFunctionName)(completion: ((CallResult) -> Void)?) throws -> \(callName)")
  162. }
  163. println()
  164. }
  165. outdent()
  166. println("}")
  167. }
  168. private func printServiceClientImplementation() {
  169. println("\(access) final class \(serviceClassName)Client: ServiceClientBase, \(serviceClassName) {")
  170. indent()
  171. for method in service.methods {
  172. self.method = method
  173. switch streamingType(method) {
  174. case .unary:
  175. println("/// Synchronous. Unary.")
  176. println("\(access) func \(methodFunctionName)(_ request: \(methodInputName)) throws -> \(methodOutputName) {")
  177. indent()
  178. println("return try \(callName)Base(channel)")
  179. indent()
  180. println(".run(request: request, metadata: metadata)")
  181. outdent()
  182. outdent()
  183. println("}")
  184. println("/// Asynchronous. Unary.")
  185. println("\(access) func \(methodFunctionName)(_ request: \(methodInputName), completion: @escaping (\(methodOutputName)?, CallResult) -> Void) throws -> \(callName) {")
  186. indent()
  187. println("return try \(callName)Base(channel)")
  188. indent()
  189. println(".start(request: request, metadata: metadata, completion: completion)")
  190. outdent()
  191. outdent()
  192. println("}")
  193. case .serverStreaming:
  194. println("/// Asynchronous. Server-streaming.")
  195. println("/// Send the initial message.")
  196. println("/// Use methods on the returned object to get streamed responses.")
  197. println("\(access) func \(methodFunctionName)(_ request: \(methodInputName), completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  198. indent()
  199. println("return try \(callName)Base(channel)")
  200. indent()
  201. println(".start(request: request, metadata: metadata, completion: completion)")
  202. outdent()
  203. outdent()
  204. println("}")
  205. case .clientStreaming:
  206. println("/// Asynchronous. Client-streaming.")
  207. println("/// Use methods on the returned object to stream messages and")
  208. println("/// to close the connection and wait for a final response.")
  209. println("\(access) func \(methodFunctionName)(completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  210. indent()
  211. println("return try \(callName)Base(channel)")
  212. indent()
  213. println(".start(metadata: metadata, completion: completion)")
  214. outdent()
  215. outdent()
  216. println("}")
  217. case .bidirectionalStreaming:
  218. println("/// Asynchronous. Bidirectional-streaming.")
  219. println("/// Use methods on the returned object to stream messages,")
  220. println("/// to wait for replies, and to close the connection.")
  221. println("\(access) func \(methodFunctionName)(completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  222. indent()
  223. println("return try \(callName)Base(channel)")
  224. indent()
  225. println(".start(metadata: metadata, completion: completion)")
  226. outdent()
  227. outdent()
  228. println("}")
  229. }
  230. println()
  231. }
  232. outdent()
  233. println("}")
  234. }
  235. private func printServiceClientTestStubs() {
  236. println("class \(serviceClassName)TestStub: ServiceClientTestStubBase, \(serviceClassName) {")
  237. indent()
  238. for method in service.methods {
  239. self.method = method
  240. switch streamingType(method) {
  241. case .unary:
  242. println("var \(methodFunctionName)Requests: [\(methodInputName)] = []")
  243. println("var \(methodFunctionName)Responses: [\(methodOutputName)] = []")
  244. println("func \(methodFunctionName)(_ request: \(methodInputName)) throws -> \(methodOutputName) {")
  245. indent()
  246. println("\(methodFunctionName)Requests.append(request)")
  247. println("defer { \(methodFunctionName)Responses.removeFirst() }")
  248. println("return \(methodFunctionName)Responses.first!")
  249. outdent()
  250. println("}")
  251. println("func \(methodFunctionName)(_ request: \(methodInputName), completion: @escaping (\(methodOutputName)?, CallResult) -> Void) throws -> \(callName) {")
  252. indent()
  253. println("fatalError(\"not implemented\")")
  254. outdent()
  255. println("}")
  256. case .serverStreaming:
  257. println("var \(methodFunctionName)Requests: [\(methodInputName)] = []")
  258. println("var \(methodFunctionName)Calls: [\(callName)] = []")
  259. println("func \(methodFunctionName)(_ request: \(methodInputName), completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  260. indent()
  261. println("\(methodFunctionName)Requests.append(request)")
  262. println("defer { \(methodFunctionName)Calls.removeFirst() }")
  263. println("return \(methodFunctionName)Calls.first!")
  264. outdent()
  265. println("}")
  266. case .clientStreaming:
  267. println("var \(methodFunctionName)Calls: [\(callName)] = []")
  268. println("func \(methodFunctionName)(completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  269. indent()
  270. println("defer { \(methodFunctionName)Calls.removeFirst() }")
  271. println("return \(methodFunctionName)Calls.first!")
  272. outdent()
  273. println("}")
  274. case .bidirectionalStreaming:
  275. println("var \(methodFunctionName)Calls: [\(callName)] = []")
  276. println("func \(methodFunctionName)(completion: ((CallResult) -> Void)?) throws -> \(callName) {")
  277. indent()
  278. println("defer { \(methodFunctionName)Calls.removeFirst() }")
  279. println("return \(methodFunctionName)Calls.first!")
  280. outdent()
  281. println("}")
  282. }
  283. println()
  284. }
  285. outdent()
  286. println("}")
  287. }
  288. }