Generator-Client.swift 13 KB

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