use std::collections::HashMap;
use std::error::Error;
use std::sync::Arc;
use async_lock::RwLock;
use futures::Future;
use futures::future::BoxFuture;
use crate::ffi;
use crate::local_client::LocalClient;
use crate::local_session::LocalSession;
pub type ServerError = Box<dyn Error + Send + Sync>;
pub type ServerResult<T> = Result<T, ServerError>;
type SessionCallback =
Arc<dyn for<'a> Fn(&'a [u8]) -> BoxFuture<'a, Result<(), ServerError>> + Send + Sync>;
type OnPollRequestCallback =
Arc<dyn Fn(&Server) -> BoxFuture<'static, Result<(), ServerError>> + Send + Sync>;
pub trait SessionHandler: Send + Sync {
fn send_response<'a>(
&'a mut self,
msg: &'a [u8],
) -> impl Future<Output = Result<(), ServerError>> + Send + 'a;
}
#[derive(Clone)]
pub struct Server {
pub(crate) server: Arc<ffi::Server>,
pub(crate) callbacks: Arc<RwLock<HashMap<u32, SessionCallback>>>,
pub(crate) on_poll_request: Option<OnPollRequestCallback>,
}
impl std::fmt::Debug for Server {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let addr = std::ptr::addr_of!(self);
write!(f, "Server {addr:?}")?;
Ok(())
}
}
impl Server {
pub fn new(on_poll_request: Option<OnPollRequestCallback>) -> Self {
let server = Arc::new(ffi::Server::new(on_poll_request.is_some()));
let callbacks = Arc::default();
Self {
server,
callbacks,
on_poll_request,
}
}
pub async fn new_session_with_callback<F>(&self, send_response: F) -> LocalSession
where
F: for<'a> Fn(&'a [u8]) -> BoxFuture<'a, Result<(), ServerError>> + 'static + Sync + Send,
{
let id = self.server.new_session();
let server = self.clone();
self.callbacks
.write()
.await
.insert(id, Arc::new(send_response));
LocalSession {
id,
server,
closed: false,
}
}
pub async fn new_session<F>(&self, session_handler: F) -> LocalSession
where
F: SessionHandler + 'static + Sync + Send + Clone,
{
self.new_session_with_callback(move |msg| {
let mut session_handler = session_handler.clone();
Box::pin(async move { session_handler.send_response(msg).await })
})
.await
}
pub fn new_local_client(&self) -> LocalClient {
LocalClient::new(self)
}
pub async fn poll(&self) -> Result<(), ServerError> {
let responses = self.server.poll();
let mut results = Vec::with_capacity(responses.size());
for response in responses.iter_responses() {
let cb = self
.callbacks
.read()
.await
.get(&response.client_id())
.cloned();
if let Some(f) = cb {
results.push(f(response.msg()).await);
}
}
results.into_iter().collect()
}
}