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::{AsyncRead, 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 std::fmt::Formatter<'_>) -> std::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 std::fmt::Formatter<'_>) -> std::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: AsyncRead + 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.handlers.lock().await;
108 let h = h
109 .get(&instance)
110 .and_then(|h| h.get(&name))
111 .ok_or_else(|| AcceptError::UnhandledFunction { instance, name })?;
112 h.send((cx, rx, tx)).await?;
113 Ok(())
114 }
115}
116
117#[instrument(level = "trace", skip(srv, paths))]
118async fn serve<C, I, O, H>(
119 srv: &Server<C, I, O, H>,
120 instance: &str,
121 func: &str,
122 paths: Arc<[Box<[Option<usize>]>]>,
123) -> anyhow::Result<
124 impl Stream<Item = anyhow::Result<(C, Outgoing, Incoming)>> + 'static + use<C, I, O, H>,
125>
126where
127 C: Send + Sync + 'static,
128 I: AsyncRead + Send + Sync + Unpin + 'static,
129 O: AsyncWrite + Send + Sync + Unpin + 'static,
130 H: ConnHandler<I, O>,
131{
132 let (tx, rx) = mpsc::channel(1024);
133 let mut handlers = srv.handlers.lock().await;
134 match handlers
135 .entry(instance.to_string())
136 .or_default()
137 .entry(func.to_string())
138 {
139 hash_map::Entry::Occupied(_) => {
140 bail!("handler for `{instance}#{func}` already exists")
141 }
142 hash_map::Entry::Vacant(entry) => {
143 entry.insert(tx);
144 }
145 }
146 Ok(ReceiverStream::new(rx).map(move |(cx, rx, tx)| {
147 trace!("received invocation");
148 let rx = Incoming::new(rx, paths.as_ref(), |rx, res| H::on_ingress(rx, res));
149 let tx = Outgoing::new(tx, |tx, res| H::on_egress(tx, res));
150 Ok((cx, tx, rx))
151 }))
152}
153
154impl<C, I, O, H> Serve for Server<C, I, O, H>
155where
156 C: Send + Sync + 'static,
157 I: AsyncRead + Send + Sync + Unpin + 'static,
158 O: AsyncWrite + Send + Sync + Unpin + 'static,
159 H: ConnHandler<I, O> + Send + Sync,
160{
161 type Context = C;
162
163 async fn serve(
164 &self,
165 instance: &str,
166 func: &str,
167 paths: Arc<[Box<[Option<usize>]>]>,
168 ) -> anyhow::Result<
169 impl Stream<Item = anyhow::Result<(Self::Context, Outgoing, Incoming)>>
170 + 'static
171 + use<C, I, O, H>,
172 > {
173 serve(self, instance, func, paths).await
174 }
175}
176
177impl<'a, C, I, O, H> Serve for &'a Server<C, I, O, H>
178where
179 C: Send + Sync + 'static,
180 I: AsyncRead + Send + Sync + Unpin + 'static,
181 O: AsyncWrite + Send + Sync + Unpin + 'static,
182 H: ConnHandler<I, O> + Send + Sync,
183{
184 type Context = C;
185
186 async fn serve(
187 &self,
188 instance: &str,
189 func: &str,
190 paths: Arc<[Box<[Option<usize>]>]>,
191 ) -> anyhow::Result<
192 impl Stream<Item = anyhow::Result<(Self::Context, Outgoing, Incoming)>>
193 + 'static
194 + use<'a, C, I, O, H>,
195 > {
196 serve(self, instance, func, paths).await
197 }
198}