Skip to main content

component_map/
sync_infallible.rs

1use crate::{ComponentManager, Keyed, WithArgs};
2
3impl<Key, Args, Comp, FnInit> ComponentManager<Key, Args, Comp, FnInit> {
4    pub fn init(args: impl IntoIterator<Item = (Key, Args)>, init: FnInit) -> Self
5    where
6        Key: Eq + std::hash::Hash,
7        FnInit: Fn(&Args) -> Comp,
8    {
9        let map = args
10            .into_iter()
11            .map(|(key, args)| {
12                (
13                    key,
14                    WithArgs {
15                        component: (init)(&args),
16                        args,
17                    },
18                )
19            })
20            .collect();
21
22        Self { map, init }
23    }
24
25    pub fn reinit_all(&mut self) -> impl Iterator<Item = Keyed<&Key, Comp>>
26    where
27        FnInit: Fn(&Args) -> Comp,
28    {
29        self.map.iter_mut().map(|(key, component)| {
30            let next = (self.init)(&component.args);
31            let prev = std::mem::replace(&mut component.component, next);
32            Keyed::new(key, prev)
33        })
34    }
35
36    pub fn reinit(
37        &mut self,
38        keys: impl IntoIterator<Item = Key>,
39    ) -> impl Iterator<Item = Keyed<Key, Option<Comp>>>
40    where
41        Key: Eq + std::hash::Hash,
42        FnInit: Fn(&Args) -> Comp,
43    {
44        keys.into_iter().map(|key| {
45            let prev = self.map.get_mut(&key).map(|component| {
46                let next = (self.init)(&component.args);
47                std::mem::replace(&mut component.component, next)
48            });
49
50            Keyed::new(key, prev)
51        })
52    }
53
54    pub fn update(
55        &mut self,
56        updates: impl IntoIterator<Item = (Key, Args)>,
57    ) -> impl Iterator<Item = Keyed<Key, Option<WithArgs<Args, Comp>>>>
58    where
59        Key: Clone + Eq + std::hash::Hash,
60        FnInit: Fn(&Args) -> Comp,
61    {
62        updates.into_iter().map(move |(key, args)| {
63            let prev = self.map.insert(
64                key.clone(),
65                WithArgs {
66                    component: (self.init)(&args),
67                    args,
68                },
69            );
70
71            Keyed::new(key, prev)
72        })
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79    use std::sync::{Arc, Mutex};
80
81    #[derive(Debug, Clone, PartialEq, Eq)]
82    struct Counter(usize);
83
84    #[derive(Debug, Clone, PartialEq, Eq)]
85    struct Args {
86        value: usize,
87    }
88
89    #[test]
90    fn test_init() {
91        let init = |args: &Args| Counter(args.value);
92        let manager = ComponentManager::init(
93            [("key1", Args { value: 1 }), ("key2", Args { value: 2 })],
94            init,
95        );
96
97        assert_eq!(manager.components().len(), 2);
98        assert_eq!(
99            manager.components().get("key1").unwrap().component,
100            Counter(1)
101        );
102        assert_eq!(
103            manager.components().get("key2").unwrap().component,
104            Counter(2)
105        );
106        assert_eq!(manager.components().get("key1").unwrap().args.value, 1);
107    }
108
109    #[test]
110    fn test_init_empty() {
111        let init = |args: &Args| Counter(args.value);
112        let manager: ComponentManager<&str, Args, Counter, _> = ComponentManager::init([], init);
113
114        assert_eq!(manager.components().len(), 0);
115    }
116
117    #[test]
118    fn test_init_multiple_components() {
119        let init = |args: &Args| Counter(args.value * 10);
120        let manager = ComponentManager::init(
121            [
122                ("a", Args { value: 1 }),
123                ("b", Args { value: 2 }),
124                ("c", Args { value: 3 }),
125                ("d", Args { value: 4 }),
126            ],
127            init,
128        );
129
130        assert_eq!(manager.components().len(), 4);
131        assert_eq!(
132            manager.components().get("a").unwrap().component,
133            Counter(10)
134        );
135        assert_eq!(
136            manager.components().get("d").unwrap().component,
137            Counter(40)
138        );
139    }
140
141    #[test]
142    fn test_reinit_all() {
143        let call_count = Arc::new(Mutex::new(0));
144        let call_count_clone = call_count.clone();
145
146        let init = move |args: &Args| {
147            *call_count_clone.lock().unwrap() += 1;
148            Counter(args.value * 2)
149        };
150
151        let mut manager = ComponentManager::init(
152            [("key1", Args { value: 1 }), ("key2", Args { value: 2 })],
153            init,
154        );
155
156        // Collect to force evaluation
157        let prev_components: Vec<_> = manager.reinit_all().collect();
158
159        assert_eq!(prev_components.len(), 2);
160
161        // Previous components should be the original values
162        let prev_values: Vec<_> = prev_components.iter().map(|k| &k.value.0).collect();
163        assert!(prev_values.contains(&&2));
164        assert!(prev_values.contains(&&4));
165
166        // Components should now have doubled values (checked after prev_components is used)
167        assert_eq!(
168            manager.components().get("key1").unwrap().component,
169            Counter(2)
170        );
171        assert_eq!(
172            manager.components().get("key2").unwrap().component,
173            Counter(4)
174        );
175
176        // Should have called init 4 times (2 for init, 2 for reinit_all)
177        assert_eq!(*call_count.lock().unwrap(), 4);
178    }
179
180    #[test]
181    fn test_reinit_all_empty() {
182        let init = |args: &Args| Counter(args.value);
183        let mut manager: ComponentManager<&str, Args, Counter, _> =
184            ComponentManager::init([], init);
185
186        let results: Vec<_> = manager.reinit_all().collect();
187        assert_eq!(results.len(), 0);
188    }
189
190    #[test]
191    fn test_reinit_existing_key() {
192        let init = |args: &Args| Counter(args.value * 2);
193
194        let mut manager = ComponentManager::init(
195            [("key1", Args { value: 1 }), ("key2", Args { value: 2 })],
196            init,
197        );
198
199        let results: Vec<_> = manager.reinit(["key1"]).collect();
200
201        assert_eq!(results.len(), 1);
202        assert_eq!(results[0].key, "key1");
203        assert_eq!(results[0].value, Some(Counter(2)));
204
205        // key1 should be reinitialized (still 2 since args are still 1)
206        assert_eq!(
207            manager.components().get("key1").unwrap().component,
208            Counter(2)
209        );
210        // key2 should be unchanged
211        assert_eq!(
212            manager.components().get("key2").unwrap().component,
213            Counter(4)
214        );
215    }
216
217    #[test]
218    fn test_reinit_multiple_keys() {
219        let init = |args: &Args| Counter(args.value * 3);
220
221        let mut manager = ComponentManager::init(
222            [
223                ("key1", Args { value: 1 }),
224                ("key2", Args { value: 2 }),
225                ("key3", Args { value: 3 }),
226            ],
227            init,
228        );
229
230        let results: Vec<_> = manager.reinit(["key1", "key3"]).collect();
231
232        assert_eq!(results.len(), 2);
233        assert_eq!(
234            manager.components().get("key1").unwrap().component,
235            Counter(3)
236        );
237        assert_eq!(
238            manager.components().get("key2").unwrap().component,
239            Counter(6)
240        );
241        assert_eq!(
242            manager.components().get("key3").unwrap().component,
243            Counter(9)
244        );
245    }
246
247    #[test]
248    fn test_reinit_nonexistent_key() {
249        let init = |args: &Args| Counter(args.value);
250
251        let mut manager = ComponentManager::init([("key1", Args { value: 1 })], init);
252
253        let results: Vec<_> = manager.reinit(["nonexistent"]).collect();
254
255        assert_eq!(results.len(), 1);
256        assert_eq!(results[0].key, "nonexistent");
257        assert_eq!(results[0].value, None);
258
259        // Original component should be unchanged
260        assert_eq!(manager.components().len(), 1);
261    }
262
263    #[test]
264    fn test_reinit_mixed_existent_and_nonexistent() {
265        let init = |args: &Args| Counter(args.value);
266
267        let mut manager = ComponentManager::init([("key1", Args { value: 1 })], init);
268
269        let results: Vec<_> = manager.reinit(["key1", "nonexistent"]).collect();
270
271        assert_eq!(results.len(), 2);
272        assert!(results[0].value.is_some() || results[1].value.is_some());
273        assert!(results[0].value.is_none() || results[1].value.is_none());
274    }
275
276    #[test]
277    fn test_update_existing_key() {
278        let init = |args: &Args| Counter(args.value);
279
280        let mut manager = ComponentManager::init([("key1", Args { value: 1 })], init);
281
282        let results: Vec<_> = manager.update([("key1", Args { value: 10 })]).collect();
283
284        assert_eq!(results.len(), 1);
285        assert_eq!(results[0].key, "key1");
286        assert!(results[0].value.is_some());
287        assert_eq!(results[0].value.as_ref().unwrap().component, Counter(1));
288        assert_eq!(results[0].value.as_ref().unwrap().args.value, 1);
289
290        // Component should now be updated
291        assert_eq!(
292            manager.components().get("key1").unwrap().component,
293            Counter(10)
294        );
295        assert_eq!(manager.components().get("key1").unwrap().args.value, 10);
296    }
297
298    #[test]
299    fn test_update_new_key() {
300        let init = |args: &Args| Counter(args.value);
301
302        let mut manager = ComponentManager::init([("key1", Args { value: 1 })], init);
303
304        let results: Vec<_> = manager.update([("key2", Args { value: 20 })]).collect();
305
306        assert_eq!(results.len(), 1);
307        assert_eq!(results[0].key, "key2");
308        assert!(results[0].value.is_none());
309
310        // Should now have 2 components
311        assert_eq!(manager.components().len(), 2);
312        assert_eq!(
313            manager.components().get("key2").unwrap().component,
314            Counter(20)
315        );
316    }
317
318    #[test]
319    fn test_update_multiple_keys() {
320        let init = |args: &Args| Counter(args.value);
321
322        let mut manager = ComponentManager::init([("key1", Args { value: 1 })], init);
323
324        let results: Vec<_> = manager
325            .update([
326                ("key1", Args { value: 10 }),
327                ("key2", Args { value: 20 }),
328                ("key3", Args { value: 30 }),
329            ])
330            .collect();
331
332        assert_eq!(results.len(), 3);
333        assert_eq!(manager.components().len(), 3);
334        assert_eq!(
335            manager.components().get("key1").unwrap().component,
336            Counter(10)
337        );
338        assert_eq!(
339            manager.components().get("key2").unwrap().component,
340            Counter(20)
341        );
342        assert_eq!(
343            manager.components().get("key3").unwrap().component,
344            Counter(30)
345        );
346    }
347
348    #[test]
349    fn test_components_accessors() {
350        let init = |args: &Args| Counter(args.value);
351        let mut manager = ComponentManager::init([("key1", Args { value: 1 })], init);
352
353        // Test immutable access
354        assert_eq!(manager.components().len(), 1);
355        assert_eq!(
356            manager.components().get("key1").unwrap().component,
357            Counter(1)
358        );
359
360        // Test mutable access
361        manager.components_mut().get_mut("key1").unwrap().component = Counter(999);
362        assert_eq!(
363            manager.components().get("key1").unwrap().component,
364            Counter(999)
365        );
366    }
367
368    #[test]
369    fn test_fn_init_accessor() {
370        let init = |args: &Args| Counter(args.value * 5);
371        let manager = ComponentManager::init([("key1", Args { value: 1 })], init);
372
373        let fn_init = manager.fn_init();
374        let result = (fn_init)(&Args { value: 10 });
375        assert_eq!(result, Counter(50));
376    }
377}