1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use crate::reactor::*;

/// Notifies all [`Reactor`]s in the slice in order.
///
/// # Example
///
/// ```rust
/// use reducer::*;
///
/// struct State { /* ... */ }
/// struct Action { /* ... */ }
///
/// impl Reducer<Action> for State {
///     fn reduce(&mut self, action: Action) {
///         // ...
///     }
/// }
///
/// struct Actor { /* ... */ }
/// struct ActorError(/*...*/);
///
/// impl Reactor<State> for Actor {
///     type Error = ActorError;
///     fn react(&mut self, state: &State) -> Result<(), Self::Error> {
///         // ...
///         Ok(())
///     }
/// }
///
/// # #[cfg(feature = "std")] {
/// let mut actors = vec![];
///
/// actors.push(Actor { /* ... */ });
/// actors.push(Actor { /* ... */ });
/// // ...
/// actors.push(Actor { /* ... */ });
///
/// let mut store = Store::new(State { /* ... */ }, actors.into_boxed_slice());
///
/// // All actors get notified of state changes.
/// store.dispatch(Action { /* ... */ });
/// # }
/// ```
impl<S, T> Reactor<S> for [T]
where
    T: Reactor<S>,
{
    type Error = T::Error;

    fn react(&mut self, state: &S) -> Result<(), Self::Error> {
        for reducer in self {
            reducer.react(state)?;
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use crate::mock::*;
    use proptest::prelude::*;

    prop_compose! {
        pub(crate) fn length_and_index(max: usize)
            (length in 1..=max)
            (index in 0..length, length in Just(length))
        -> (usize, usize) {
            (length, index)
        }
    }

    proptest! {
        #[test]
        fn ok(states: Vec<u8>, len in 0..=100usize) {
            let reactors: &mut [Mock<_>] = &mut vec![Mock::default(); len];

            for (i, state) in states.iter().enumerate() {
                assert_eq!(react(reactors, state), Ok(()));

                for reactor in reactors.iter() {
                    assert_eq!(reactor.calls(), &states[0..=i])
                }
            }
        }
    }

    proptest! {
        #[test]
        fn err(state: u8, error: String, (len, at) in length_and_index(100)) {
            let reactors: &mut [Mock<_, _>] = &mut vec![Mock::default(); len];
            reactors[at].fail_if(state, &error[..]);

            assert_eq!(react(reactors, &state), Err(&error[..]));

            for reactor in reactors.iter().take(at + 1) {
                assert_eq!(reactor.calls(), &[state])
            }

            for reactor in reactors.iter().skip(at + 1) {
                assert_eq!(reactor.calls(), &[])
            }
        }
    }
}