Generator-Client.swift 16 KB

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