aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/basic/animals/human.rs6
-rw-r--r--examples/basic/bootstrap.rs5
-rw-r--r--examples/basic/main.rs2
-rw-r--r--macros/src/dependency_type.rs40
-rw-r--r--macros/src/injectable_impl.rs79
-rw-r--r--macros/src/lib.rs1
6 files changed, 82 insertions, 51 deletions
diff --git a/examples/basic/animals/human.rs b/examples/basic/animals/human.rs
index 8e52b5b..d9b848b 100644
--- a/examples/basic/animals/human.rs
+++ b/examples/basic/animals/human.rs
@@ -1,5 +1,5 @@
use syrette::injectable;
-use syrette::ptr::TransientPtr;
+use syrette::ptr::{SingletonPtr, TransientPtr};
use crate::interfaces::cat::ICat;
use crate::interfaces::dog::IDog;
@@ -7,14 +7,14 @@ use crate::interfaces::human::IHuman;
pub struct Human
{
- dog: TransientPtr<dyn IDog>,
+ dog: SingletonPtr<dyn IDog>,
cat: TransientPtr<dyn ICat>,
}
#[injectable(IHuman)]
impl Human
{
- pub fn new(dog: TransientPtr<dyn IDog>, cat: TransientPtr<dyn ICat>) -> Self
+ pub fn new(dog: SingletonPtr<dyn IDog>, cat: TransientPtr<dyn ICat>) -> Self
{
Self { dog, cat }
}
diff --git a/examples/basic/bootstrap.rs b/examples/basic/bootstrap.rs
index 71ef713..10a7041 100644
--- a/examples/basic/bootstrap.rs
+++ b/examples/basic/bootstrap.rs
@@ -14,7 +14,10 @@ pub fn bootstrap() -> DIContainer
{
let mut di_container: DIContainer = DIContainer::new();
- di_container.bind::<dyn IDog>().to::<Dog>();
+ di_container
+ .bind::<dyn IDog>()
+ .to_singleton::<Dog>()
+ .unwrap();
di_container.bind::<dyn ICat>().to::<Cat>();
di_container.bind::<dyn IHuman>().to::<Human>();
diff --git a/examples/basic/main.rs b/examples/basic/main.rs
index f96d963..3a937c3 100644
--- a/examples/basic/main.rs
+++ b/examples/basic/main.rs
@@ -16,7 +16,7 @@ fn main()
let di_container = bootstrap();
- let dog = di_container.get::<dyn IDog>().unwrap();
+ let dog = di_container.get_singleton::<dyn IDog>().unwrap();
dog.woof();
diff --git a/macros/src/dependency_type.rs b/macros/src/dependency_type.rs
new file mode 100644
index 0000000..35f810e
--- /dev/null
+++ b/macros/src/dependency_type.rs
@@ -0,0 +1,40 @@
+use proc_macro2::Ident;
+use syn::{GenericArgument, PathArguments, Type, TypePath};
+
+pub struct DependencyType
+{
+ pub interface: Type,
+ pub ptr: Ident,
+}
+
+impl DependencyType
+{
+ pub fn from_type_path(type_path: &TypePath) -> Option<Self>
+ {
+ // Assume the type path has a last segment.
+ let last_path_segment = type_path.path.segments.last().unwrap();
+
+ let ptr = &last_path_segment.ident;
+
+ match &last_path_segment.arguments {
+ PathArguments::AngleBracketed(angle_bracketed_generic_args) => {
+ let generic_args = &angle_bracketed_generic_args.args;
+
+ let opt_first_generic_arg = generic_args.first();
+
+ // Assume a first generic argument exists because TransientPtr,
+ // SingletonPtr and FactoryPtr requires one
+ let first_generic_arg = opt_first_generic_arg.as_ref().unwrap();
+
+ match first_generic_arg {
+ GenericArgument::Type(first_generic_arg_type) => Some(Self {
+ interface: first_generic_arg_type.clone(),
+ ptr: ptr.clone(),
+ }),
+ &_ => None,
+ }
+ }
+ &_ => None,
+ }
+ }
+}
diff --git a/macros/src/injectable_impl.rs b/macros/src/injectable_impl.rs
index 89346e8..f510407 100644
--- a/macros/src/injectable_impl.rs
+++ b/macros/src/injectable_impl.rs
@@ -2,16 +2,17 @@ use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream};
use syn::Generics;
use syn::{
- parse_str, punctuated::Punctuated, token::Comma, ExprMethodCall, FnArg,
- GenericArgument, Ident, ImplItem, ImplItemMethod, ItemImpl, Path, PathArguments,
- Type, TypePath,
+ parse_str, punctuated::Punctuated, token::Comma, ExprMethodCall, FnArg, Ident,
+ ImplItem, ImplItemMethod, ItemImpl, Path, Type, TypePath,
};
+use crate::dependency_type::DependencyType;
+
const DI_CONTAINER_VAR_NAME: &str = "di_container";
pub struct InjectableImpl
{
- pub dependency_types: Vec<Type>,
+ pub dependency_types: Vec<DependencyType>,
pub self_type: Type,
pub generics: Generics,
pub original_impl: ItemImpl,
@@ -21,20 +22,17 @@ impl Parse for InjectableImpl
{
fn parse(input: ParseStream) -> syn::Result<Self>
{
- match input.parse::<ItemImpl>() {
- Ok(impl_parsed_input) => {
- match Self::_get_dependency_types(&impl_parsed_input) {
- Ok(dependency_types) => Ok(Self {
- dependency_types,
- self_type: impl_parsed_input.self_ty.as_ref().clone(),
- generics: impl_parsed_input.generics.clone(),
- original_impl: impl_parsed_input,
- }),
- Err(error_msg) => Err(input.error(error_msg)),
- }
- }
- Err(_) => Err(input.error("Expected an impl")),
- }
+ let impl_parsed_input = input.parse::<ItemImpl>()?;
+
+ let dependency_types = Self::_get_dependency_types(&impl_parsed_input)
+ .map_err(|err| input.error(err))?;
+
+ Ok(Self {
+ dependency_types,
+ self_type: impl_parsed_input.self_ty.as_ref().clone(),
+ generics: impl_parsed_input.generics.clone(),
+ original_impl: impl_parsed_input,
+ })
}
}
@@ -81,16 +79,23 @@ impl InjectableImpl
}
}
- fn _create_get_dependencies(dependency_types: &[Type]) -> Vec<ExprMethodCall>
+ fn _create_get_dependencies(
+ dependency_types: &[DependencyType],
+ ) -> Vec<ExprMethodCall>
{
dependency_types
.iter()
- .filter_map(|dep_type| match dep_type {
+ .filter_map(|dep_type| match &dep_type.interface {
Type::TraitObject(dep_type_trait) => Some(
parse_str(
format!(
- "{}.get::<{}>()",
+ "{}.get{}::<{}>()",
DI_CONTAINER_VAR_NAME,
+ if dep_type.ptr == "SingletonPtr" {
+ "_singleton"
+ } else {
+ ""
+ },
dep_type_trait.to_token_stream()
)
.as_str(),
@@ -194,12 +199,17 @@ impl InjectableImpl
arg_type_path_string == "TransientPtr"
|| arg_type_path_string == "ptr::TransientPtr"
|| arg_type_path_string == "syrrete::ptr::TransientPtr"
+ || arg_type_path_string == "SingletonPtr"
+ || arg_type_path_string == "ptr::SingletonPtr"
+ || arg_type_path_string == "syrrete::ptr::SingletonPtr"
|| arg_type_path_string == "FactoryPtr"
|| arg_type_path_string == "ptr::FactoryPtr"
|| arg_type_path_string == "syrrete::ptr::FactoryPtr"
}
- fn _get_dependency_types(item_impl: &ItemImpl) -> Result<Vec<Type>, &'static str>
+ fn _get_dependency_types(
+ item_impl: &ItemImpl,
+ ) -> Result<Vec<DependencyType>, &'static str>
{
let new_method_impl_item = match Self::_find_method_by_name(item_impl, "new") {
Some(method_item) => Ok(method_item),
@@ -223,30 +233,7 @@ impl InjectableImpl
Ok(new_method_arg_type_paths
.iter()
- .filter_map(|arg_type_path| {
- // Assume the type path has a last segment.
- let last_path_segment = arg_type_path.path.segments.last().unwrap();
-
- match &last_path_segment.arguments {
- PathArguments::AngleBracketed(angle_bracketed_generic_args) => {
- let generic_args = &angle_bracketed_generic_args.args;
-
- let opt_first_generic_arg = generic_args.first();
-
- // Assume a first generic argument exists because TransientPtr and
- // FactoryPtr requires one
- let first_generic_arg = opt_first_generic_arg.as_ref().unwrap();
-
- match first_generic_arg {
- GenericArgument::Type(first_generic_arg_type) => {
- Some(first_generic_arg_type.clone())
- }
- &_ => None,
- }
- }
- &_ => None,
- }
- })
+ .filter_map(|arg_type_path| DependencyType::from_type_path(arg_type_path))
.collect())
}
}
diff --git a/macros/src/lib.rs b/macros/src/lib.rs
index d65df68..20eb7d3 100644
--- a/macros/src/lib.rs
+++ b/macros/src/lib.rs
@@ -6,6 +6,7 @@ use quote::quote;
use syn::{parse, parse_macro_input};
mod declare_interface_args;
+mod dependency_type;
mod factory_type_alias;
mod injectable_impl;
mod injectable_macro_args;