use std::marker::PhantomData;
use crate::{AppBuilder, AppContext, Dependencies, Plugin};
pub type StdError = Box<dyn std::error::Error + Send + Sync>;
pub trait Service: Send + Sync {
type Handle: Send + Sync + 'static;
fn build(
ctx: &AppContext,
) -> impl std::future::Future<Output = Result<Self::Handle, StdError>> + Send;
fn dependencies() -> Dependencies {
Dependencies::new()
}
}
struct ServiceProvider<T>(PhantomData<T>)
where
T: Service;
impl<T> Plugin for ServiceProvider<T>
where
T: Service,
{
async fn build(&self, ctx: &AppContext) -> Result<(), StdError> {
ctx.add_component(T::build(ctx).await?);
Ok(())
}
fn dependencies(&self) -> Dependencies {
T::dependencies()
}
}
pub trait AddServiceExt {
fn add_service<T>(&mut self) -> &mut Self
where
T: Service + 'static;
fn has_service<T>(&self) -> bool
where
T: Service + 'static;
}
impl AddServiceExt for AppBuilder {
fn add_service<T>(&mut self) -> &mut Self
where
T: Service + 'static,
{
self.add_plugin(ServiceProvider::<T>(PhantomData));
self
}
fn has_service<T>(&self) -> bool
where
T: Service + 'static,
{
self.has_plugin::<ServiceProvider<T>>()
}
}
pub trait ServiceDependencyExt {
fn service<T>(self) -> Self
where
T: Service + 'static;
}
impl ServiceDependencyExt for Dependencies {
fn service<T>(self) -> Self
where
T: Service + 'static,
{
self.plugin::<ServiceProvider<T>>()
}
}