Generator-Server+AsyncAwait.swift 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright 2021, 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 SwiftProtobuf
  17. import SwiftProtobufPluginLibrary
  18. // MARK: - Protocol
  19. extension Generator {
  20. internal func printServerProtocolAsyncAwait() {
  21. let sourceComments = self.service.protoSourceComments()
  22. if !sourceComments.isEmpty {
  23. // Source comments already have the leading '///'
  24. self.println(sourceComments, newline: false)
  25. self.println("///")
  26. }
  27. self.println("/// To implement a server, implement an object which conforms to this protocol.")
  28. self.printAvailabilityForAsyncAwait()
  29. self.withIndentation(
  30. "\(self.access) protocol \(self.asyncProviderName): CallHandlerProvider",
  31. braces: .curly
  32. ) {
  33. self.println("static var serviceDescriptor: GRPCServiceDescriptor { get }")
  34. self.println("var interceptors: \(self.serverInterceptorProtocolName)? { get }")
  35. for method in service.methods {
  36. self.method = method
  37. self.println()
  38. self.printRPCProtocolRequirement()
  39. }
  40. }
  41. }
  42. private func printRPCProtocolRequirement() {
  43. // Print any comments; skip the newline as source comments include them already.
  44. self.println(self.method.protoSourceComments(), newline: false)
  45. let arguments: [String]
  46. let returnType: String?
  47. switch streamingType(self.method) {
  48. case .unary:
  49. arguments = [
  50. "request: \(self.methodInputName)",
  51. "context: \(Types.serverContext)",
  52. ]
  53. returnType = self.methodOutputName
  54. case .clientStreaming:
  55. arguments = [
  56. "requestStream: \(Types.requestStream(of: self.methodInputName))",
  57. "context: \(Types.serverContext)",
  58. ]
  59. returnType = self.methodOutputName
  60. case .serverStreaming:
  61. arguments = [
  62. "request: \(self.methodInputName)",
  63. "responseStream: \(Types.responseStreamWriter(of: self.methodOutputName))",
  64. "context: \(Types.serverContext)",
  65. ]
  66. returnType = nil
  67. case .bidirectionalStreaming:
  68. arguments = [
  69. "requestStream: \(Types.requestStream(of: self.methodInputName))",
  70. "responseStream: \(Types.responseStreamWriter(of: self.methodOutputName))",
  71. "context: \(Types.serverContext)",
  72. ]
  73. returnType = nil
  74. }
  75. self.printFunction(
  76. name: self.methodFunctionName,
  77. arguments: arguments,
  78. returnType: returnType,
  79. sendable: true,
  80. async: true,
  81. throws: true,
  82. bodyBuilder: nil
  83. )
  84. }
  85. }
  86. // MARK: - Protocol Extension; RPC handling
  87. extension Generator {
  88. internal func printServerProtocolExtensionAsyncAwait() {
  89. // Default extension to provide the service name and routing for methods.
  90. self.printAvailabilityForAsyncAwait()
  91. self.withIndentation("extension \(self.asyncProviderName)", braces: .curly) {
  92. self.withIndentation(
  93. "\(self.access) static var serviceDescriptor: GRPCServiceDescriptor",
  94. braces: .curly
  95. ) {
  96. self.println("return \(self.serviceServerMetadata).serviceDescriptor")
  97. }
  98. self.println()
  99. // This fulfils a requirement from 'CallHandlerProvider'
  100. self.withIndentation("\(self.access) var serviceName: Substring", braces: .curly) {
  101. /// This API returns a Substring (hence the '[...]')
  102. self.println("return \(self.serviceServerMetadata).serviceDescriptor.fullName[...]")
  103. }
  104. self.println()
  105. // Default nil interceptor factory.
  106. self.withIndentation(
  107. "\(self.access) var interceptors: \(self.serverInterceptorProtocolName)?",
  108. braces: .curly
  109. ) {
  110. self.println("return nil")
  111. }
  112. self.println()
  113. self.printFunction(
  114. name: "handle",
  115. arguments: [
  116. "method name: Substring",
  117. "context: CallHandlerContext",
  118. ],
  119. returnType: "GRPCServerHandlerProtocol?",
  120. access: self.access
  121. ) {
  122. self.println("switch name {")
  123. for method in self.service.methods {
  124. self.method = method
  125. let requestType = self.methodInputName
  126. let responseType = self.methodOutputName
  127. let interceptorFactory = self.methodInterceptorFactoryName
  128. let functionName = self.methodFunctionName
  129. self.withIndentation("case \"\(self.method.name)\":", braces: .none) {
  130. self.withIndentation("return \(Types.serverHandler)", braces: .round) {
  131. self.println("context: context,")
  132. self.println("requestDeserializer: \(Types.deserializer(for: requestType))(),")
  133. self.println("responseSerializer: \(Types.serializer(for: responseType))(),")
  134. self.println("interceptors: self.interceptors?.\(interceptorFactory)() ?? [],")
  135. switch streamingType(self.method) {
  136. case .unary:
  137. self.println("wrapping: self.\(functionName)(request:context:)")
  138. case .clientStreaming:
  139. self.println("wrapping: self.\(functionName)(requestStream:context:)")
  140. case .serverStreaming:
  141. self.println("wrapping: self.\(functionName)(request:responseStream:context:)")
  142. case .bidirectionalStreaming:
  143. self.println(
  144. "wrapping: self.\(functionName)(requestStream:responseStream:context:)"
  145. )
  146. }
  147. }
  148. }
  149. }
  150. // Default case.
  151. self.println("default:")
  152. self.withIndentation {
  153. self.println("return nil")
  154. }
  155. self.println("}") // switch
  156. }
  157. }
  158. }
  159. }