reducer/reactor/array.rs
1use crate::reactor::*;
2
3/// Notifies all [`Reactor`]s in the array in order.
4///
5/// <small>Currently implemented for arrays of up to 32 elements.</small>
6///
7/// # Example
8///
9/// ```rust
10/// use reducer::*;
11///
12/// struct State { /* ... */ }
13/// struct Action { /* ... */ }
14///
15/// impl Reducer<Action> for State {
16/// fn reduce(&mut self, action: Action) {
17/// // ...
18/// }
19/// }
20///
21/// struct Actor { /* ... */ }
22/// struct ActorError(/*...*/);
23///
24/// impl Reactor<State> for Actor {
25/// type Error = ActorError;
26/// fn react(&mut self, state: &State) -> Result<(), Self::Error> {
27/// // ...
28/// Ok(())
29/// }
30/// }
31///
32/// let a = Actor { /* ... */ };
33/// let b = Actor { /* ... */ };
34/// // ...
35/// let z = Actor { /* ... */ };
36///
37/// let mut store = Store::new(State { /* ... */ }, [a, b, /* ..., */ z]);
38///
39/// // All actors get notified of state changes.
40/// store.dispatch(Action { /* ... */ });
41/// ```
42impl<S, T, const N: usize> Reactor<S> for [T; N]
43where
44 S: ?Sized,
45 T: Reactor<S>,
46{
47 type Error = T::Error;
48
49 fn react(&mut self, state: &S) -> Result<(), Self::Error> {
50 self[..].react(state)
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use mockall::predicate::*;
58 use test_strategy::proptest;
59
60 #[proptest]
61 fn react(state: u8, results: [Result<(), u8>; 32]) {
62 let (idx, result) = results
63 .iter()
64 .enumerate()
65 .find(|(_, r)| r.is_err())
66 .map_or((results.len(), Ok(())), |(i, &r)| (i, r));
67
68 let mut reactor: [MockReactor<_, _>; 32] = Default::default();
69
70 for (i, (mock, result)) in reactor.iter_mut().zip(results).enumerate() {
71 mock.expect_react()
72 .with(eq(state))
73 .times(if i > idx { 0 } else { 1 })
74 .return_const(result);
75 }
76
77 assert_eq!(Reactor::react(&mut reactor, &state), result);
78 }
79}