use core::marker::PhantomData;
use std::{io, sync::Arc, time::Duration};
use bincode::error::DecodeError;
use futures::future::BoxFuture;
use tokio::{net::TcpListener, sync::oneshot};
use crate::{
app::{Envelope, Packet, WireframeApp},
codec::{FrameCodec, LengthDelimitedFrameCodec},
preamble::Preamble,
serializer::{BincodeSerializer, Serializer},
};
pub(crate) fn default_worker_count() -> usize {
std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
}
pub trait PreambleSuccessHandler<T>:
for<'a> Fn(&'a T, &'a mut tokio::net::TcpStream) -> BoxFuture<'a, io::Result<()>>
+ Send
+ Sync
+ 'static
{
}
impl<T, F> PreambleSuccessHandler<T> for F where
F: for<'a> Fn(&'a T, &'a mut tokio::net::TcpStream) -> BoxFuture<'a, io::Result<()>>
+ Send
+ Sync
+ 'static
{
}
pub type PreambleHandler<T> = Arc<dyn PreambleSuccessHandler<T>>;
pub type PreambleFailure = Arc<
dyn for<'a> Fn(&'a DecodeError, &'a mut tokio::net::TcpStream) -> BoxFuture<'a, io::Result<()>>
+ Send
+ Sync
+ 'static,
>;
pub trait FactoryResult<App> {
type Error: std::error::Error + Send + Sync + 'static;
fn into_result(self) -> Result<App, Self::Error>;
}
impl<Ser, Ctx, E, Codec> FactoryResult<WireframeApp<Ser, Ctx, E, Codec>>
for WireframeApp<Ser, Ctx, E, Codec>
where
Ser: Serializer + Send + Sync,
Ctx: Send + 'static,
E: Packet,
Codec: FrameCodec,
{
type Error = std::convert::Infallible;
fn into_result(self) -> Result<WireframeApp<Ser, Ctx, E, Codec>, Self::Error> { Ok(self) }
}
impl<Ser, Ctx, E, Codec, Err> FactoryResult<WireframeApp<Ser, Ctx, E, Codec>>
for Result<WireframeApp<Ser, Ctx, E, Codec>, Err>
where
Ser: Serializer + Send + Sync,
Ctx: Send + 'static,
E: Packet,
Codec: FrameCodec,
Err: std::error::Error + Send + Sync + 'static,
{
type Error = Err;
fn into_result(self) -> Result<WireframeApp<Ser, Ctx, E, Codec>, Self::Error> { self }
}
pub trait AppFactory<Ser, Ctx, E, Codec>: Send + Sync + Clone + 'static
where
Ser: Serializer + Send + Sync,
Ctx: Send + 'static,
E: Packet,
Codec: FrameCodec,
{
type Error: std::error::Error + Send + Sync + 'static;
fn build(&self) -> Result<WireframeApp<Ser, Ctx, E, Codec>, Self::Error>;
}
impl<F, R, Ser, Ctx, E, Codec> AppFactory<Ser, Ctx, E, Codec> for F
where
F: Fn() -> R + Send + Sync + Clone + 'static,
R: FactoryResult<WireframeApp<Ser, Ctx, E, Codec>>,
Ser: Serializer + Send + Sync,
Ctx: Send + 'static,
E: Packet,
Codec: FrameCodec,
{
type Error = R::Error;
fn build(&self) -> Result<WireframeApp<Ser, Ctx, E, Codec>, Self::Error> {
(self)().into_result()
}
}
pub struct WireframeServer<
F,
T = (),
S = Unbound,
Ser = BincodeSerializer,
Ctx = (),
E = Envelope,
Codec = LengthDelimitedFrameCodec,
> where
F: AppFactory<Ser, Ctx, E, Codec>,
T: Preamble,
S: ServerState,
Ser: Serializer + Send + Sync,
Ctx: Send + 'static,
E: Packet,
Codec: FrameCodec,
{
pub(crate) factory: F,
pub(crate) workers: usize,
pub(crate) on_preamble_success: Option<PreambleHandler<T>>,
pub(crate) on_preamble_failure: Option<PreambleFailure>,
pub(crate) ready_tx: Option<oneshot::Sender<()>>,
pub(crate) backoff_config: BackoffConfig,
pub(crate) preamble_timeout: Option<Duration>,
pub(crate) state: S,
pub(crate) _app: PhantomData<(Ser, Ctx, E, Codec)>,
pub(crate) _preamble: PhantomData<T>,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Unbound;
#[derive(Debug, Clone)]
pub struct Bound {
pub(crate) listener: Arc<TcpListener>,
}
pub trait ServerState: sealed::Sealed {}
mod sealed {
pub trait Sealed {}
impl Sealed for super::Unbound {}
impl Sealed for super::Bound {}
}
impl ServerState for Unbound {}
impl ServerState for Bound {}
mod config;
pub use config::{binding, preamble};
mod connection_spawner;
pub mod error;
pub use error::ServerError;
mod runtime;
pub use runtime::BackoffConfig;
#[cfg(test)]
pub(crate) mod test_util;