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
mod array; mod boxed; mod mpsc; mod option; mod reference; mod slice; mod tuple; /// Trait for types that react to state transitions. /// /// Reactors connect the _state_ to the _view_ components. They can implement arbitrary logic in /// response to state transitions, but it's often better to think of Reactors as _channels_ that /// transmit the current state to other parts of your application. /// /// # Reactor as a Data Channel /// For GUI applications, it is a good practice to have a separate thread dedicated to rendering. /// To help wiring up the Flux pattern in such multi-threaded scenarios, Reactor is implemented /// for [`mpsc::Sender`] out of the box. /// /// ## Example /// /// ```rust /// use reducer::*; /// /// fn main() { /// // Create a channel for the current state. /// let (tx, rx) = std::sync::mpsc::channel(); /// /// // Start the rendering thread. /// std::thread::spawn(move || { /// while let Ok(Countdown(t)) = rx.recv() { /// // Render the current state to the screen. /// match t { /// 6 => println!("T-6 seconds - Main engine start."), /// 0 => println!("T-0 seconds - Solid rocket booster ignition and liftoff!"), /// t if t > 0 => println!("T-{} seconds", t), /// _ => break, /// } /// } /// }); /// /// #[derive(Clone)] /// struct Countdown(i32); /// /// struct Tick; /// impl Reducer<Tick> for Countdown { /// fn reduce(&mut self, _: Tick) { /// self.0 -= 1; /// } /// } /// /// // Set-up the initial state. /// let mut store = Store::new(Countdown(10), tx); /// /// // Count down to liftoff! /// while let Ok(()) = store.dispatch(Tick) {} /// } /// ``` pub trait Reactor<S> { /// The result of reacting to `S`. type Output; /// Reacts to `S` and produces `Self::Output`. /// /// # Example /// /// ```rust /// use reducer::*; /// use std::fmt::Debug; /// use std::io::{self, Write}; /// /// struct Console; /// /// impl<T: Debug> Reactor<T> for Console { /// type Output = io::Result<()>; /// fn react(&self, state: &T) -> Self::Output { /// io::stdout().write_fmt(format_args!("{:?}\n", state)) /// } /// } /// ``` fn react(&self, state: &S) -> Self::Output; } #[cfg(test)] mod tests { use super::*; use crate::mock::*; use proptest::*; proptest! { #[test] fn react(states: Vec<u8>) { let mut mock = Mock::default(); for (i, state) in states.iter().enumerate() { let reactor: &mut dyn Reactor<_, Output = _> = &mut mock; assert_eq!(reactor.react(state), Ok(())); assert_eq!(mock, Mock::new(&states[0..=i])); } } } }