use crate::DiResult;
use std::any::Any;
use std::future::Future;
use std::ops::Deref;
use std::pin::Pin;
use std::sync::Arc;
type ProviderFutureInner =
Pin<Box<dyn Future<Output = DiResult<Box<dyn Any + Send + Sync>>> + Send>>;
pub struct ProviderFuture(ProviderFutureInner);
impl ProviderFuture {
pub fn new(future: ProviderFutureInner) -> Self {
Self(future)
}
pub fn into_inner(self) -> ProviderFutureInner {
self.0
}
}
impl Deref for ProviderFuture {
type Target = ProviderFutureInner;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<ProviderFutureInner> for ProviderFuture {
fn from(future: ProviderFutureInner) -> Self {
Self::new(future)
}
}
pub struct ProviderFn(Arc<dyn Fn() -> ProviderFuture + Send + Sync>);
impl ProviderFn {
pub fn new(func: Arc<dyn Fn() -> ProviderFuture + Send + Sync>) -> Self {
Self(func)
}
pub fn as_fn(&self) -> &Arc<dyn Fn() -> ProviderFuture + Send + Sync> {
&self.0
}
pub fn into_inner(self) -> Arc<dyn Fn() -> ProviderFuture + Send + Sync> {
self.0
}
}
impl Deref for ProviderFn {
type Target = Arc<dyn Fn() -> ProviderFuture + Send + Sync>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Arc<dyn Fn() -> ProviderFuture + Send + Sync>> for ProviderFn {
fn from(func: Arc<dyn Fn() -> ProviderFuture + Send + Sync>) -> Self {
Self::new(func)
}
}
pub trait Provider: Send + Sync {
fn provide(&self) -> ProviderFuture;
}
impl<F, Fut, T> Provider for F
where
F: Fn() -> Fut + Send + Sync,
Fut: Future<Output = DiResult<T>> + Send + 'static,
T: Any + Send + Sync + 'static,
{
fn provide(&self) -> ProviderFuture {
let fut = self();
ProviderFuture::new(Box::pin(async move {
let result = fut.await?;
Ok(Box::new(result) as Box<dyn Any + Send + Sync>)
}))
}
}