StructuredSwift+Server.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*
  2. * Copyright 2024, 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. extension FunctionSignatureDescription {
  17. /// ```
  18. /// func <Method>(
  19. /// request: GRPCCore.ServerRequest<Input>,
  20. /// context: GRPCCore.ServerContext
  21. /// ) async throws -> GRPCCore.ServerResponse<Output>
  22. /// ```
  23. static func serverMethod(
  24. accessLevel: AccessModifier? = nil,
  25. name: String,
  26. input: String,
  27. output: String,
  28. streamingInput: Bool,
  29. streamingOutput: Bool
  30. ) -> Self {
  31. return FunctionSignatureDescription(
  32. accessModifier: accessLevel,
  33. kind: .function(name: name),
  34. parameters: [
  35. ParameterDescription(
  36. label: "request",
  37. type: .serverRequest(forType: input, streaming: streamingInput)
  38. ),
  39. ParameterDescription(label: "context", type: .serverContext),
  40. ],
  41. keywords: [.async, .throws],
  42. returnType: .identifierType(.serverResponse(forType: output, streaming: streamingOutput))
  43. )
  44. }
  45. }
  46. extension ProtocolDescription {
  47. /// ```
  48. /// protocol <Name>: GRPCCore.RegistrableRPCService {
  49. /// ...
  50. /// }
  51. /// ```
  52. static func streamingService(
  53. accessLevel: AccessModifier? = nil,
  54. name: String,
  55. methods: [MethodDescriptor]
  56. ) -> Self {
  57. return ProtocolDescription(
  58. accessModifier: accessLevel,
  59. name: name,
  60. conformances: ["GRPCCore.RegistrableRPCService"],
  61. members: methods.map { method in
  62. .commentable(
  63. .preFormatted(method.documentation),
  64. .function(
  65. signature: .serverMethod(
  66. name: method.name.generatedLowerCase,
  67. input: method.inputType,
  68. output: method.outputType,
  69. streamingInput: true,
  70. streamingOutput: true
  71. )
  72. )
  73. )
  74. }
  75. )
  76. }
  77. }
  78. extension ExtensionDescription {
  79. /// ```
  80. /// extension <ExtensionName> {
  81. /// func registerMethods(with router: inout GRPCCore.RPCRouter) {
  82. /// // ...
  83. /// }
  84. /// }
  85. /// ```
  86. static func registrableRPCServiceDefaultImplementation(
  87. accessLevel: AccessModifier? = nil,
  88. on extensionName: String,
  89. serviceNamespace: String,
  90. methods: [MethodDescriptor],
  91. serializer: (String) -> String,
  92. deserializer: (String) -> String
  93. ) -> Self {
  94. return ExtensionDescription(
  95. onType: extensionName,
  96. declarations: [
  97. .function(
  98. .registerMethods(
  99. accessLevel: accessLevel,
  100. serviceNamespace: serviceNamespace,
  101. methods: methods,
  102. serializer: serializer,
  103. deserializer: deserializer
  104. )
  105. )
  106. ]
  107. )
  108. }
  109. }
  110. extension ProtocolDescription {
  111. /// ```
  112. /// protocol <Name>: <StreamingProtocol> {
  113. /// ...
  114. /// }
  115. /// ```
  116. static func service(
  117. accessLevel: AccessModifier? = nil,
  118. name: String,
  119. streamingProtocol: String,
  120. methods: [MethodDescriptor]
  121. ) -> Self {
  122. return ProtocolDescription(
  123. accessModifier: accessLevel,
  124. name: name,
  125. conformances: [streamingProtocol],
  126. members: methods.map { method in
  127. .commentable(
  128. .preFormatted(method.documentation),
  129. .function(
  130. signature: .serverMethod(
  131. name: method.name.generatedLowerCase,
  132. input: method.inputType,
  133. output: method.outputType,
  134. streamingInput: method.isInputStreaming,
  135. streamingOutput: method.isOutputStreaming
  136. )
  137. )
  138. )
  139. }
  140. )
  141. }
  142. }
  143. extension FunctionCallDescription {
  144. /// ```
  145. /// self.<Name>(request: request, context: context)
  146. /// ```
  147. static func serverMethodCallOnSelf(
  148. name: String,
  149. requestArgument: Expression = .identifierPattern("request")
  150. ) -> Self {
  151. return FunctionCallDescription(
  152. calledExpression: .memberAccess(
  153. MemberAccessDescription(
  154. left: .identifierPattern("self"),
  155. right: name
  156. )
  157. ),
  158. arguments: [
  159. FunctionArgumentDescription(
  160. label: "request",
  161. expression: requestArgument
  162. ),
  163. FunctionArgumentDescription(
  164. label: "context",
  165. expression: .identifierPattern("context")
  166. ),
  167. ]
  168. )
  169. }
  170. }
  171. extension ClosureInvocationDescription {
  172. /// ```
  173. /// { router, context in
  174. /// try await self.<Method>(
  175. /// request: request,
  176. /// context: context
  177. /// )
  178. /// }
  179. /// ```
  180. static func routerHandlerInvokingRPC(method: String) -> Self {
  181. return ClosureInvocationDescription(
  182. argumentNames: ["request", "context"],
  183. body: [
  184. .expression(
  185. .unaryKeyword(
  186. kind: .try,
  187. expression: .unaryKeyword(
  188. kind: .await,
  189. expression: .functionCall(.serverMethodCallOnSelf(name: method))
  190. )
  191. )
  192. )
  193. ]
  194. )
  195. }
  196. }
  197. /// ```
  198. /// router.registerHandler(
  199. /// forMethod: ...,
  200. /// deserializer: ...
  201. /// serializer: ...
  202. /// handler: { request, context in
  203. /// // ...
  204. /// }
  205. /// )
  206. /// ```
  207. extension FunctionCallDescription {
  208. static func registerWithRouter(
  209. serviceNamespace: String,
  210. methodNamespace: String,
  211. methodName: String,
  212. inputDeserializer: String,
  213. outputSerializer: String
  214. ) -> Self {
  215. return FunctionCallDescription(
  216. calledExpression: .memberAccess(
  217. .init(left: .identifierPattern("router"), right: "registerHandler")
  218. ),
  219. arguments: [
  220. FunctionArgumentDescription(
  221. label: "forMethod",
  222. expression: .identifierPattern("\(serviceNamespace).Method.\(methodNamespace).descriptor")
  223. ),
  224. FunctionArgumentDescription(
  225. label: "deserializer",
  226. expression: .identifierPattern(inputDeserializer)
  227. ),
  228. FunctionArgumentDescription(
  229. label: "serializer",
  230. expression: .identifierPattern(outputSerializer)
  231. ),
  232. FunctionArgumentDescription(
  233. label: "handler",
  234. expression: .closureInvocation(.routerHandlerInvokingRPC(method: methodName))
  235. ),
  236. ]
  237. )
  238. }
  239. }
  240. extension FunctionDescription {
  241. /// ```
  242. /// func registerMethods(with router: inout GRPCCore.RPCRouter) {
  243. /// // ...
  244. /// }
  245. /// ```
  246. static func registerMethods(
  247. accessLevel: AccessModifier? = nil,
  248. serviceNamespace: String,
  249. methods: [MethodDescriptor],
  250. serializer: (String) -> String,
  251. deserializer: (String) -> String
  252. ) -> Self {
  253. return FunctionDescription(
  254. accessModifier: accessLevel,
  255. kind: .function(name: "registerMethods"),
  256. parameters: [
  257. ParameterDescription(
  258. label: "with",
  259. name: "router",
  260. type: .rpcRouter,
  261. `inout`: true
  262. )
  263. ],
  264. body: methods.map { method in
  265. .functionCall(
  266. .registerWithRouter(
  267. serviceNamespace: serviceNamespace,
  268. methodNamespace: method.name.generatedUpperCase,
  269. methodName: method.name.generatedLowerCase,
  270. inputDeserializer: deserializer(method.inputType),
  271. outputSerializer: serializer(method.outputType)
  272. )
  273. )
  274. }
  275. )
  276. }
  277. }
  278. extension FunctionDescription {
  279. /// ```
  280. /// func <Name>(
  281. /// request: GRPCCore.StreamingServerRequest<Input>
  282. /// context: GRPCCore.ServerContext
  283. /// ) async throws -> GRPCCore.StreamingServerResponse<Output> {
  284. /// let response = try await self.<Name>(
  285. /// request: GRPCCore.ServerRequest(stream: request),
  286. /// context: context
  287. /// )
  288. /// return GRPCCore.StreamingServerResponse(single: response)
  289. /// }
  290. /// ```
  291. static func serverStreamingMethodsCallingMethod(
  292. accessLevel: AccessModifier? = nil,
  293. name: String,
  294. input: String,
  295. output: String,
  296. streamingInput: Bool,
  297. streamingOutput: Bool
  298. ) -> FunctionDescription {
  299. let signature: FunctionSignatureDescription = .serverMethod(
  300. accessLevel: accessLevel,
  301. name: name,
  302. input: input,
  303. output: output,
  304. // This method converts from the fully streamed version to the specified version.
  305. streamingInput: true,
  306. streamingOutput: true
  307. )
  308. // Call the underlying function.
  309. let functionCall: Expression = .functionCall(
  310. calledExpression: .memberAccess(
  311. MemberAccessDescription(
  312. left: .identifierPattern("self"),
  313. right: name
  314. )
  315. ),
  316. arguments: [
  317. FunctionArgumentDescription(
  318. label: "request",
  319. expression: streamingInput
  320. ? .identifierPattern("request")
  321. : .functionCall(
  322. calledExpression: .identifierType(.serverRequest(forType: nil, streaming: false)),
  323. arguments: [
  324. FunctionArgumentDescription(
  325. label: "stream",
  326. expression: .identifierPattern("request")
  327. )
  328. ]
  329. )
  330. ),
  331. FunctionArgumentDescription(
  332. label: "context",
  333. expression: .identifierPattern("context")
  334. ),
  335. ]
  336. )
  337. // Call the function and assign to 'response'.
  338. let response: Declaration = .variable(
  339. kind: .let,
  340. left: "response",
  341. right: .unaryKeyword(
  342. kind: .try,
  343. expression: .unaryKeyword(
  344. kind: .await,
  345. expression: functionCall
  346. )
  347. )
  348. )
  349. // Build the return statement.
  350. let returnExpression: Expression = .unaryKeyword(
  351. kind: .return,
  352. expression: streamingOutput
  353. ? .identifierPattern("response")
  354. : .functionCall(
  355. calledExpression: .identifierType(.serverResponse(forType: nil, streaming: true)),
  356. arguments: [
  357. FunctionArgumentDescription(
  358. label: "single",
  359. expression: .identifierPattern("response")
  360. )
  361. ]
  362. )
  363. )
  364. return Self(
  365. signature: signature,
  366. body: [.declaration(response), .expression(returnExpression)]
  367. )
  368. }
  369. }
  370. extension ExtensionDescription {
  371. /// ```
  372. /// extension <ExtensionName> {
  373. /// func <Name>(
  374. /// request: GRPCCore.StreamingServerRequest<Input>
  375. /// context: GRPCCore.ServerContext
  376. /// ) async throws -> GRPCCore.StreamingServerResponse<Output> {
  377. /// let response = try await self.<Name>(
  378. /// request: GRPCCore.ServerRequest(stream: request),
  379. /// context: context
  380. /// )
  381. /// return GRPCCore.StreamingServerResponse(single: response)
  382. /// }
  383. /// ...
  384. /// }
  385. /// ```
  386. static func streamingServiceProtocolDefaultImplementation(
  387. accessModifier: AccessModifier? = nil,
  388. on extensionName: String,
  389. methods: [MethodDescriptor]
  390. ) -> Self {
  391. return ExtensionDescription(
  392. onType: extensionName,
  393. declarations: methods.compactMap { method -> Declaration? in
  394. // Bidirectional streaming methods don't need a default implementation as their signatures
  395. // match across the two protocols.
  396. if method.isInputStreaming, method.isOutputStreaming { return nil }
  397. return .function(
  398. .serverStreamingMethodsCallingMethod(
  399. accessLevel: accessModifier,
  400. name: method.name.generatedLowerCase,
  401. input: method.inputType,
  402. output: method.outputType,
  403. streamingInput: method.isInputStreaming,
  404. streamingOutput: method.isOutputStreaming
  405. )
  406. )
  407. }
  408. )
  409. }
  410. }