1use core::future::Future;
4use core::mem;
5use core::pin::Pin;
6
7use std::sync::Arc;
8
9use anyhow::{Context as _, bail};
10use futures::{SinkExt as _, Stream, TryStreamExt as _};
11use tokio::io::AsyncWriteExt as _;
12use tokio_util::codec::{FramedRead, FramedWrite};
13use tracing::{Instrument as _, Span, debug, instrument, trace};
14
15use crate::frame::{Incoming, Outgoing};
16use crate::{BufferedIncoming, Deferred as _, TupleDecode, TupleEncode};
17
18pub trait Serve: Sync {
24 type Context: Send + Sync + 'static;
26
27 fn serve(
29 &self,
30 instance: &str,
31 func: &str,
32 paths: Arc<[Box<[Option<usize>]>]>,
33 ) -> impl Future<
34 Output = anyhow::Result<
35 impl Stream<Item = anyhow::Result<(Self::Context, Outgoing, Incoming)>>
36 + Send
37 + 'static
38 + use<Self>,
39 >,
40 > + Send;
41}
42
43pub trait ServeExt: Serve {
45 #[instrument(level = "trace", skip(self, paths))]
47 fn serve_values<Params, Results>(
48 &self,
49 instance: &str,
50 func: &str,
51 paths: Arc<[Box<[Option<usize>]>]>,
52 ) -> impl Future<
53 Output = anyhow::Result<
54 impl Stream<
55 Item = anyhow::Result<(
56 Self::Context,
57 Params,
58 Option<
59 impl Future<Output = std::io::Result<()>>
60 + Send
61 + Unpin
62 + 'static
63 + use<Self, Params, Results>,
64 >,
65 impl FnOnce(
66 Results,
67 )
68 -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send + 'static>>
69 + Send
70 + 'static
71 + use<Self, Params, Results>,
72 )>,
73 >
74 + Send
75 + 'static
76 + use<Self, Params, Results>,
77 >,
78 > + Send
79 where
80 Params: TupleDecode + Send + 'static,
81 Results: TupleEncode + Send + 'static,
82 <Params::Decoder as tokio_util::codec::Decoder>::Error:
83 std::error::Error + Send + Sync + 'static,
84 <Results::Encoder as tokio_util::codec::Encoder<Results>>::Error:
85 std::error::Error + Send + Sync + 'static,
86 {
87 let span = Span::current();
88 async {
89 let invocations = self.serve(instance, func, paths).await?;
90 Ok(invocations.and_then(move |(cx, outgoing, incoming)| {
91 async {
92 let mut dec = FramedRead::new(incoming, Params::Decoder::default());
93 debug!("receiving sync parameters");
94 let Some(params) = dec
95 .try_next()
96 .await
97 .context("failed to receive sync parameters")?
98 else {
99 bail!("incomplete sync parameters")
100 };
101 trace!("received sync parameters");
102 let rx = dec.decoder_mut().take_deferred();
103 let buffer = mem::take(dec.read_buffer_mut());
104 let span = Span::current();
105 Ok((
106 cx,
107 params,
108 rx.map(|f| {
109 f(
110 BufferedIncoming {
111 buffer,
112 inner: dec.into_inner(),
113 },
114 Vec::default(),
115 )
116 }),
117 move |results| {
118 Box::pin(
119 async {
120 let mut enc =
121 FramedWrite::new(outgoing, Results::Encoder::default());
122 debug!("transmitting sync results");
123 enc.send(results)
124 .await
125 .context("failed to transmit synchronous results")?;
126 let tx = enc.encoder_mut().take_deferred();
127 let mut outgoing = enc.into_inner();
128 outgoing
129 .shutdown()
130 .await
131 .context("failed to shutdown synchronous return channel")?;
132 if let Some(tx) = tx {
133 debug!("transmitting async results");
134 tx(outgoing, Vec::default())
135 .await
136 .context("failed to write async results")?;
137 }
138 Ok(())
139 }
140 .instrument(span),
141 ) as Pin<_>
142 },
143 ))
144 }
145 .instrument(span.clone())
146 }))
147 }
148 }
149}
150
151impl<T: Serve> ServeExt for T {}
152
153#[allow(dead_code)]
154#[cfg(test)]
155mod tests {
156 use bytes::Bytes;
157 use futures::{StreamExt as _, TryStreamExt as _, stream};
158
159 use super::*;
160
161 async fn call_serve<T: Serve>(s: &T) -> anyhow::Result<Vec<(T::Context, Outgoing, Incoming)>> {
162 let st = stream::empty()
163 .chain({
164 s.serve(
165 "foo",
166 "bar",
167 Arc::from([Box::from([Some(42), None]), Box::from([None])]),
168 )
169 .await
170 .unwrap()
171 })
172 .chain({
173 s.serve(
174 "foo",
175 "bar",
176 Arc::from([Box::from([Some(42), None]), Box::from([None])]),
177 )
178 .await
179 .unwrap()
180 })
181 .chain({
182 s.serve(
183 "foo",
184 "bar",
185 Arc::from([Box::from([Some(42), None]), Box::from([None])]),
186 )
187 .await
188 .unwrap()
189 });
190 tokio::spawn(async move { st.try_collect().await })
191 .await
192 .unwrap()
193 }
194
195 fn serve_lifetime<T: Serve>(
196 s: &T,
197 ) -> impl Future<
198 Output = anyhow::Result<Pin<Box<dyn Stream<Item = anyhow::Result<T::Context>> + 'static>>>,
199 > {
200 let fut = s.serve(
201 "foo",
202 "bar",
203 Arc::from([Box::from([Some(42), None]), Box::from([None])]),
204 );
205 async move {
206 let st = fut.await.unwrap();
207 Ok(Box::pin(st.and_then(|(cx, _, _)| async { Ok(cx) }))
208 as Pin<Box<dyn Stream<Item = _>>>)
209 }
210 }
211
212 fn serve_values_lifetime<T: Serve>(
213 s: &T,
214 ) -> impl Future<
215 Output = anyhow::Result<Pin<Box<dyn Stream<Item = anyhow::Result<T::Context>> + 'static>>>,
216 > {
217 let fut = s.serve_values::<(Bytes,), (Bytes,)>(
218 "foo",
219 "bar",
220 Arc::from([Box::from([Some(42), None]), Box::from([None])]),
221 );
222 async move {
223 let st = fut.await.unwrap();
224 Ok(Box::pin(st.and_then(|(cx, _, _, tx)| async {
225 tx((Bytes::from("test"),)).await.unwrap();
226 Ok(cx)
227 })) as Pin<Box<dyn Stream<Item = _>>>)
228 }
229 }
230}