ferrunix_core/dependency_builder.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
//! Implementation of [`DepBuilder`] for tuples to be used with
//! [`Registry::with_deps`].
use std::any::TypeId;
use crate::types::Registerable;
use crate::Registry;
/// Required for sealing the trait. *Must not be public*.
pub(crate) mod private {
/// This token is used to seal the [`DepBuilder`] trait from downstream
/// crates.
#[allow(missing_debug_implementations)]
#[derive(Clone, Copy)]
pub struct SealToken;
}
/// The [`DepBuilder`] trait is the key to specify a variable amount of
/// dependencies in the [`Registry::with_deps`] call from [`Registry`].
///
/// The trait is implemented by the `DepBuilderImpl!` macro for 0-ary, to 10-ary
/// tuples (e.g., `(T1,)`, `(T1, T2)`, etc.), which allows these tuples to be
/// passed as a single type parameter into [`Registry::with_deps`].
///
/// This trait is sealed, meaning it cannot be implemented or called by any
/// downstream crates.
pub trait DepBuilder<R> {
/// When implemented, this should validate that all dependencies which are
/// part of `Self` exist to construct the type `R`. If the dependencies
/// cannot be fulfilled, `None` must be returned.
///
/// If the dependencies can be fulfilled, they must be constructed as an
/// N-ary tuple (same length and types as `Self`) and passed as the
/// argument to `ctor`. `ctor` is a user provided constructor for the
/// type `R`.
///
/// An implementation for tuples is provided by `DepBuilderImpl!`.
///
/// We advise against *manually* implementing `build`.
fn build(
registry: &Registry,
ctor: fn(Self) -> R,
_: private::SealToken,
) -> Option<R>
where
R: Sized;
/// Constructs a [`Vec`] of [`std::any::TypeId`]s from the types in `Self`.
/// The resulting vector must have the same length as `Self`.
///
/// An implementation for tuples is provided by `DepBuilderImpl!`.
///
/// We advise against *manually* implementing `as_typeids`.
fn as_typeids(_: private::SealToken) -> Vec<TypeId>;
}
impl<R> DepBuilder<R> for ()
where
R: Registerable,
{
fn build(
_registry: &Registry,
ctor: fn(Self) -> R,
_: private::SealToken,
) -> Option<R> {
Some(ctor(()))
}
fn as_typeids(_: private::SealToken) -> Vec<TypeId> {
Vec::new()
}
}
/// Generates the implementation for [`DepBuilder`].
macro_rules! DepBuilderImpl {
($n:expr, { $($ts:ident),+ }) => {
impl<R, $($ts,)*> $crate::dependency_builder::DepBuilder<R> for ($($ts,)*)
where
R: $crate::types::Registerable,
$($ts: $crate::dependencies::Dep,)*
{
fn build(registry: &$crate::registry::Registry, ctor: fn(Self) -> R, _: private::SealToken) -> Option<R> {
if !registry.validate::<R>() {
return None;
}
let deps = (
$(
<$ts>::new(registry),
)*
);
Some(ctor(deps))
}
fn as_typeids(_: private::SealToken) -> ::std::vec::Vec<::std::any::TypeId> {
::std::vec![ $(<$ts>::type_id(),)* ]
}
}
};
}
DepBuilderImpl!(1, { T1 });
DepBuilderImpl!(2, { T1, T2 });
DepBuilderImpl!(3, { T1, T2, T3 });
DepBuilderImpl!(4, { T1, T2, T3, T4 });
DepBuilderImpl!(5, { T1, T2, T3, T4, T5 });
DepBuilderImpl!(6, { T1, T2, T3, T4, T5, T6 });
DepBuilderImpl!(7, { T1, T2, T3, T4, T5, T6, T8 });
DepBuilderImpl!(8, { T1, T2, T3, T4, T5, T6, T8, T9 });