From 20d37eb93060e51970d3791c6c173e07ef5ad489 Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 11 Jul 2024 21:00:09 +0200 Subject: refactor: rename castable factory to castable function --- src/castable_function/mod.rs | 93 ++++++++++++++++++++++++++++++++ src/castable_function/threadsafe.rs | 105 ++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 src/castable_function/mod.rs create mode 100644 src/castable_function/threadsafe.rs (limited to 'src/castable_function') diff --git a/src/castable_function/mod.rs b/src/castable_function/mod.rs new file mode 100644 index 0000000..4c2f0db --- /dev/null +++ b/src/castable_function/mod.rs @@ -0,0 +1,93 @@ +use std::any::{type_name, Any}; +use std::fmt::Debug; + +use crate::ptr::TransientPtr; + +#[cfg(feature = "async")] +pub mod threadsafe; + +/// Interface for any castable function. +pub trait AnyCastableFunction: Any + Debug +{ + fn as_any(&self) -> &dyn Any; +} + +pub struct CastableFunction +where + ReturnInterface: 'static + ?Sized, + DIContainerT: 'static, +{ + func: &'static dyn Fn(&DIContainerT) -> TransientPtr, +} + +impl CastableFunction +where + ReturnInterface: 'static + ?Sized, +{ + pub fn new( + func: &'static dyn Fn(&DIContainerT) -> TransientPtr, + ) -> Self + { + Self { func } + } + + pub fn call(&self, di_container: &DIContainerT) -> TransientPtr + { + (self.func)(di_container) + } +} + +impl AnyCastableFunction + for CastableFunction +where + ReturnInterface: 'static + ?Sized, + DIContainerT: 'static, +{ + fn as_any(&self) -> &dyn Any + { + self + } +} + +impl Debug + for CastableFunction +where + ReturnInterface: 'static + ?Sized, +{ + #[cfg(not(tarpaulin_include))] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + let ret = type_name::>(); + + formatter.write_fmt(format_args!( + "CastableFunction (&DIContainer) -> {ret} {{ ... }}" + )) + } +} + +#[cfg(test)] +mod tests +{ + use super::*; + use crate::di_container::blocking::MockDIContainer; + + #[derive(Debug, PartialEq, Eq)] + struct Bacon + { + heal_amount: u32, + } + + #[test] + fn can_call() + { + let castable_func = CastableFunction::new(&|_: &MockDIContainer| { + TransientPtr::new(Bacon { heal_amount: 27 }) + }); + + let mock_di_container = MockDIContainer::new(); + + let output = castable_func.call(&mock_di_container); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); + } +} diff --git a/src/castable_function/threadsafe.rs b/src/castable_function/threadsafe.rs new file mode 100644 index 0000000..7543396 --- /dev/null +++ b/src/castable_function/threadsafe.rs @@ -0,0 +1,105 @@ +use std::any::{type_name, Any}; +use std::fmt::Debug; + +use crate::castable_function::AnyCastableFunction; +use crate::ptr::TransientPtr; + +/// Interface for any threadsafe castable function. +pub trait AnyThreadsafeCastableFunction: + AnyCastableFunction + Send + Sync + Debug +{ +} + +pub struct ThreadsafeCastableFunction +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ + func: &'static (dyn Fn(&DIContainerT) -> TransientPtr + Send + Sync), +} + +impl + ThreadsafeCastableFunction +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ + pub fn new( + func: &'static (dyn Fn(&DIContainerT) -> TransientPtr + + Send + + Sync), + ) -> Self + { + Self { func } + } + + pub fn call(&self, di_container: &DIContainerT) -> TransientPtr + { + (self.func)(di_container) + } +} + +impl AnyCastableFunction + for ThreadsafeCastableFunction +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ + fn as_any(&self) -> &dyn Any + { + self + } +} + +impl AnyThreadsafeCastableFunction + for ThreadsafeCastableFunction +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ +} + +impl Debug + for ThreadsafeCastableFunction +where + DIContainerT: 'static, + ReturnInterface: 'static + ?Sized, +{ + #[cfg(not(tarpaulin_include))] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + let ret = type_name::>(); + + formatter.write_fmt(format_args!( + "ThreadsafeCastableFunction(&AsyncDIContainer) -> {ret} {{ ... }}", + )) + } +} + +#[cfg(test)] +mod tests +{ + use super::*; + use crate::di_container::asynchronous::MockAsyncDIContainer; + + #[derive(Debug, PartialEq, Eq)] + struct Bacon + { + heal_amount: u32, + } + + #[test] + fn can_call() + { + let castable_function = + ThreadsafeCastableFunction::new(&|_: &MockAsyncDIContainer| { + TransientPtr::new(Bacon { heal_amount: 27 }) + }); + + let mock_di_container = MockAsyncDIContainer::new(); + + let output = castable_function.call(&mock_di_container); + + assert_eq!(output, TransientPtr::new(Bacon { heal_amount: 27 })); + } +} -- cgit v1.2.3-18-g5258