use std::ops::{Deref, DerefMut};
use crate::{
AppContext, AppError, ComponentMut, ComponentRef, Dependencies, Service, ServiceDependencyExt,
};
pub trait Extract<T> {
fn extract(ctx: &AppContext) -> Result<T, AppError>;
fn dependencies() -> Dependencies {
Dependencies::new()
}
}
pub trait ExtractRef<T> {
type Ref<'a>: Deref<Target = T> + 'a;
fn extract_ref(ctx: &AppContext) -> Result<Self::Ref<'_>, AppError>;
fn dependencies() -> Dependencies {
Dependencies::new()
}
}
pub trait ExtractMut<T>: ExtractRef<T> {
type RefMut<'a>: DerefMut<Target = T> + 'a;
fn extract_mut(ctx: &AppContext) -> Result<Self::RefMut<'_>, AppError>;
}
impl<T, S> Extract<T> for S
where
T: Clone + Send + Sync + 'static,
S: Service<Handle = T> + 'static,
{
fn extract(ctx: &AppContext) -> Result<T, AppError> {
ctx.get_component::<T>().ok_or(AppError::MissingComponent(std::any::type_name::<T>()))
}
fn dependencies() -> Dependencies {
Dependencies::new().service::<S>()
}
}
impl<T, S> ExtractRef<T> for S
where
T: Send + Sync + 'static,
S: Service<Handle = T> + 'static,
{
type Ref<'a> = ComponentRef<'a, T>;
fn extract_ref(ctx: &AppContext) -> Result<Self::Ref<'_>, AppError> {
ctx.get_component_ref::<T>().ok_or(AppError::MissingComponent(std::any::type_name::<T>()))
}
fn dependencies() -> Dependencies {
Dependencies::new().service::<S>()
}
}
impl ExtractRef<AppContext> for AppContext {
type Ref<'a> = &'a AppContext;
fn extract_ref(ctx: &AppContext) -> Result<&AppContext, AppError> {
Ok(ctx)
}
}
pub struct Component;
impl<T> Extract<T> for Component
where
T: Clone + Send + Sync + 'static,
{
fn extract(ctx: &AppContext) -> Result<T, AppError> {
ctx.get_component::<T>().ok_or(AppError::MissingComponent(std::any::type_name::<T>()))
}
}
impl<T> ExtractRef<T> for Component
where
T: Send + Sync + 'static,
{
type Ref<'a> = ComponentRef<'a, T>;
fn extract_ref(ctx: &AppContext) -> Result<Self::Ref<'_>, AppError> {
ctx.get_component_ref::<T>()
.ok_or(AppError::MissingComponent(std::any::type_name::<T>()))
}
}
impl<T> ExtractMut<T> for Component
where
T: Send + Sync + 'static,
{
type RefMut<'a> = ComponentMut<'a, T>;
fn extract_mut(ctx: &AppContext) -> Result<Self::RefMut<'_>, AppError> {
ctx.get_component_mut::<T>()
.ok_or(AppError::MissingComponent(std::any::type_name::<T>()))
}
}