ServerCodeTranslator.swift 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Copyright 2023, 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. /// Creates a representation for the server code that will be generated based on the ``CodeGenerationRequest`` object
  17. /// specifications, using types from ``StructuredSwiftRepresentation``.
  18. ///
  19. /// For example, in the case of a service called "Bar", in the "foo" namespace which has
  20. /// one method "baz" with input type "Input" and output type "Output", the ``ServerCodeTranslator`` will create
  21. /// a representation for the following generated code:
  22. ///
  23. /// ```swift
  24. /// @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  25. /// public protocol Foo_BarStreamingServiceProtocol: GRPCCore.RegistrableRPCService {
  26. /// func baz(
  27. /// request: GRPCCore.StreamingServerRequest<Foo_Bar_Input>
  28. /// ) async throws -> GRPCCore.StreamingServerResponse<Foo_Bar_Output>
  29. /// }
  30. /// // Conformance to `GRPCCore.RegistrableRPCService`.
  31. /// @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  32. /// extension Foo_Bar.StreamingServiceProtocol {
  33. /// public func registerMethods(with router: inout GRPCCore.RPCRouter) {
  34. /// router.registerHandler(
  35. /// forMethod: Foo_Bar.Method.baz.descriptor,
  36. /// deserializer: GRPCProtobuf.ProtobufDeserializer<Foo_Bar_Input>(),
  37. /// serializer: GRPCProtobuf.ProtobufSerializer<Foo_Bar_Output>(),
  38. /// handler: { request in try await self.baz(request: request) }
  39. /// )
  40. /// }
  41. /// }
  42. /// @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  43. /// public protocol Foo_BarServiceProtocol: Foo_Bar.StreamingServiceProtocol {
  44. /// func baz(
  45. /// request: GRPCCore.ServerRequest<Foo_Bar_Input>
  46. /// ) async throws -> GRPCCore.ServerResponse<Foo_Bar_Output>
  47. /// }
  48. /// // Partial conformance to `Foo_BarStreamingServiceProtocol`.
  49. /// @available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
  50. /// extension Foo_Bar.ServiceProtocol {
  51. /// public func baz(
  52. /// request: GRPCCore.StreamingServerRequest<Foo_Bar_Input>
  53. /// ) async throws -> GRPCCore.StreamingServerResponse<Foo_Bar_Output> {
  54. /// let response = try await self.baz(request: GRPCCore.ServerRequest(stream: request))
  55. /// return GRPCCore.StreamingServerResponse(single: response)
  56. /// }
  57. /// }
  58. ///```
  59. @available(gRPCSwift 2.0, *)
  60. struct ServerCodeTranslator {
  61. init() {}
  62. func translate(
  63. accessModifier: AccessModifier,
  64. service: ServiceDescriptor,
  65. availability: AvailabilityDescription,
  66. namer: Namer = Namer(),
  67. serializer: (String) -> String,
  68. deserializer: (String) -> String
  69. ) -> [CodeBlock] {
  70. var blocks = [CodeBlock]()
  71. let `extension` = ExtensionDescription(
  72. onType: service.name.typeName,
  73. declarations: [
  74. // protocol StreamingServiceProtocol { ... }
  75. .commentable(
  76. .preFormatted(
  77. Docs.suffix(
  78. self.streamingServiceDocs(serviceName: service.name.identifyingName),
  79. withDocs: service.documentation
  80. )
  81. ),
  82. .protocol(
  83. .streamingService(
  84. accessLevel: accessModifier,
  85. name: "StreamingServiceProtocol",
  86. methods: service.methods,
  87. namer: namer
  88. )
  89. )
  90. ),
  91. // protocol ServiceProtocol { ... }
  92. .commentable(
  93. .preFormatted(
  94. Docs.suffix(
  95. self.serviceDocs(serviceName: service.name.identifyingName),
  96. withDocs: service.documentation
  97. )
  98. ),
  99. .protocol(
  100. .service(
  101. accessLevel: accessModifier,
  102. name: "ServiceProtocol",
  103. streamingProtocol: "\(service.name.typeName).StreamingServiceProtocol",
  104. methods: service.methods,
  105. namer: namer
  106. )
  107. )
  108. ),
  109. // protocol SimpleServiceProtocol { ... }
  110. .commentable(
  111. .preFormatted(
  112. Docs.suffix(
  113. self.simpleServiceDocs(serviceName: service.name.identifyingName),
  114. withDocs: service.documentation
  115. )
  116. ),
  117. .protocol(
  118. .simpleServiceProtocol(
  119. accessModifier: accessModifier,
  120. name: "SimpleServiceProtocol",
  121. serviceProtocol: "\(service.name.typeName).ServiceProtocol",
  122. methods: service.methods,
  123. namer: namer
  124. )
  125. )
  126. ),
  127. ]
  128. )
  129. blocks.append(.declaration(.guarded(availability, .extension(`extension`))))
  130. // extension <Service>.StreamingServiceProtocol> { ... }
  131. let registerExtension: ExtensionDescription = .registrableRPCServiceDefaultImplementation(
  132. accessLevel: accessModifier,
  133. on: "\(service.name.typeName).StreamingServiceProtocol",
  134. serviceNamespace: service.name.typeName,
  135. methods: service.methods,
  136. namer: namer,
  137. serializer: serializer,
  138. deserializer: deserializer
  139. )
  140. blocks.append(
  141. CodeBlock(
  142. comment: .inline("Default implementation of 'registerMethods(with:)'."),
  143. item: .declaration(.guarded(availability, .extension(registerExtension)))
  144. )
  145. )
  146. // extension <Service>_ServiceProtocol { ... }
  147. let streamingServiceDefaultImplExtension: ExtensionDescription =
  148. .streamingServiceProtocolDefaultImplementation(
  149. accessModifier: accessModifier,
  150. on: "\(service.name.typeName).ServiceProtocol",
  151. methods: service.methods,
  152. namer: namer
  153. )
  154. blocks.append(
  155. CodeBlock(
  156. comment: .inline(
  157. "Default implementation of streaming methods from 'StreamingServiceProtocol'."
  158. ),
  159. item: .declaration(.guarded(availability, .extension(streamingServiceDefaultImplExtension)))
  160. )
  161. )
  162. // extension <Service>_SimpleServiceProtocol { ... }
  163. let serviceDefaultImplExtension: ExtensionDescription = .serviceProtocolDefaultImplementation(
  164. accessModifier: accessModifier,
  165. on: "\(service.name.typeName).SimpleServiceProtocol",
  166. methods: service.methods,
  167. namer: namer
  168. )
  169. blocks.append(
  170. CodeBlock(
  171. comment: .inline("Default implementation of methods from 'ServiceProtocol'."),
  172. item: .declaration(.guarded(availability, .extension(serviceDefaultImplExtension)))
  173. )
  174. )
  175. return blocks
  176. }
  177. private func streamingServiceDocs(serviceName: String) -> String {
  178. return """
  179. /// Streaming variant of the service protocol for the "\(serviceName)" service.
  180. ///
  181. /// This protocol is the lowest-level of the service protocols generated for this service
  182. /// giving you the most flexibility over the implementation of your service. This comes at
  183. /// the cost of more verbose and less strict APIs. Each RPC requires you to implement it in
  184. /// terms of a request stream and response stream. Where only a single request or response
  185. /// message is expected, you are responsible for enforcing this invariant is maintained.
  186. ///
  187. /// Where possible, prefer using the stricter, less-verbose ``ServiceProtocol``
  188. /// or ``SimpleServiceProtocol`` instead.
  189. """
  190. }
  191. private func serviceDocs(serviceName: String) -> String {
  192. return """
  193. /// Service protocol for the "\(serviceName)" service.
  194. ///
  195. /// This protocol is higher level than ``StreamingServiceProtocol`` but lower level than
  196. /// the ``SimpleServiceProtocol``, it provides access to request and response metadata and
  197. /// trailing response metadata. If you don't need these then consider using
  198. /// the ``SimpleServiceProtocol``. If you need fine grained control over your RPCs then
  199. /// use ``StreamingServiceProtocol``.
  200. """
  201. }
  202. private func simpleServiceDocs(serviceName: String) -> String {
  203. return """
  204. /// Simple service protocol for the "\(serviceName)" service.
  205. ///
  206. /// This is the highest level protocol for the service. The API is the easiest to use but
  207. /// doesn't provide access to request or response metadata. If you need access to these
  208. /// then use ``ServiceProtocol`` instead.
  209. """
  210. }
  211. }