use crate::{Ctx, IntoService, IntoServiceFactory, Service, ServiceFactory};
pub fn map_state<S, St, Req>(st: St, s: impl IntoService<S, St, Req>) -> MapState<S, St>
where
S: Service<St, Req>,
{
MapState {
st,
s: s.into_service(),
}
}
pub fn map_state_factory<Sf, St, Req>(
st: St,
sf: impl IntoServiceFactory<Sf, St, Req>,
) -> MapStateFactory<Sf, St>
where
Sf: ServiceFactory<St, Req>,
St: Clone,
{
MapStateFactory {
st,
sf: sf.into_factory(),
}
}
#[derive(Clone, Debug)]
pub struct MapState<S, St> {
s: S,
st: St,
}
impl<OtSt, S, St, Req> Service<OtSt, Req> for MapState<S, St>
where
S: Service<St, Req>,
{
type Res = S::Res;
type Error = S::Error;
fn bind(&self, ctx: crate::BindCtx<'_>) {
ctx.bind(&self.s);
}
#[inline]
async fn call(&self, req: Req, ctx: Ctx<'_, Self, OtSt>) -> Result<S::Res, S::Error> {
self.s.call(req, ctx.map_state(&self.st).cast()).await
}
#[inline]
async fn ready(&self, ctx: Ctx<'_, Self, OtSt>) -> Result<(), S::Error> {
self.s.ready(ctx.map_state(&self.st).cast()).await
}
#[inline]
async fn shutdown(&self, ctx: Ctx<'_, Self, OtSt>) {
self.s.shutdown(ctx.map_state(&self.st).cast()).await;
}
}
#[derive(Clone, Debug)]
pub struct MapStateFactory<Sf, St> {
sf: Sf,
st: St,
}
impl<OtSt, Sf, St, Req> ServiceFactory<OtSt, Req> for MapStateFactory<Sf, St>
where
Sf: ServiceFactory<St, Req>,
St: Clone,
{
type Res = Sf::Res;
type Error = Sf::Error;
type Service = MapState<Sf::Service, St>;
type InitError = Sf::InitError;
#[inline]
async fn create(&self, _: &OtSt) -> Result<Self::Service, Self::InitError> {
Ok(MapState {
s: self.sf.create(&self.st).await?,
st: self.st.clone(),
})
}
}
#[cfg(test)]
#[path = "../tests/unit/map_state.rs"]
mod tests;