Generator-Server.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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 printServer() {
  21. printServerProtocol()
  22. guard !options.generateNIOImplementation
  23. else { return }
  24. for method in service.methods {
  25. self.method = method
  26. switch streamingType(method) {
  27. case .unary:
  28. printServerMethodUnary()
  29. case .clientStreaming:
  30. printServerMethodClientStreaming()
  31. case .serverStreaming:
  32. printServerMethodServerStreaming()
  33. case .bidirectionalStreaming:
  34. printServerMethodBidirectional()
  35. }
  36. println()
  37. }
  38. }
  39. private func printServerProtocol() {
  40. println("/// To build a server, implement a class that conforms to this protocol.")
  41. if !options.generateNIOImplementation {
  42. println("/// If one of the methods returning `ServerStatus?` returns nil,")
  43. println("/// it is expected that you have already returned a status to the client by means of `session.close`.")
  44. }
  45. println("\(access) protocol \(providerName): \(options.generateNIOImplementation ? "CallHandlerProvider" : "ServiceProvider") {")
  46. indent()
  47. for method in service.methods {
  48. self.method = method
  49. if options.generateNIOImplementation {
  50. switch streamingType(method) {
  51. case .unary:
  52. println("func \(methodFunctionName)(request: \(methodInputName), context: StatusOnlyCallContext) -> EventLoopFuture<\(methodOutputName)>")
  53. case .serverStreaming:
  54. println("func \(methodFunctionName)(request: \(methodInputName), context: StreamingResponseCallContext<\(methodOutputName)>) -> EventLoopFuture<GRPCStatus>")
  55. case .clientStreaming:
  56. println("func \(methodFunctionName)(context: UnaryResponseCallContext<\(methodOutputName)>) -> EventLoopFuture<(StreamEvent<\(methodInputName)>) -> Void>")
  57. case .bidirectionalStreaming:
  58. println("func \(methodFunctionName)(context: StreamingResponseCallContext<\(methodOutputName)>) -> EventLoopFuture<(StreamEvent<\(methodInputName)>) -> Void>")
  59. }
  60. } else {
  61. switch streamingType(method) {
  62. case .unary:
  63. println("func \(methodFunctionName)(request: \(methodInputName), session: \(methodSessionName)) throws -> \(methodOutputName)")
  64. case .serverStreaming:
  65. println("func \(methodFunctionName)(request: \(methodInputName), session: \(methodSessionName)) throws -> ServerStatus?")
  66. case .clientStreaming:
  67. println("func \(methodFunctionName)(session: \(methodSessionName)) throws -> \(methodOutputName)?")
  68. case .bidirectionalStreaming:
  69. println("func \(methodFunctionName)(session: \(methodSessionName)) throws -> ServerStatus?")
  70. }
  71. }
  72. }
  73. outdent()
  74. println("}")
  75. println()
  76. println("extension \(providerName) {")
  77. indent()
  78. println("\(access) var serviceName: String { return \"\(servicePath)\" }")
  79. println()
  80. if options.generateNIOImplementation {
  81. println("/// Determines, calls and returns the appropriate request handler, depending on the request's method.")
  82. println("/// Returns nil for methods not handled by this service.")
  83. println("\(access) func handleMethod(_ methodName: String, request: HTTPRequestHead, serverHandler: GRPCChannelHandler, channel: Channel, errorDelegate: ServerErrorDelegate?) -> GRPCCallHandler? {")
  84. indent()
  85. println("switch methodName {")
  86. for method in service.methods {
  87. self.method = method
  88. println("case \"\(method.name)\":")
  89. indent()
  90. let callHandlerType: String
  91. switch streamingType(method) {
  92. case .unary: callHandlerType = "UnaryCallHandler"
  93. case .serverStreaming: callHandlerType = "ServerStreamingCallHandler"
  94. case .clientStreaming: callHandlerType = "ClientStreamingCallHandler"
  95. case .bidirectionalStreaming: callHandlerType = "BidirectionalStreamingCallHandler"
  96. }
  97. println("return \(callHandlerType)(channel: channel, request: request, errorDelegate: errorDelegate) { context in")
  98. indent()
  99. switch streamingType(method) {
  100. case .unary, .serverStreaming:
  101. println("return { request in")
  102. indent()
  103. println("self.\(methodFunctionName)(request: request, context: context)")
  104. outdent()
  105. println("}")
  106. case .clientStreaming, .bidirectionalStreaming:
  107. println("return self.\(methodFunctionName)(context: context)")
  108. }
  109. outdent()
  110. println("}")
  111. outdent()
  112. println()
  113. }
  114. println("default: return nil")
  115. println("}")
  116. outdent()
  117. println("}")
  118. } else {
  119. println("/// Determines and calls the appropriate request handler, depending on the request's method.")
  120. println("/// Throws `HandleMethodError.unknownMethod` for methods not handled by this service.")
  121. println("\(access) func handleMethod(_ method: String, handler: Handler) throws -> ServerStatus? {")
  122. indent()
  123. println("switch method {")
  124. for method in service.methods {
  125. self.method = method
  126. println("case \(methodPath):")
  127. indent()
  128. switch streamingType(method) {
  129. case .unary, .serverStreaming:
  130. println("return try \(methodSessionName)Base(")
  131. indent()
  132. println("handler: handler,")
  133. println("providerBlock: { try self.\(methodFunctionName)(request: $0, session: $1 as! \(methodSessionName)Base) })")
  134. indent()
  135. println(".run()")
  136. outdent()
  137. outdent()
  138. default:
  139. println("return try \(methodSessionName)Base(")
  140. indent()
  141. println("handler: handler,")
  142. println("providerBlock: { try self.\(methodFunctionName)(session: $0 as! \(methodSessionName)Base) })")
  143. indent()
  144. println(".run()")
  145. outdent()
  146. outdent()
  147. }
  148. outdent()
  149. }
  150. println("default:")
  151. indent()
  152. println("throw HandleMethodError.unknownMethod")
  153. outdent()
  154. println("}")
  155. outdent()
  156. println("}")
  157. }
  158. outdent()
  159. println("}")
  160. println()
  161. }
  162. private func printServerMethodUnary() {
  163. println("\(access) protocol \(methodSessionName): ServerSessionUnary {}")
  164. println()
  165. println("fileprivate final class \(methodSessionName)Base: ServerSessionUnaryBase<\(methodInputName), \(methodOutputName)>, \(methodSessionName) {}")
  166. if options.generateTestStubs {
  167. println()
  168. println("class \(methodSessionName)TestStub: ServerSessionUnaryTestStub, \(methodSessionName) {}")
  169. }
  170. }
  171. private func printServerMethodSendAndClose(sentType: String) {
  172. println("/// Exactly one of these two methods should be called if and only if your request handler returns nil;")
  173. println("/// otherwise SwiftGRPC will take care of sending the response and status for you.")
  174. println("/// Close the connection and send a single result. Non-blocking.")
  175. println("func sendAndClose(response: \(sentType), status: ServerStatus, completion: (() -> Void)?) throws")
  176. println("/// Close the connection and send an error. Non-blocking.")
  177. println("/// Use this method if you encountered an error that makes it impossible to send a response.")
  178. println("/// Accordingly, it does not make sense to call this method with a status of `.ok`.")
  179. println("func sendErrorAndClose(status: ServerStatus, completion: (() -> Void)?) throws")
  180. }
  181. private func printServerMethodClientStreaming() {
  182. println("\(access) protocol \(methodSessionName): ServerSessionClientStreaming {")
  183. indent()
  184. printStreamReceiveMethods(receivedType: methodInputName)
  185. println()
  186. printServerMethodSendAndClose(sentType: methodOutputName)
  187. outdent()
  188. println("}")
  189. println()
  190. printStreamReceiveExtension(extendedType: methodSessionName, receivedType: methodInputName)
  191. println()
  192. println("fileprivate final class \(methodSessionName)Base: ServerSessionClientStreamingBase<\(methodInputName), \(methodOutputName)>, \(methodSessionName) {}")
  193. if options.generateTestStubs {
  194. println()
  195. println("class \(methodSessionName)TestStub: ServerSessionClientStreamingTestStub<\(methodInputName), \(methodOutputName)>, \(methodSessionName) {}")
  196. }
  197. }
  198. private func printServerMethodClose() {
  199. println("/// Close the connection and send the status. Non-blocking.")
  200. println("/// This method should be called if and only if your request handler returns a nil value instead of a server status;")
  201. println("/// otherwise SwiftGRPC will take care of sending the status for you.")
  202. println("func close(withStatus status: ServerStatus, completion: (() -> Void)?) throws")
  203. }
  204. private func printServerMethodServerStreaming() {
  205. println("\(access) protocol \(methodSessionName): ServerSessionServerStreaming {")
  206. indent()
  207. printStreamSendMethods(sentType: methodOutputName)
  208. println()
  209. printServerMethodClose()
  210. outdent()
  211. println("}")
  212. println()
  213. printStreamSendExtension(extendedType: methodSessionName, sentType: methodOutputName)
  214. println()
  215. println("fileprivate final class \(methodSessionName)Base: ServerSessionServerStreamingBase<\(methodInputName), \(methodOutputName)>, \(methodSessionName) {}")
  216. if options.generateTestStubs {
  217. println()
  218. println("class \(methodSessionName)TestStub: ServerSessionServerStreamingTestStub<\(methodOutputName)>, \(methodSessionName) {}")
  219. }
  220. }
  221. private func printServerMethodBidirectional() {
  222. println("\(access) protocol \(methodSessionName): ServerSessionBidirectionalStreaming {")
  223. indent()
  224. printStreamReceiveMethods(receivedType: methodInputName)
  225. println()
  226. printStreamSendMethods(sentType: methodOutputName)
  227. println()
  228. printServerMethodClose()
  229. outdent()
  230. println("}")
  231. println()
  232. printStreamReceiveExtension(extendedType: methodSessionName, receivedType: methodInputName)
  233. println()
  234. printStreamSendExtension(extendedType: methodSessionName, sentType: methodOutputName)
  235. println()
  236. println("fileprivate final class \(methodSessionName)Base: ServerSessionBidirectionalStreamingBase<\(methodInputName), \(methodOutputName)>, \(methodSessionName) {}")
  237. if options.generateTestStubs {
  238. println()
  239. println("class \(methodSessionName)TestStub: ServerSessionBidirectionalStreamingTestStub<\(methodInputName), \(methodOutputName)>, \(methodSessionName) {}")
  240. }
  241. }
  242. }