From cc46fbe6210620bca67d8a9eca78abde03cbfd0d Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Tue, 2 Apr 2019 17:16:33 +0100 Subject: [PATCH] Add support for dependencies of dependencies --- Cargo.toml | 2 +- src/context.rs | 41 ++++++++++++++++++++++++++++++++++++----- src/lib.rs | 6 +++--- src/main.rs | 6 +++--- 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7ddf4d3..6204c3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aerosol" -version = "0.1.2" +version = "0.2.0" authors = ["Diggory Blake "] edition = "2018" description = "Dependency injection with compile-time guarantees" diff --git a/src/context.rs b/src/context.rs index 08080e6..45abec6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -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 { + $( + 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; -/// fn build() -> Result, failure::Error> { Ok(Arc::new(Foo)) } +/// fn build(_: ()) -> Result, failure::Error> { Ok(Arc::new(Foo)) } /// } /// /// aerosol::define_context!( diff --git a/src/lib.rs b/src/lib.rs index 855b200..dab41b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,7 +52,7 @@ //! struct StdoutLoggerFactory; //! impl aerosol::Factory for StdoutLoggerFactory { //! type Object = Arc; -//! fn build() -> Result, failure::Error> { +//! fn build(_: ()) -> Result, failure::Error> { //! Ok(Arc::new(StdoutLogger)) //! } //! } @@ -116,9 +116,9 @@ pub trait Provide { /// Implement this trait to provide a convenient syntax for /// constructing implementations of dependencies. -pub trait Factory { +pub trait Factory { type Object; - fn build() -> Result; + fn build(args: Args) -> Result; } /// Allows cloning a context whilst replacing one dependency diff --git a/src/main.rs b/src/main.rs index e2cbdc3..7cfc5f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 { Ok(Foo) } + fn build(_: (Bar,)) -> Result { Ok(Foo) } } aerosol::define_context!( TestContext { - foo: Foo [FooFactory], + foo: Foo [(bar) FooFactory], bar: Bar } );