1use std::{collections::BTreeSet, future::Future, marker::PhantomData};
3
4use prost::Message;
5
6use super::MethodDescriptor;
7
8pub trait Rpc {
9 type Request: Message;
10 type Response: Message + Default;
11 const METHOD: &'static MethodDescriptor;
12}
13pub trait UnaryRpc: Rpc {}
14pub trait ServerStreamingRpc: Rpc {}
15pub trait ClientStreamingRpc: Rpc {}
16pub trait BidirectionalRpc: Rpc {}
17
18pub trait MessageReader: Send {
21 type Error: std::error::Error + Send + Sync + 'static;
22 fn next(&mut self) -> impl Future<Output = Result<Option<Vec<u8>>, Self::Error>> + Send;
23 fn cancel(&mut self);
25}
26
27pub trait MessageWriter: Send {
28 type Error: std::error::Error + Send + Sync + 'static;
29 fn send(&mut self, message: Vec<u8>) -> impl Future<Output = Result<(), Self::Error>> + Send;
30 fn finish(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send;
31 fn abort(&mut self);
32}
33
34pub trait RpcTransport: Send + Sync {
38 type Error: std::error::Error + Send + Sync + 'static;
39 type Reader: MessageReader<Error = Self::Error>;
40 type Writer: MessageWriter<Error = Self::Error>;
41 fn unary(
42 &self,
43 method: &'static MethodDescriptor,
44 request: Vec<u8>,
45 ) -> impl Future<Output = Result<Vec<u8>, Self::Error>> + Send;
46 fn observe(
47 &self,
48 method: &'static MethodDescriptor,
49 request: Vec<u8>,
50 ) -> impl Future<Output = Result<Self::Reader, Self::Error>> + Send;
51 fn exchange(
52 &self,
53 method: &'static MethodDescriptor,
54 opening: Vec<u8>,
55 ) -> impl Future<Output = Result<(Self::Writer, Self::Reader), Self::Error>> + Send;
56}
57
58#[derive(Debug, thiserror::Error)]
59pub enum ClientError<E: std::error::Error> {
60 #[error("endpoint does not implement {0}")]
61 NotImplemented(&'static str),
62 #[error("{0} requires a stable client operation ID")]
63 MissingOperationId(&'static str),
64 #[error("invalid request metadata: {0}")]
65 Metadata(#[from] crate::RequestMetadataError),
66 #[error("transport failure: {0}")]
67 Transport(E),
68 #[error("invalid protobuf response: {0}")]
69 Decode(#[from] prost::DecodeError),
70}
71
72pub struct Client<T> {
73 transport: T,
74 implemented: BTreeSet<String>,
75}
76
77impl<T: RpcTransport> Client<T> {
78 pub fn new(transport: T, implemented: impl IntoIterator<Item = String>) -> Self {
81 Self {
82 transport,
83 implemented: implemented.into_iter().collect(),
84 }
85 }
86
87 fn encode<M: Rpc>(&self, request: &M::Request) -> Result<Vec<u8>, ClientError<T::Error>> {
88 let method = M::METHOD;
89 if !self.implemented.contains(method.path) {
90 return Err(ClientError::NotImplemented(method.path));
91 }
92 let bytes = request.encode_to_vec();
93 if method.client_operation_id_required {
94 let Some(field) = method.client_operation_id_field_number else {
95 return Err(ClientError::MissingOperationId(method.path));
96 };
97 let id = crate::transport::protobuf_string_field(&bytes, field)?;
98 if id.is_none_or(|value| value.trim().is_empty()) {
99 return Err(ClientError::MissingOperationId(method.path));
100 }
101 }
102 Ok(bytes)
103 }
104
105 pub async fn call<M: UnaryRpc>(
106 &self,
107 request: &M::Request,
108 ) -> Result<M::Response, ClientError<T::Error>> {
109 let bytes = self
110 .transport
111 .unary(M::METHOD, self.encode::<M>(request)?)
112 .await
113 .map_err(ClientError::Transport)?;
114 Ok(M::Response::decode(bytes.as_slice())?)
115 }
116
117 pub async fn observe<M: ServerStreamingRpc>(
118 &self,
119 request: &M::Request,
120 ) -> Result<Messages<T::Reader, M::Response>, ClientError<T::Error>> {
121 let reader = self
122 .transport
123 .observe(M::METHOD, self.encode::<M>(request)?)
124 .await
125 .map_err(ClientError::Transport)?;
126 Ok(Messages {
127 reader,
128 done: false,
129 message: PhantomData,
130 })
131 }
132
133 pub async fn exchange<M: BidirectionalRpc>(
135 &self,
136 opening: &M::Request,
137 ) -> Result<
138 (
139 Sender<T::Writer, M::Request>,
140 Messages<T::Reader, M::Response>,
141 ),
142 ClientError<T::Error>,
143 > {
144 let (writer, reader) = self
145 .transport
146 .exchange(M::METHOD, self.encode::<M>(opening)?)
147 .await
148 .map_err(ClientError::Transport)?;
149 Ok((
150 Sender {
151 writer,
152 finished: false,
153 message: PhantomData,
154 },
155 Messages {
156 reader,
157 done: false,
158 message: PhantomData,
159 },
160 ))
161 }
162}
163
164pub struct Messages<R: MessageReader, O> {
165 reader: R,
166 done: bool,
167 message: PhantomData<O>,
168}
169
170impl<R: MessageReader, O> Messages<R, O> {
171 pub fn cancel(&mut self) {
174 if !self.done {
175 self.reader.cancel();
176 self.done = true;
177 }
178 }
179}
180
181impl<R: MessageReader, O: Message + Default> Messages<R, O> {
182 pub async fn next(&mut self) -> Result<Option<O>, ClientError<R::Error>> {
183 if self.done {
184 return Ok(None);
185 }
186 let decoded = match self.reader.next().await {
187 Ok(Some(bytes)) => O::decode(bytes.as_slice())
188 .map(Some)
189 .map_err(ClientError::Decode),
190 Ok(None) => {
191 self.done = true;
192 Ok(None)
193 }
194 Err(error) => Err(ClientError::Transport(error)),
195 };
196 if decoded.is_err() {
197 self.reader.cancel();
198 self.done = true;
199 }
200 decoded
201 }
202}
203
204impl<R: MessageReader, O> Drop for Messages<R, O> {
205 fn drop(&mut self) {
206 self.cancel();
207 }
208}
209
210pub struct Sender<W: MessageWriter, I> {
211 writer: W,
212 finished: bool,
213 message: PhantomData<I>,
214}
215
216impl<W: MessageWriter, I: Message> Sender<W, I> {
217 pub async fn send(&mut self, message: &I) -> Result<(), W::Error> {
218 self.writer.send(message.encode_to_vec()).await
219 }
220 pub async fn finish(mut self) -> Result<(), W::Error> {
221 self.writer.finish().await?;
222 self.finished = true;
223 Ok(())
224 }
225}
226
227impl<W: MessageWriter, I> Drop for Sender<W, I> {
228 fn drop(&mut self) {
229 if !self.finished {
230 self.writer.abort();
231 }
232 }
233}