1use std::borrow::Borrow;
30use std::sync::{Mutex, MutexGuard};
31
32pub use service_provider::ServiceProvider;
33
34use crate::service_provider_extensions::ServiceProviderExtensions;
35
36pub mod service_provider;
37pub mod service_provider_extensions;
38
39#[derive(Debug, thiserror::Error, PartialEq)]
40pub enum Error {
41 #[error("InjectLookupError({0})")]
42 InjectLookupError(String),
43}
44
45#[derive(Default)]
46pub struct Container {
47 extensions: Mutex<ServiceProviderExtensions>,
48}
49
50impl Container {
51 pub fn new() -> Self {
52 Self::default()
53 }
54}
55
56impl ServiceProvider for Container {
57 fn extensions(&self) -> MutexGuard<'_, ServiceProviderExtensions> {
58 self.extensions.borrow().lock().unwrap()
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use std::borrow::Borrow;
65 use std::sync::{Arc, Mutex, MutexGuard};
66
67 use totems::assert_err;
68
69 use crate::{Container, ServiceProvider, ServiceProviderExtensions};
70
71 pub trait Animal {
72 fn make_sound(&self);
73 }
74
75 #[derive(Clone)]
76 struct Dog;
77
78 impl Animal for Dog {
79 fn make_sound(&self) {
80 println!("woof woof!")
81 }
82 }
83
84 #[test]
85 fn test_dependency_is_injected() {
86 let mut container = Container::new();
87 let animal: Arc<dyn Animal + Sync + Send> = Arc::new(Dog);
88 container.inject(animal.clone());
89
90 let animal2 = container.find::<Arc<dyn Animal + Sync + Send>>();
91
92 assert!(animal2.is_ok())
93 }
94
95 #[derive(Default)]
96 struct ServiceProviderStub {
97 extensions: Mutex<ServiceProviderExtensions>,
98 }
99
100 impl ServiceProvider for ServiceProviderStub {
101 fn extensions(&self) -> MutexGuard<'_, ServiceProviderExtensions> {
102 self.extensions.borrow().lock().unwrap()
103 }
104 }
105
106 #[test]
107 fn empty_service_provider() {
108 let sp = ServiceProviderStub::default();
109
110 assert_err!(sp.find::<String>());
111 assert_err!(sp.find::<Arc<String>>());
112 }
113
114 #[test]
115 fn value_is_injected_by_type_not_by_value() {
116 let mut sp = ServiceProviderStub::default();
117 sp.inject("String".to_string());
118 sp.inject("Ae".to_string());
119
120 assert_eq!(sp.count(), 1);
121 assert_ne!(*sp.find::<String>().unwrap(), "String".to_string());
122 assert_eq!(*sp.find::<String>().unwrap(), "Ae".to_string());
123 }
124
125 #[test]
126 fn inject_arc() {
127 struct MyStub {}
128 let mut sp = ServiceProviderStub::default();
129 sp.inject(Arc::new(MyStub {}));
130
131 assert!(sp.find::<Arc<MyStub>>().is_ok());
132 }
133}