Skip to main content

component_map/
sync_infallible.rs

1use crate::{ComponentMap, Keyed, WithArgs};
2
3impl<Key, Args, Comp, FnInit> ComponentMap<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 = ComponentMap::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: ComponentMap<&str, Args, Counter, _> = ComponentMap::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 = ComponentMap::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 = ComponentMap::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: ComponentMap<&str, Args, Counter, _> = ComponentMap::init([], init);
184
185        let results: Vec<_> = manager.reinit_all().collect();
186        assert_eq!(results.len(), 0);
187    }
188
189    #[test]
190    fn test_reinit_existing_key() {
191        let init = |args: &Args| Counter(args.value * 2);
192
193        let mut manager = ComponentMap::init(
194            [("key1", Args { value: 1 }), ("key2", Args { value: 2 })],
195            init,
196        );
197
198        let results: Vec<_> = manager.reinit(["key1"]).collect();
199
200        assert_eq!(results.len(), 1);
201        assert_eq!(results[0].key, "key1");
202        assert_eq!(results[0].value, Some(Counter(2)));
203
204        // key1 should be reinitialized (still 2 since args are still 1)
205        assert_eq!(
206            manager.components().get("key1").unwrap().component,
207            Counter(2)
208        );
209        // key2 should be unchanged
210        assert_eq!(
211            manager.components().get("key2").unwrap().component,
212            Counter(4)
213        );
214    }
215
216    #[test]
217    fn test_reinit_multiple_keys() {
218        let init = |args: &Args| Counter(args.value * 3);
219
220        let mut manager = ComponentMap::init(
221            [
222                ("key1", Args { value: 1 }),
223                ("key2", Args { value: 2 }),
224                ("key3", Args { value: 3 }),
225            ],
226            init,
227        );
228
229        let results: Vec<_> = manager.reinit(["key1", "key3"]).collect();
230
231        assert_eq!(results.len(), 2);
232        assert_eq!(
233            manager.components().get("key1").unwrap().component,
234            Counter(3)
235        );
236        assert_eq!(
237            manager.components().get("key2").unwrap().component,
238            Counter(6)
239        );
240        assert_eq!(
241            manager.components().get("key3").unwrap().component,
242            Counter(9)
243        );
244    }
245
246    #[test]
247    fn test_reinit_nonexistent_key() {
248        let init = |args: &Args| Counter(args.value);
249
250        let mut manager = ComponentMap::init([("key1", Args { value: 1 })], init);
251
252        let results: Vec<_> = manager.reinit(["nonexistent"]).collect();
253
254        assert_eq!(results.len(), 1);
255        assert_eq!(results[0].key, "nonexistent");
256        assert_eq!(results[0].value, None);
257
258        // Original component should be unchanged
259        assert_eq!(manager.components().len(), 1);
260    }
261
262    #[test]
263    fn test_reinit_mixed_existent_and_nonexistent() {
264        let init = |args: &Args| Counter(args.value);
265
266        let mut manager = ComponentMap::init([("key1", Args { value: 1 })], init);
267
268        let results: Vec<_> = manager.reinit(["key1", "nonexistent"]).collect();
269
270        assert_eq!(results.len(), 2);
271        assert!(results[0].value.is_some() || results[1].value.is_some());
272        assert!(results[0].value.is_none() || results[1].value.is_none());
273    }
274
275    #[test]
276    fn test_update_existing_key() {
277        let init = |args: &Args| Counter(args.value);
278
279        let mut manager = ComponentMap::init([("key1", Args { value: 1 })], init);
280
281        let results: Vec<_> = manager.update([("key1", Args { value: 10 })]).collect();
282
283        assert_eq!(results.len(), 1);
284        assert_eq!(results[0].key, "key1");
285        assert!(results[0].value.is_some());
286        assert_eq!(results[0].value.as_ref().unwrap().component, Counter(1));
287        assert_eq!(results[0].value.as_ref().unwrap().args.value, 1);
288
289        // Component should now be updated
290        assert_eq!(
291            manager.components().get("key1").unwrap().component,
292            Counter(10)
293        );
294        assert_eq!(manager.components().get("key1").unwrap().args.value, 10);
295    }
296
297    #[test]
298    fn test_update_new_key() {
299        let init = |args: &Args| Counter(args.value);
300
301        let mut manager = ComponentMap::init([("key1", Args { value: 1 })], init);
302
303        let results: Vec<_> = manager.update([("key2", Args { value: 20 })]).collect();
304
305        assert_eq!(results.len(), 1);
306        assert_eq!(results[0].key, "key2");
307        assert!(results[0].value.is_none());
308
309        // Should now have 2 components
310        assert_eq!(manager.components().len(), 2);
311        assert_eq!(
312            manager.components().get("key2").unwrap().component,
313            Counter(20)
314        );
315    }
316
317    #[test]
318    fn test_update_multiple_keys() {
319        let init = |args: &Args| Counter(args.value);
320
321        let mut manager = ComponentMap::init([("key1", Args { value: 1 })], init);
322
323        let results: Vec<_> = manager
324            .update([
325                ("key1", Args { value: 10 }),
326                ("key2", Args { value: 20 }),
327                ("key3", Args { value: 30 }),
328            ])
329            .collect();
330
331        assert_eq!(results.len(), 3);
332        assert_eq!(manager.components().len(), 3);
333        assert_eq!(
334            manager.components().get("key1").unwrap().component,
335            Counter(10)
336        );
337        assert_eq!(
338            manager.components().get("key2").unwrap().component,
339            Counter(20)
340        );
341        assert_eq!(
342            manager.components().get("key3").unwrap().component,
343            Counter(30)
344        );
345    }
346
347    #[test]
348    fn test_components_accessors() {
349        let init = |args: &Args| Counter(args.value);
350        let mut manager = ComponentMap::init([("key1", Args { value: 1 })], init);
351
352        // Test immutable access
353        assert_eq!(manager.components().len(), 1);
354        assert_eq!(
355            manager.components().get("key1").unwrap().component,
356            Counter(1)
357        );
358
359        // Test mutable access
360        manager.components_mut().get_mut("key1").unwrap().component = Counter(999);
361        assert_eq!(
362            manager.components().get("key1").unwrap().component,
363            Counter(999)
364        );
365    }
366
367    #[test]
368    fn test_fn_init_accessor() {
369        let init = |args: &Args| Counter(args.value * 5);
370        let manager = ComponentMap::init([("key1", Args { value: 1 })], init);
371
372        let fn_init = manager.fn_init();
373        let result = (fn_init)(&Args { value: 10 });
374        assert_eq!(result, Counter(50));
375    }
376}