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