grpc_webnext_client/
typed.rs1use futures::stream::{Stream, StreamExt};
9use prost::Message;
10
11use crate::client::{CallOptions, Client, UnaryResponse};
12use crate::metadata::Metadata;
13use crate::status::{Code, Status};
14
15#[derive(Debug, Clone)]
17pub struct TypedResponse<M> {
18 pub message: M,
19 pub headers: Metadata,
20 pub trailers: Metadata,
21}
22
23impl<M> TypedResponse<M> {
24 pub fn into_inner(self) -> M {
26 self.message
27 }
28}
29
30pub trait TypedClient {
32 fn unary_typed<Req, Res>(
34 &self,
35 path: &str,
36 request: Req,
37 options: CallOptions,
38 ) -> impl std::future::Future<Output = Result<TypedResponse<Res>, Status>>
39 where
40 Req: Message,
41 Res: Message + Default;
42
43 fn client_streaming_typed<Req, Res, S>(
45 &self,
46 path: &str,
47 requests: S,
48 options: CallOptions,
49 ) -> impl std::future::Future<Output = Result<TypedResponse<Res>, Status>>
50 where
51 Req: Message + 'static,
52 Res: Message + Default,
53 S: Stream<Item = Req> + 'static;
54}
55
56impl TypedClient for Client {
57 async fn unary_typed<Req, Res>(
58 &self,
59 path: &str,
60 request: Req,
61 options: CallOptions,
62 ) -> Result<TypedResponse<Res>, Status>
63 where
64 Req: Message,
65 Res: Message + Default,
66 {
67 let response = self.unary(path, request.encode_to_vec(), options).await?;
68 decode(response)
69 }
70
71 async fn client_streaming_typed<Req, Res, S>(
72 &self,
73 path: &str,
74 requests: S,
75 options: CallOptions,
76 ) -> Result<TypedResponse<Res>, Status>
77 where
78 Req: Message + 'static,
79 Res: Message + Default,
80 S: Stream<Item = Req> + 'static,
81 {
82 let response = self
83 .client_streaming(path, requests.map(|m| m.encode_to_vec()), options)
84 .await?;
85 decode(response)
86 }
87}
88
89fn decode<Res: Message + Default>(response: UnaryResponse) -> Result<TypedResponse<Res>, Status> {
90 let message = Res::decode(response.message.as_slice()).map_err(|e| {
91 Status::new(Code::Internal, format!("failed to decode response message: {e}"))
92 })?;
93 Ok(TypedResponse { message, headers: response.headers, trailers: response.trailers })
94}