use std::{convert::Infallible, sync::Arc};
use async_trait::async_trait;
use crate::app::PacketParts;
#[derive(Debug, Default)]
pub struct FrameContainer<F> {
frame: F,
}
impl<F> FrameContainer<F> {
#[must_use]
pub fn new(frame: F) -> Self { Self { frame } }
#[must_use]
pub fn frame(&self) -> &F { &self.frame }
#[must_use]
pub fn frame_mut(&mut self) -> &mut F { &mut self.frame }
#[must_use]
pub fn into_inner(self) -> F { self.frame }
}
#[derive(Debug)]
pub struct ServiceRequest {
inner: FrameContainer<Vec<u8>>,
correlation_id: Option<u64>,
}
impl ServiceRequest {
#[must_use]
pub fn new(frame: Vec<u8>, correlation_id: Option<u64>) -> Self {
Self {
inner: FrameContainer::new(frame),
correlation_id,
}
}
#[must_use]
pub fn frame(&self) -> &[u8] { self.inner.frame().as_slice() }
#[must_use]
pub fn correlation_id(&self) -> Option<u64> { self.correlation_id }
#[must_use]
pub fn set_correlation_id(&mut self, correlation_id: Option<u64>) -> &mut Self {
self.correlation_id = correlation_id;
self
}
#[must_use]
pub fn frame_mut(&mut self) -> &mut Vec<u8> { self.inner.frame_mut() }
#[must_use]
pub fn into_inner(self) -> Vec<u8> { self.inner.into_inner() }
}
#[derive(Debug, Default)]
pub struct ServiceResponse {
inner: FrameContainer<Vec<u8>>,
correlation_id: Option<u64>,
}
impl ServiceResponse {
#[must_use]
pub fn new(frame: Vec<u8>, correlation_id: Option<u64>) -> Self {
Self {
inner: FrameContainer::new(frame),
correlation_id,
}
}
#[must_use]
pub fn frame(&self) -> &[u8] { self.inner.frame().as_slice() }
#[must_use]
pub fn frame_mut(&mut self) -> &mut Vec<u8> { self.inner.frame_mut() }
#[must_use]
pub fn correlation_id(&self) -> Option<u64> { self.correlation_id }
#[must_use]
pub fn set_correlation_id(&mut self, correlation_id: Option<u64>) -> &mut Self {
self.correlation_id = correlation_id;
self
}
#[must_use]
pub fn into_inner(self) -> Vec<u8> { self.inner.into_inner() }
}
pub struct Next<'a, S>
where
S: Service + ?Sized,
{
service: &'a S,
}
impl<'a, S> Next<'a, S>
where
S: Service + ?Sized,
{
#[inline]
#[must_use]
pub fn new(service: &'a S) -> Self { Self { service } }
#[must_use = "await the returned future"]
pub async fn call(&self, req: ServiceRequest) -> Result<ServiceResponse, S::Error> {
self.service.call(req).await
}
}
#[async_trait]
pub trait Service: Send + Sync {
type Error: std::error::Error + Send + Sync + 'static;
async fn call(&self, req: ServiceRequest) -> Result<ServiceResponse, Self::Error>;
}
#[async_trait]
pub trait Transform<S>: Send + Sync
where
S: Service,
{
type Output: Service;
#[must_use = "use the returned middleware service"]
async fn transform(&self, service: S) -> Self::Output;
}
pub struct FromFn<F> {
f: F,
}
impl<F> FromFn<F> {
pub fn new(f: F) -> Self { Self { f } }
}
pub fn from_fn<F>(f: F) -> FromFn<F> { FromFn::new(f) }
pub struct FnService<S, F> {
service: S,
f: Arc<F>,
}
#[async_trait]
impl<S, F, Fut> Service for FnService<S, F>
where
S: Service + 'static,
F: for<'a> Fn(ServiceRequest, Next<'a, S>) -> Fut + Send + Sync + 'static,
Fut: std::future::Future<Output = Result<ServiceResponse, S::Error>> + Send,
{
type Error = S::Error;
async fn call(&self, req: ServiceRequest) -> Result<ServiceResponse, Self::Error> {
let next = Next::new(&self.service);
(self.f.as_ref())(req, next).await
}
}
#[async_trait]
impl<S, F, Fut> Transform<S> for FromFn<F>
where
S: Service + 'static,
F: for<'a> Fn(ServiceRequest, Next<'a, S>) -> Fut + Send + Sync + Clone + 'static,
Fut: std::future::Future<Output = Result<ServiceResponse, S::Error>> + Send,
{
type Output = FnService<S, F>;
async fn transform(&self, service: S) -> Self::Output {
FnService {
service,
f: Arc::new(self.f.clone()),
}
}
}
use crate::app::{Handler, Packet};
pub struct HandlerService<E: Packet> {
id: u32,
svc: Box<dyn Service<Error = Infallible> + Send + Sync>,
_marker: std::marker::PhantomData<E>,
}
impl<E: Packet> HandlerService<E> {
#[must_use]
pub fn new(id: u32, handler: Handler<E>) -> Self {
Self {
id,
svc: Box::new(RouteService {
id,
handler,
_marker: std::marker::PhantomData,
}),
_marker: std::marker::PhantomData,
}
}
#[must_use]
pub fn from_service(id: u32, svc: impl Service<Error = Infallible> + 'static) -> Self {
Self {
id,
svc: Box::new(svc),
_marker: std::marker::PhantomData,
}
}
#[must_use]
pub const fn id(&self) -> u32 { self.id }
}
struct RouteService<E: Packet> {
id: u32,
handler: Handler<E>,
_marker: std::marker::PhantomData<E>,
}
#[async_trait]
impl<E: Packet> Service for RouteService<E> {
type Error = Infallible;
async fn call(&self, req: ServiceRequest) -> Result<ServiceResponse, Self::Error> {
let env = E::from_parts(PacketParts::new(
self.id,
req.correlation_id(),
req.into_inner(),
));
(self.handler.as_ref())(&env).await;
let parts = env.into_parts();
let correlation_id = parts.correlation_id();
let payload = parts.into_payload();
Ok(ServiceResponse::new(payload, correlation_id))
}
}
#[async_trait]
impl<E: Packet> Service for HandlerService<E> {
type Error = Infallible;
async fn call(&self, req: ServiceRequest) -> Result<ServiceResponse, Self::Error> {
self.svc.call(req).await
}
}