From 75ca777bbeb618e14b1cf8854ebb37b7a2c884b5 Mon Sep 17 00:00:00 2001
From: HampusM <hampus@hampusmat.com>
Date: Sat, 16 Sep 2023 16:04:47 +0200
Subject: refactor: make castable factory take DI container param

---
 src/private/castable_factory/blocking.rs | 85 +++++++++++++++-----------------
 src/private/factory.rs                   |  9 ++--
 2 files changed, 43 insertions(+), 51 deletions(-)

(limited to 'src/private')

diff --git a/src/private/castable_factory/blocking.rs b/src/private/castable_factory/blocking.rs
index bf0dde8..24c653e 100644
--- a/src/private/castable_factory/blocking.rs
+++ b/src/private/castable_factory/blocking.rs
@@ -1,109 +1,95 @@
 use std::any::type_name;
 use std::fmt::Debug;
-use std::marker::Tuple;
+use std::rc::Rc;
 
 use crate::private::any_factory::AnyFactory;
 use crate::private::factory::IFactory;
 use crate::ptr::TransientPtr;
 
-pub struct CastableFactory<Args, ReturnInterface>
+pub struct CastableFactory<ReturnInterface, DIContainerT>
 where
-    Args: Tuple + 'static,
     ReturnInterface: 'static + ?Sized,
+    DIContainerT: 'static,
 {
-    func: &'static dyn Fn<Args, Output = TransientPtr<ReturnInterface>>,
+    func: &'static dyn Fn<(Rc<DIContainerT>,), Output = TransientPtr<ReturnInterface>>,
 }
 
-impl<Args, ReturnInterface> CastableFactory<Args, ReturnInterface>
+impl<ReturnInterface, DIContainerT> CastableFactory<ReturnInterface, DIContainerT>
 where
-    Args: Tuple + 'static,
     ReturnInterface: 'static + ?Sized,
 {
     pub fn new(
-        func: &'static dyn Fn<Args, Output = TransientPtr<ReturnInterface>>,
+        func: &'static dyn Fn<
+            (Rc<DIContainerT>,),
+            Output = TransientPtr<ReturnInterface>,
+        >,
     ) -> Self
     {
         Self { func }
     }
 }
 
-impl<Args, ReturnInterface> IFactory<Args, ReturnInterface>
-    for CastableFactory<Args, ReturnInterface>
+impl<ReturnInterface, DIContainerT> IFactory<ReturnInterface, DIContainerT>
+    for CastableFactory<ReturnInterface, DIContainerT>
 where
-    Args: Tuple + 'static,
     ReturnInterface: 'static + ?Sized,
 {
 }
 
-impl<Args, ReturnInterface> Fn<Args> for CastableFactory<Args, ReturnInterface>
+impl<ReturnInterface, DIContainerT> Fn<(Rc<DIContainerT>,)>
+    for CastableFactory<ReturnInterface, DIContainerT>
 where
-    Args: Tuple + 'static,
     ReturnInterface: 'static + ?Sized,
 {
-    extern "rust-call" fn call(&self, args: Args) -> Self::Output
+    extern "rust-call" fn call(&self, args: (Rc<DIContainerT>,)) -> Self::Output
     {
         self.func.call(args)
     }
 }
 
-impl<Args, ReturnInterface> FnMut<Args> for CastableFactory<Args, ReturnInterface>
+impl<ReturnInterface, DIContainerT> FnMut<(Rc<DIContainerT>,)>
+    for CastableFactory<ReturnInterface, DIContainerT>
 where
-    Args: Tuple + 'static,
     ReturnInterface: 'static + ?Sized,
 {
-    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output
+    extern "rust-call" fn call_mut(&mut self, args: (Rc<DIContainerT>,)) -> Self::Output
     {
         self.call(args)
     }
 }
 
-impl<Args, ReturnInterface> FnOnce<Args> for CastableFactory<Args, ReturnInterface>
+impl<ReturnInterface, DIContainerT> FnOnce<(Rc<DIContainerT>,)>
+    for CastableFactory<ReturnInterface, DIContainerT>
 where
-    Args: Tuple + 'static,
     ReturnInterface: 'static + ?Sized,
 {
     type Output = TransientPtr<ReturnInterface>;
 
-    extern "rust-call" fn call_once(self, args: Args) -> Self::Output
+    extern "rust-call" fn call_once(self, args: (Rc<DIContainerT>,)) -> Self::Output
     {
         self.call(args)
     }
 }
 
-impl<Args, ReturnInterface> AnyFactory for CastableFactory<Args, ReturnInterface>
+impl<ReturnInterface, DIContainerT> AnyFactory
+    for CastableFactory<ReturnInterface, DIContainerT>
 where
-    Args: Tuple + 'static,
     ReturnInterface: 'static + ?Sized,
+    DIContainerT: 'static,
 {
 }
 
-impl<Args, ReturnInterface> Debug for CastableFactory<Args, ReturnInterface>
+impl<ReturnInterface, DIContainerT> Debug
+    for CastableFactory<ReturnInterface, DIContainerT>
 where
-    Args: Tuple + 'static,
     ReturnInterface: 'static + ?Sized,
 {
     #[cfg(not(tarpaulin_include))]
     fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
     {
-        let mut args = type_name::<Args>();
-
-        if args.len() < 2 {
-            return Err(std::fmt::Error);
-        }
-
-        args = args
-            .get(1..args.len() - 1)
-            .map_or_else(|| Err(std::fmt::Error), Ok)?;
-
-        if args.ends_with(',') {
-            args = args
-                .get(..args.len() - 1)
-                .map_or_else(|| Err(std::fmt::Error), Ok)?;
-        }
-
         let ret = type_name::<TransientPtr<ReturnInterface>>();
 
-        formatter.write_fmt(format_args!("CastableFactory ({args}) -> {ret}"))
+        formatter.write_fmt(format_args!("CastableFactory (Rc<DIContainer>) -> {ret}"))
     }
 }
 
@@ -111,6 +97,7 @@ where
 mod tests
 {
     use super::*;
+    use crate::di_container::blocking::MockDIContainer;
 
     #[derive(Debug, PartialEq, Eq)]
     struct Bacon
@@ -122,9 +109,11 @@ mod tests
     fn can_call()
     {
         let castable_factory =
-            CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount }));
+            CastableFactory::new(&|_| TransientPtr::new(Bacon { heal_amount: 27 }));
 
-        let output = castable_factory.call((27,));
+        let mock_di_container = Rc::new(MockDIContainer::new());
+
+        let output = castable_factory.call((mock_di_container,));
 
         assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 }));
     }
@@ -133,9 +122,11 @@ mod tests
     fn can_call_mut()
     {
         let mut castable_factory =
-            CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount }));
+            CastableFactory::new(&|_| TransientPtr::new(Bacon { heal_amount: 103 }));
+
+        let mock_di_container = Rc::new(MockDIContainer::new());
 
-        let output = castable_factory.call_mut((103,));
+        let output = castable_factory.call_mut((mock_di_container,));
 
         assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 103 }));
     }
@@ -144,9 +135,11 @@ mod tests
     fn can_call_once()
     {
         let castable_factory =
-            CastableFactory::new(&|heal_amount| TransientPtr::new(Bacon { heal_amount }));
+            CastableFactory::new(&|_| TransientPtr::new(Bacon { heal_amount: 19 }));
+
+        let mock_di_container = Rc::new(MockDIContainer::new());
 
-        let output = castable_factory.call_once((19,));
+        let output = castable_factory.call_once((mock_di_container,));
 
         assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 19 }));
     }
diff --git a/src/private/factory.rs b/src/private/factory.rs
index 84b00c6..af6df8a 100644
--- a/src/private/factory.rs
+++ b/src/private/factory.rs
@@ -1,13 +1,12 @@
-use std::marker::Tuple;
+use std::rc::Rc;
 
 use crate::private::cast::CastFrom;
 use crate::ptr::TransientPtr;
 
 /// Interface for a factory.
-pub trait IFactory<Args, ReturnInterface>:
-    Fn<Args, Output = TransientPtr<ReturnInterface>> + CastFrom
+pub trait IFactory<ReturnInterface, DIContainerT>:
+    Fn<(Rc<DIContainerT>,), Output = TransientPtr<ReturnInterface>> + CastFrom
 where
-    Args: Tuple,
     ReturnInterface: 'static + ?Sized,
 {
 }
@@ -17,7 +16,7 @@ where
 pub trait IThreadsafeFactory<Args, ReturnInterface>:
     Fn<Args, Output = TransientPtr<ReturnInterface>> + crate::private::cast::CastFromArc
 where
-    Args: Tuple,
+    Args: std::marker::Tuple,
     ReturnInterface: 'static + ?Sized,
 {
 }
-- 
cgit v1.2.3-18-g5258