Add support for dependencies of dependencies

This commit is contained in:
Diggory Blake 2019-04-02 17:16:33 +01:00
parent f47d3a417d
commit cc46fbe621
4 changed files with 43 additions and 12 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "aerosol"
version = "0.1.2"
version = "0.2.0"
authors = ["Diggory Blake <diggsey@googlemail.com>"]
edition = "2018"
description = "Dependency injection with compile-time guarantees"

View file

@ -22,7 +22,7 @@ macro_rules! private_define_context {
{
$caller:tt
name = [{ $name:ident }]
$(auto_field = [{ $auto_field:ident, $auto_t:ty, $factory:ty }])*
$(auto_field = [{ $auto_field:ident, $auto_t:ty, $factory:ty, ($($f_args:ident,)*) }])*
$(field = [{ $field:ident, $t:ty }])*
} => {
$crate::tt_call::tt_return! {
@ -36,8 +36,11 @@ macro_rules! private_define_context {
impl $name {
fn new($($field: $t,)*) -> Result<Self, $crate::failure::Error> {
$(
let $auto_field = <$factory as $crate::Factory<_>>::build(($($f_args.clone(),)*))?;
)*
Ok(Self {
$($auto_field: <$factory as $crate::Factory>::build()?,)*
$($auto_field,)*
$($field,)*
})
}
@ -75,6 +78,34 @@ macro_rules! private_define_context {
}]
}
};
{
$caller:tt
$(auto_field = [{ $($auto_field:tt)* }])*
$(field = [{ $($field:tt)* }])*
rest = [{ $field_name:ident: $t:ty [ ($($f_args:ident),*) $factory:ty ], $($rest:tt)* }]
} => {
private_define_context! {
$caller
$(auto_field = [{ $($auto_field)* }])*
auto_field = [{ $field_name, $t, $factory, ($($f_args,)*) }]
$(field = [{ $($field)* }])*
rest = [{ $($rest)* }]
}
};
{
$caller:tt
$(auto_field = [{ $($auto_field:tt)* }])*
$(field = [{ $($field:tt)* }])*
rest = [{ $field_name:ident: $t:ty [ ($($f_args:ident),*) $factory:ty ] }]
} => {
private_define_context! {
$caller
$(auto_field = [{ $($auto_field)* }])*
auto_field = [{ $field_name, $t, $factory, ($($f_args,)*) }]
$(field = [{ $($field)* }])*
rest = [{ }]
}
};
{
$caller:tt
$(auto_field = [{ $($auto_field:tt)* }])*
@ -84,7 +115,7 @@ macro_rules! private_define_context {
private_define_context! {
$caller
$(auto_field = [{ $($auto_field)* }])*
auto_field = [{ $field_name, $t, $factory }]
auto_field = [{ $field_name, $t, $factory, () }]
$(field = [{ $($field)* }])*
rest = [{ $($rest)* }]
}
@ -98,7 +129,7 @@ macro_rules! private_define_context {
private_define_context! {
$caller
$(auto_field = [{ $($auto_field)* }])*
auto_field = [{ $field_name, $t, $factory }]
auto_field = [{ $field_name, $t, $factory, () }]
$(field = [{ $($field)* }])*
rest = [{ }]
}
@ -219,7 +250,7 @@ macro_rules! private_define_context {
/// struct FooFactory;
/// impl aerosol::Factory for FooFactory {
/// type Object = Arc<Foo>;
/// fn build() -> Result<Arc<Foo>, failure::Error> { Ok(Arc::new(Foo)) }
/// fn build(_: ()) -> Result<Arc<Foo>, failure::Error> { Ok(Arc::new(Foo)) }
/// }
///
/// aerosol::define_context!(

View file

@ -52,7 +52,7 @@
//! struct StdoutLoggerFactory;
//! impl aerosol::Factory for StdoutLoggerFactory {
//! type Object = Arc<Logger>;
//! fn build() -> Result<Arc<Logger>, failure::Error> {
//! fn build(_: ()) -> Result<Arc<Logger>, failure::Error> {
//! Ok(Arc::new(StdoutLogger))
//! }
//! }
@ -116,9 +116,9 @@ pub trait Provide<T> {
/// Implement this trait to provide a convenient syntax for
/// constructing implementations of dependencies.
pub trait Factory {
pub trait Factory<Args=()> {
type Object;
fn build() -> Result<Self::Object, failure::Error>;
fn build(args: Args) -> Result<Self::Object, failure::Error>;
}
/// Allows cloning a context whilst replacing one dependency

View file

@ -39,14 +39,14 @@ struct Foo;
#[derive(Clone, Debug)]
struct Bar;
impl aerosol::Factory for FooFactory {
impl aerosol::Factory<(Bar,)> for FooFactory {
type Object = Foo;
fn build() -> Result<Foo, failure::Error> { Ok(Foo) }
fn build(_: (Bar,)) -> Result<Foo, failure::Error> { Ok(Foo) }
}
aerosol::define_context!(
TestContext {
foo: Foo [FooFactory],
foo: Foo [(bar) FooFactory],
bar: Bar
}
);