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
//! [Middleware] used to modify the behaviour of a [Store] during a
//! [Store::dispatch()]. This module also contains some simple
//! middleware implementations which can be used as utilities in an
//! application.

#[cfg(feature = "simple_logger")]
#[cfg_attr(docsrs, doc(cfg(feature = "simple_logger")))]
pub mod simple_logger;

#[cfg(feature = "web_logger")]
#[cfg_attr(docsrs, doc(cfg(feature = "web_logger")))]
pub mod web_logger;

use crate::Store;

pub struct ReduceMiddlewareResult<Event, Effect> {
    pub events: Vec<Event>,
    pub effects: Vec<Effect>,
}

impl<Event, Effect> Default for ReduceMiddlewareResult<Event, Effect> {
    fn default() -> Self {
        ReduceMiddlewareResult {
            events: Vec::new(),
            effects: Vec::new(),
        }
    }
}

/// Executes subsequent middleware and then runs the [Reducer](crate::Reducer).
pub type ReduceFn<State, Action, Event, Effect> = fn(
    &Store<State, Action, Event, Effect>,
    Option<&Action>,
) -> ReduceMiddlewareResult<Event, Effect>;

/// Executes subsequent middleware and then notifies the listeners.
pub type NotifyFn<State, Action, Event, Effect> =
    fn(&Store<State, Action, Event, Effect>, Vec<Event>) -> Vec<Event>;

/// `Middleware` used to modify the behaviour of a [Store] during a
/// [Store::dispatch()].
pub trait Middleware<State, Action, Event, Effect> {
    /// This method is invoked by the [Store] during a
    /// [Store::dispatch()] just before the `Action` is sent to the
    /// [Reducer](crate::Reducer). It is necessary to call the
    /// provided `reduce` function, which executes subsequent
    /// middleware and runs the [Reducer](crate::Reducer), and usually
    /// the events produced by the `reduce` function are returned from
    /// this method.
    ///
    /// This method allows modifying the action in question, or even
    /// removing it, preventing the [Reducer](crate::Reducer) from
    /// processing the action. It also allows modifying the events
    /// produced by the [Reducer](crate::Reducer) before the
    /// [Middleware::on_notify()] is invoked and they are sent to the
    /// [Store] listeners.
    fn on_reduce(
        &self,
        store: &Store<State, Action, Event, Effect>,
        action: Option<&Action>,
        reduce: ReduceFn<State, Action, Event, Effect>,
    ) -> ReduceMiddlewareResult<Event, Effect> {
        reduce(store, action)
    }

    /// Process an `Effect`. Returns `None` if the effect was
    /// processed/consumed by this handler, otherwise returns
    /// `Some(effect)`.
    fn process_effect(
        &self,
        _store: &Store<State, Action, Event, Effect>,
        effect: Effect,
    ) -> Option<Effect> {
        Some(effect)
    }

    /// This method is invoked by the [Store] during a
    /// [Store::dispatch()] after the [Reducer](crate::Reducer) has
    /// processed the `Action` and all [Middleware::on_reduce()]
    /// methods have completed, just before resulting events are
    /// sent to the store listeners. It is necessary to call the
    /// provided `notify` function, which executes subsequent
    /// middleware and then notifies the listeners.
    ///
    /// This method allows modifying the events in question before the
    /// listeners are notified.
    fn on_notify(
        &self,
        store: &Store<State, Action, Event, Effect>,
        events: Vec<Event>,
        notify: NotifyFn<State, Action, Event, Effect>,
    ) -> Vec<Event> {
        notify(store, events)
    }
}