1use core::fmt::{Debug, Display};
2use core::marker::PhantomData;
3
4use std::collections::{HashMap, hash_map};
5use std::sync::Arc;
6
7use anyhow::bail;
8use futures::{Stream, StreamExt as _};
9use tokio::io::{AsyncBufRead, AsyncWrite};
10use tokio::sync::{Mutex, mpsc};
11use tokio_stream::wrappers::ReceiverStream;
12use tracing::{instrument, trace};
13
14use crate::Serve;
15use crate::frame::{ConnHandler, Header, HeaderReadError, Incoming, Outgoing};
16
17#[derive(Debug)]
19pub struct Server<C, I, O, H = ()> {
20 handlers: Mutex<HashMap<String, HashMap<String, mpsc::Sender<(C, I, O)>>>>,
21 conn_handler: PhantomData<H>,
22}
23
24impl<C, I, O, H> Server<C, I, O, H> {
25 #[must_use]
27 pub fn new() -> Self {
28 Self {
29 handlers: Mutex::default(),
30 conn_handler: PhantomData,
31 }
32 }
33}
34
35impl<C, I, O> Default for Server<C, I, O> {
36 fn default() -> Self {
37 Self::new()
38 }
39}
40
41pub enum AcceptError<C, I, O> {
43 HeaderRead(HeaderReadError),
45 UnhandledFunction {
47 instance: String,
49 name: String,
51 },
52 Send(mpsc::error::SendError<(C, I, O)>),
54}
55
56impl<C, I, O> From<HeaderReadError> for AcceptError<C, I, O> {
57 fn from(err: HeaderReadError) -> Self {
58 Self::HeaderRead(err)
59 }
60}
61
62impl<C, I, O> From<mpsc::error::SendError<(C, I, O)>> for AcceptError<C, I, O> {
63 fn from(err: mpsc::error::SendError<(C, I, O)>) -> Self {
64 Self::Send(err)
65 }
66}
67
68impl<C, I, O> Debug for AcceptError<C, I, O> {
69 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70 match self {
71 Self::HeaderRead(err) => Debug::fmt(err, f),
72 Self::UnhandledFunction { instance, name } => {
73 write!(f, "`{instance}#{name}` does not have a handler registered")
74 }
75 Self::Send(err) => Debug::fmt(err, f),
76 }
77 }
78}
79
80impl<C, I, O> Display for AcceptError<C, I, O> {
81 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
82 match self {
83 Self::HeaderRead(err) => Display::fmt(err, f),
84 Self::UnhandledFunction { instance, name } => {
85 write!(f, "`{instance}#{name}` does not have a handler registered")
86 }
87 Self::Send(err) => Display::fmt(err, f),
88 }
89 }
90}
91
92impl<C, I, O> core::error::Error for AcceptError<C, I, O> {}
93
94impl<C, I, O, H> Server<C, I, O, H>
95where
96 I: AsyncBufRead + Unpin,
97 H: ConnHandler<I, O>,
98{
99 #[instrument(level = "trace", skip_all, ret(level = "trace"))]
105 pub async fn accept(&self, cx: C, tx: O, mut rx: I) -> Result<(), AcceptError<C, I, O>> {
106 let Header { instance, name } = Header::read(&mut rx).await?;
107 let h = self
108 .handlers
109 .lock()
110 .await
111 .get(&instance)
112 .and_then(|h| h.get(&name))
113 .cloned()
114 .ok_or_else(|| AcceptError::UnhandledFunction { instance, name })?;
115 h.send((cx, rx, tx)).await?;
116 Ok(())
117 }
118}
119
120#[instrument(level = "trace", skip(srv, paths))]
121async fn serve<C, I, O, H>(
122 srv: &Server<C, I, O, H>,
123 instance: &str,
124 func: &str,
125 paths: Arc<[Box<[Option<usize>]>]>,
126) -> anyhow::Result<
127 impl Stream<Item = anyhow::Result<(C, Outgoing, Incoming)>> + 'static + use<C, I, O, H>,
128>
129where
130 C: Send + Sync + 'static,
131 I: AsyncBufRead + Send + Sync + Unpin + 'static,
132 O: AsyncWrite + Send + Sync + Unpin + 'static,
133 H: ConnHandler<I, O>,
134{
135 let (tx, rx) = mpsc::channel(1024);
136 let mut handlers = srv.handlers.lock().await;
137 match handlers
138 .entry(instance.to_string())
139 .or_default()
140 .entry(func.to_string())
141 {
142 hash_map::Entry::Occupied(_) => {
143 bail!("handler for `{instance}#{func}` already exists")
144 }
145 hash_map::Entry::Vacant(entry) => {
146 entry.insert(tx);
147 }
148 }
149 Ok(ReceiverStream::new(rx).map(move |(cx, rx, tx)| {
150 trace!("received invocation");
151 let rx = Incoming::new(rx, paths.as_ref(), H::DRAIN, |rx, res| {
152 H::on_ingress(rx, res)
153 });
154 let tx = Outgoing::new(tx, |tx, res| H::on_egress(tx, res));
155 Ok((cx, tx, rx))
156 }))
157}
158
159impl<C, I, O, H> Serve for Server<C, I, O, H>
160where
161 C: Send + Sync + 'static,
162 I: AsyncBufRead + Send + Sync + Unpin + 'static,
163 O: AsyncWrite + Send + Sync + Unpin + 'static,
164 H: ConnHandler<I, O> + Send + Sync,
165{
166 type Context = C;
167
168 async fn serve(
169 &self,
170 instance: &str,
171 func: &str,
172 paths: Arc<[Box<[Option<usize>]>]>,
173 ) -> anyhow::Result<
174 impl Stream<Item = anyhow::Result<(Self::Context, Outgoing, Incoming)>>
175 + 'static
176 + use<C, I, O, H>,
177 > {
178 serve(self, instance, func, paths).await
179 }
180}
181
182impl<'a, C, I, O, H> Serve for &'a Server<C, I, O, H>
183where
184 C: Send + Sync + 'static,
185 I: AsyncBufRead + Send + Sync + Unpin + 'static,
186 O: AsyncWrite + Send + Sync + Unpin + 'static,
187 H: ConnHandler<I, O> + Send + Sync,
188{
189 type Context = C;
190
191 async fn serve(
192 &self,
193 instance: &str,
194 func: &str,
195 paths: Arc<[Box<[Option<usize>]>]>,
196 ) -> anyhow::Result<
197 impl Stream<Item = anyhow::Result<(Self::Context, Outgoing, Incoming)>>
198 + 'static
199 + use<'a, C, I, O, H>,
200 > {
201 serve(self, instance, func, paths).await
202 }
203}