StructuredSwift+Server.swift 12 KB

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