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] [package]
name = "aerosol" name = "aerosol"
version = "0.1.2" version = "0.2.0"
authors = ["Diggory Blake <diggsey@googlemail.com>"] authors = ["Diggory Blake <diggsey@googlemail.com>"]
edition = "2018" edition = "2018"
description = "Dependency injection with compile-time guarantees" description = "Dependency injection with compile-time guarantees"

View file

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

View file

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

View file

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