1use std::marker::PhantomData;
6use std::sync::Arc;
7
8use crate::core::builder::ModuleBuilder;
9use crate::core::capability::CapabilityKey;
10use crate::core::module::Module;
11
12use crate::kit::error::KitError;
13use crate::kit::kit::Kit;
14
15pub trait IntoKitModuleBuilder<M: Module> {
19 type Builder: ModuleBuilder<M>;
21
22 fn kit(self, kit: &Kit) -> KitModuleBuilder<M, Self::Builder>;
26}
27
28impl<M, B> IntoKitModuleBuilder<M> for B
30where
31 M: Module<Builder = B>,
32 B: ModuleBuilder<M>,
33{
34 type Builder = B;
35
36 fn kit(self, kit: &Kit) -> KitModuleBuilder<M, Self::Builder> {
37 KitModuleBuilder::new(self, kit.clone())
38 }
39}
40
41pub struct KitModuleBuilder<M: Module, B> {
48 builder: B,
49 kit: Kit,
50 _phantom: PhantomData<M>,
51}
52
53impl<M: Module, B: ModuleBuilder<M>> KitModuleBuilder<M, B> {
54 pub fn new(builder: B, kit: Kit) -> Self {
56 KitModuleBuilder {
57 builder,
58 kit,
59 _phantom: PhantomData,
60 }
61 }
62
63 pub fn provide<K>(self) -> Result<Arc<K::Capability>, KitError>
78 where
79 K: CapabilityKey,
80 M: Module<Capability = Arc<K::Capability>>,
81 {
82 let module_name = M::NAME;
83
84 let capability: Arc<K::Capability> =
86 self.builder.build().map_err(|e| KitError::BuildFailed {
87 module: module_name,
88 source: Box::new(e),
89 })?;
90
91 self.kit.provide::<K>(Arc::clone(&capability))?;
93
94 Ok(capability)
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use crate::core::builder::ModuleBuilder;
103 use crate::core::capability::CapabilityKey;
104 use crate::core::module::Module;
105 use std::fmt;
106
107 #[derive(Debug)]
108 struct TestError(&'static str);
109
110 impl fmt::Display for TestError {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 write!(f, "{}", self.0)
113 }
114 }
115
116 impl std::error::Error for TestError {}
117
118 struct TestCapKey;
119 impl CapabilityKey for TestCapKey {
120 type Capability = dyn Send + Sync;
121 const NAME: &'static str = "test_cap";
122 }
123
124 struct TestModule;
125 impl Module for TestModule {
126 const NAME: &'static str = "test_module";
127 type Config = ();
128 type Requirements = ();
129 type Capability = Arc<dyn Send + Sync>;
130 type Error = TestError;
131 type Builder = TestBuilder;
132 }
133
134 struct TestBuilder;
135 impl ModuleBuilder<TestModule> for TestBuilder {
136 fn build(self) -> Result<Arc<dyn Send + Sync>, TestError> {
137 Ok(Arc::new(42i32) as Arc<dyn Send + Sync>)
138 }
139 }
140
141 struct FailingModule;
142 impl Module for FailingModule {
143 const NAME: &'static str = "failing_module";
144 type Config = ();
145 type Requirements = ();
146 type Capability = Arc<dyn Send + Sync>;
147 type Error = TestError;
148 type Builder = FailingBuilder;
149 }
150
151 struct FailingBuilder;
152 impl ModuleBuilder<FailingModule> for FailingBuilder {
153 fn build(self) -> Result<Arc<dyn Send + Sync>, TestError> {
154 Err(TestError("build failed"))
155 }
156 }
157
158 #[test]
159 fn kit_creates_kit_module_builder() {
160 let kit = Kit::new();
161 let kmb = TestBuilder.kit(&kit);
162 let result = kmb.provide::<TestCapKey>();
164 assert!(result.is_ok());
165 assert!(kit.contains::<TestCapKey>());
166 }
167
168 #[test]
169 fn provide_build_failure() {
170 let kit = Kit::new();
171 let result = FailingBuilder.kit(&kit).provide::<TestCapKey>();
172 assert!(result.is_err(), "build should fail");
173 let err = result.err().unwrap();
174 assert!(err.to_string().contains("failed to build module"));
175 assert!(err.to_string().contains("failing_module"));
176 }
177
178 #[test]
179 fn provide_duplicate_failure() {
180 let kit = Kit::new();
181 TestBuilder.kit(&kit).provide::<TestCapKey>().unwrap();
182 let result = TestBuilder.kit(&kit).provide::<TestCapKey>();
183 assert!(result.is_err(), "duplicate should fail");
184 let err = result.err().unwrap();
185 assert!(err.to_string().contains("already exists"));
186 assert!(err.to_string().contains("test_cap"));
187 }
188
189 #[test]
190 fn test_error_display() {
191 let err = TestError("oops");
192 assert_eq!(err.to_string(), "oops");
193 }
194}