1use crate::{ComponentManager, Keyed, WithArgs};
2
3impl<Key, Args, Comp, FnInit> ComponentManager<Key, Args, Comp, FnInit> {
4 pub fn try_init<Error>(
5 args: impl IntoIterator<Item = (Key, Args)>,
6 init: FnInit,
7 ) -> Result<Self, Error>
8 where
9 Key: Eq + std::hash::Hash,
10 FnInit: Fn(&Args) -> Result<Comp, Error>,
11 {
12 let map = args
13 .into_iter()
14 .map(|(key, args)| {
15 let component = (init)(&args)?;
16 Ok((key, WithArgs { component, args }))
17 })
18 .collect::<Result<_, _>>()?;
19
20 Ok(Self { map, init })
21 }
22
23 pub fn try_reinit_all<Error>(
24 &mut self,
25 ) -> impl Iterator<Item = Keyed<&Key, Result<Comp, Error>>>
26 where
27 FnInit: Fn(&Args) -> Result<Comp, Error>,
28 {
29 self.map.iter_mut().map(|(key, component)| {
30 let result = (self.init)(&component.args)
31 .map(|next| std::mem::replace(&mut component.component, next));
32
33 Keyed::new(key, result)
34 })
35 }
36
37 pub fn try_reinit<Error>(
38 &mut self,
39 keys: impl IntoIterator<Item = Key>,
40 ) -> impl Iterator<Item = Keyed<Key, Option<Result<Comp, Error>>>>
41 where
42 Key: Eq + std::hash::Hash,
43 FnInit: Fn(&Args) -> Result<Comp, Error>,
44 {
45 keys.into_iter().map(|key| {
46 let prev = self.map.get_mut(&key).map(|component| {
47 (self.init)(&component.args)
48 .map(|next| std::mem::replace(&mut component.component, next))
49 });
50
51 Keyed::new(key, prev)
52 })
53 }
54
55 pub fn try_update<Error>(
56 &mut self,
57 updates: impl IntoIterator<Item = (Key, Args)>,
58 ) -> impl Iterator<Item = Keyed<Key, Option<Result<WithArgs<Args, Comp>, Error>>>>
59 where
60 Key: Clone + Eq + std::hash::Hash,
61 FnInit: Fn(&Args) -> Result<Comp, Error>,
62 {
63 updates.into_iter().map(move |(key, args)| {
64 let result = (self.init)(&args)
65 .map(|component| self.map.insert(key.clone(), WithArgs { component, args }));
66
67 Keyed::new(key, result.transpose())
68 })
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75 use std::sync::{Arc, Mutex};
76
77 #[derive(Debug, Clone, PartialEq, Eq)]
78 struct Counter(usize);
79
80 #[derive(Debug, Clone, PartialEq, Eq)]
81 struct FailArgs {
82 value: usize,
83 should_fail: bool,
84 }
85
86 #[derive(Debug, PartialEq, Eq)]
87 struct TestError(String);
88
89 #[test]
90 fn test_try_init_success() {
91 let init = |args: &FailArgs| -> Result<Counter, TestError> {
92 if args.should_fail {
93 Err(TestError("Failed".to_string()))
94 } else {
95 Ok(Counter(args.value))
96 }
97 };
98
99 let result = ComponentManager::try_init(
100 [
101 (
102 "key1",
103 FailArgs {
104 value: 1,
105 should_fail: false,
106 },
107 ),
108 (
109 "key2",
110 FailArgs {
111 value: 2,
112 should_fail: false,
113 },
114 ),
115 ],
116 init,
117 );
118
119 assert!(result.is_ok());
120 let manager = result.unwrap();
121 assert_eq!(manager.components().len(), 2);
122 assert_eq!(
123 manager.components().get("key1").unwrap().component,
124 Counter(1)
125 );
126 assert_eq!(
127 manager.components().get("key2").unwrap().component,
128 Counter(2)
129 );
130 }
131
132 #[test]
133 fn test_try_init_failure() {
134 let init = |args: &FailArgs| -> Result<Counter, TestError> {
135 if args.should_fail {
136 Err(TestError("Failed".to_string()))
137 } else {
138 Ok(Counter(args.value))
139 }
140 };
141
142 let result = ComponentManager::try_init(
143 [
144 (
145 "key1",
146 FailArgs {
147 value: 1,
148 should_fail: false,
149 },
150 ),
151 (
152 "key2",
153 FailArgs {
154 value: 2,
155 should_fail: true,
156 },
157 ),
158 ],
159 init,
160 );
161
162 assert!(result.is_err());
163 assert_eq!(result.err().unwrap(), TestError("Failed".to_string()));
164 }
165
166 #[test]
167 fn test_try_init_empty() {
168 let init = |args: &FailArgs| -> Result<Counter, TestError> {
169 if args.should_fail {
170 Err(TestError("Failed".to_string()))
171 } else {
172 Ok(Counter(args.value))
173 }
174 };
175
176 let result: Result<ComponentManager<&str, FailArgs, Counter, _>, TestError> =
177 ComponentManager::try_init([], init);
178
179 assert!(result.is_ok());
180 assert_eq!(result.unwrap().components().len(), 0);
181 }
182
183 #[test]
184 fn test_try_init_all_fail() {
185 let init = |args: &FailArgs| -> Result<Counter, TestError> {
186 if args.should_fail {
187 Err(TestError("Failed".to_string()))
188 } else {
189 Ok(Counter(args.value))
190 }
191 };
192
193 let result = ComponentManager::try_init(
194 [
195 (
196 "key1",
197 FailArgs {
198 value: 1,
199 should_fail: true,
200 },
201 ),
202 (
203 "key2",
204 FailArgs {
205 value: 2,
206 should_fail: true,
207 },
208 ),
209 ],
210 init,
211 );
212
213 assert!(result.is_err());
214 }
215
216 #[test]
217 fn test_try_reinit_all_success() {
218 let init = |args: &FailArgs| -> Result<Counter, TestError> {
219 if args.should_fail {
220 Err(TestError("Failed".to_string()))
221 } else {
222 Ok(Counter(args.value * 2))
223 }
224 };
225
226 let mut manager = ComponentManager::try_init(
227 [
228 (
229 "key1",
230 FailArgs {
231 value: 1,
232 should_fail: false,
233 },
234 ),
235 (
236 "key2",
237 FailArgs {
238 value: 2,
239 should_fail: false,
240 },
241 ),
242 ],
243 init,
244 )
245 .unwrap();
246
247 let results: Vec<_> = manager.try_reinit_all().collect();
248
249 assert_eq!(results.len(), 2);
250 assert!(results.iter().all(|r| r.value.is_ok()));
251
252 assert_eq!(
254 manager.components().get("key1").unwrap().component,
255 Counter(2)
256 );
257 assert_eq!(
258 manager.components().get("key2").unwrap().component,
259 Counter(4)
260 );
261 }
262
263 #[test]
264 fn test_try_reinit_all_with_failure() {
265 let call_count = Arc::new(Mutex::new(0));
266 let call_count_clone = call_count.clone();
267
268 let init = move |args: &FailArgs| -> Result<Counter, TestError> {
269 let count = *call_count_clone.lock().unwrap();
270 *call_count_clone.lock().unwrap() += 1;
271
272 if count >= 2 && args.should_fail {
274 Err(TestError("Failed on reinit".to_string()))
275 } else {
276 Ok(Counter(args.value * 2))
277 }
278 };
279
280 let mut manager = ComponentManager::try_init(
281 [
282 (
283 "key1",
284 FailArgs {
285 value: 1,
286 should_fail: false,
287 },
288 ),
289 (
290 "key2",
291 FailArgs {
292 value: 2,
293 should_fail: true,
294 },
295 ),
296 ],
297 init,
298 )
299 .unwrap();
300
301 let results: Vec<_> = manager.try_reinit_all().collect();
302
303 assert_eq!(results.len(), 2);
304 let failures: Vec<_> = results.iter().filter(|r| r.value.is_err()).collect();
305 assert_eq!(failures.len(), 1);
306 let successes: Vec<_> = results.iter().filter(|r| r.value.is_ok()).collect();
307 assert_eq!(successes.len(), 1);
308 }
309
310 #[test]
311 fn test_try_reinit_all_preserves_on_error() {
312 let init = |args: &FailArgs| -> Result<Counter, TestError> {
313 if args.should_fail {
314 Err(TestError("Failed".to_string()))
315 } else {
316 Ok(Counter(args.value * 2))
317 }
318 };
319
320 let mut manager = ComponentManager::try_init(
321 [(
322 "key1",
323 FailArgs {
324 value: 1,
325 should_fail: false,
326 },
327 )],
328 init,
329 )
330 .unwrap();
331
332 manager
334 .components_mut()
335 .get_mut("key1")
336 .unwrap()
337 .args
338 .should_fail = true;
339
340 let original_value = manager.components().get("key1").unwrap().component.clone();
341 let _results: Vec<_> = manager.try_reinit_all().collect();
342
343 assert_eq!(
345 manager.components().get("key1").unwrap().component,
346 original_value
347 );
348 }
349
350 #[test]
351 fn test_try_reinit_specific_keys_success() {
352 let init = |args: &FailArgs| -> Result<Counter, TestError> {
353 if args.should_fail {
354 Err(TestError("Failed".to_string()))
355 } else {
356 Ok(Counter(args.value * 3))
357 }
358 };
359
360 let mut manager = ComponentManager::try_init(
361 [
362 (
363 "key1",
364 FailArgs {
365 value: 1,
366 should_fail: false,
367 },
368 ),
369 (
370 "key2",
371 FailArgs {
372 value: 2,
373 should_fail: false,
374 },
375 ),
376 ],
377 init,
378 )
379 .unwrap();
380
381 let results: Vec<_> = manager.try_reinit(["key1"]).collect();
382
383 assert_eq!(results.len(), 1);
384 assert!(results[0].value.as_ref().unwrap().is_ok());
385 assert_eq!(
386 manager.components().get("key1").unwrap().component,
387 Counter(3)
388 );
389 assert_eq!(
391 manager.components().get("key2").unwrap().component,
392 Counter(6)
393 );
394 }
395
396 #[test]
397 fn test_try_reinit_nonexistent_key() {
398 let init = |args: &FailArgs| -> Result<Counter, TestError> {
399 if args.should_fail {
400 Err(TestError("Failed".to_string()))
401 } else {
402 Ok(Counter(args.value))
403 }
404 };
405
406 let mut manager = ComponentManager::try_init(
407 [(
408 "key1",
409 FailArgs {
410 value: 1,
411 should_fail: false,
412 },
413 )],
414 init,
415 )
416 .unwrap();
417
418 let results: Vec<_> = manager.try_reinit(["nonexistent"]).collect();
419
420 assert_eq!(results.len(), 1);
421 assert_eq!(results[0].key, "nonexistent");
422 assert!(results[0].value.is_none());
423 }
424
425 #[test]
426 fn test_try_reinit_with_failure() {
427 let init = |args: &FailArgs| -> Result<Counter, TestError> {
428 if args.should_fail {
429 Err(TestError("Failed".to_string()))
430 } else {
431 Ok(Counter(args.value))
432 }
433 };
434
435 let mut manager = ComponentManager::try_init(
436 [(
437 "key1",
438 FailArgs {
439 value: 1,
440 should_fail: false,
441 },
442 )],
443 init,
444 )
445 .unwrap();
446
447 manager
449 .components_mut()
450 .get_mut("key1")
451 .unwrap()
452 .args
453 .should_fail = true;
454
455 let results: Vec<_> = manager.try_reinit(["key1"]).collect();
456
457 assert_eq!(results.len(), 1);
458 assert!(results[0].value.as_ref().unwrap().is_err());
459 }
460
461 #[test]
462 fn test_try_update_new_key_success() {
463 let init = |args: &FailArgs| -> Result<Counter, TestError> {
464 if args.should_fail {
465 Err(TestError("Failed".to_string()))
466 } else {
467 Ok(Counter(args.value))
468 }
469 };
470
471 let mut manager = ComponentManager::try_init(
472 [(
473 "key1",
474 FailArgs {
475 value: 1,
476 should_fail: false,
477 },
478 )],
479 init,
480 )
481 .unwrap();
482
483 let results: Vec<_> = manager
484 .try_update([(
485 "key2",
486 FailArgs {
487 value: 20,
488 should_fail: false,
489 },
490 )])
491 .collect();
492
493 assert_eq!(results.len(), 1);
494 assert!(results[0].value.is_none());
495 assert_eq!(manager.components().len(), 2);
496 assert_eq!(
497 manager.components().get("key2").unwrap().component,
498 Counter(20)
499 );
500 }
501
502 #[test]
503 fn test_try_update_existing_key_success() {
504 let init = |args: &FailArgs| -> Result<Counter, TestError> {
505 if args.should_fail {
506 Err(TestError("Failed".to_string()))
507 } else {
508 Ok(Counter(args.value))
509 }
510 };
511
512 let mut manager = ComponentManager::try_init(
513 [(
514 "key1",
515 FailArgs {
516 value: 1,
517 should_fail: false,
518 },
519 )],
520 init,
521 )
522 .unwrap();
523
524 let results: Vec<_> = manager
525 .try_update([(
526 "key1",
527 FailArgs {
528 value: 10,
529 should_fail: false,
530 },
531 )])
532 .collect();
533
534 assert_eq!(results.len(), 1);
535 assert!(results[0].value.is_some());
536 let prev = results[0].value.as_ref().unwrap().as_ref().unwrap();
537 assert_eq!(prev.component, Counter(1));
538
539 assert_eq!(
540 manager.components().get("key1").unwrap().component,
541 Counter(10)
542 );
543 }
544
545 #[test]
546 fn test_try_update_failure() {
547 let init = |args: &FailArgs| -> Result<Counter, TestError> {
548 if args.should_fail {
549 Err(TestError("Failed".to_string()))
550 } else {
551 Ok(Counter(args.value))
552 }
553 };
554
555 let mut manager = ComponentManager::try_init(
556 [(
557 "key1",
558 FailArgs {
559 value: 1,
560 should_fail: false,
561 },
562 )],
563 init,
564 )
565 .unwrap();
566
567 let results: Vec<_> = manager
568 .try_update([(
569 "key2",
570 FailArgs {
571 value: 20,
572 should_fail: true,
573 },
574 )])
575 .collect();
576
577 assert_eq!(results.len(), 1);
578 assert!(results[0].value.is_some());
579 assert!(results[0].value.as_ref().unwrap().is_err());
580
581 assert_eq!(manager.components().len(), 1);
583 assert!(manager.components().get("key2").is_none());
584 }
585
586 #[test]
587 fn test_try_update_multiple_mixed() {
588 let init = |args: &FailArgs| -> Result<Counter, TestError> {
589 if args.should_fail {
590 Err(TestError("Failed".to_string()))
591 } else {
592 Ok(Counter(args.value))
593 }
594 };
595
596 let mut manager = ComponentManager::try_init(
597 [(
598 "key1",
599 FailArgs {
600 value: 1,
601 should_fail: false,
602 },
603 )],
604 init,
605 )
606 .unwrap();
607
608 let results: Vec<_> = manager
609 .try_update([
610 (
611 "key2",
612 FailArgs {
613 value: 20,
614 should_fail: false,
615 },
616 ),
617 (
618 "key3",
619 FailArgs {
620 value: 30,
621 should_fail: true,
622 },
623 ),
624 (
625 "key4",
626 FailArgs {
627 value: 40,
628 should_fail: false,
629 },
630 ),
631 ])
632 .collect();
633
634 assert_eq!(results.len(), 3);
635
636 assert_eq!(manager.components().len(), 3); assert!(manager.components().get("key2").is_some());
639 assert!(manager.components().get("key3").is_none());
640 assert!(manager.components().get("key4").is_some());
641 }
642}