tokio_interceptor/
effects.rs

1// This file is part of tokio-interceptor.
2//
3// tokio-interceptor is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Lesser General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// tokio-interceptor is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Lesser General Public License for more details.
12//
13// You should have received a copy of the GNU Lesser General Public License
14// along with tokio-interceptor.  If not, see <http://www.gnu.org/licenses/>.
15
16use std::mem;
17use std::cell::RefCell;
18use std::marker::PhantomData;
19use std::rc::Rc;
20
21use futures::{future,Future};
22
23use super::{Context,Interceptor};
24
25pub trait Effect {
26    fn action(self: Box<Self>);
27}
28
29pub struct HandleEffects<E>(PhantomData<E>);
30
31impl<E> HandleEffects<E>
32{
33    pub fn new() -> HandleEffects<E> {
34        HandleEffects(PhantomData)
35    }
36}
37
38impl<E> Interceptor for HandleEffects<E>
39where E: 'static,
40{
41    type Error = E;
42
43    fn after(&self, mut context: Context<Self::Error>) -> Box<Future<Item = Context<Self::Error>,
44                                                                     Error = Self::Error>> {
45        let effects = mem::replace(&mut context.effects, vec![]);
46        for e in effects.into_iter() {
47            e.action();
48        }
49        Box::new(future::ok(context))
50    }
51}
52
53pub struct MutateState<S, F> {
54    state_ref: Option<Rc<RefCell<S>>>,
55    mutate: F,
56}
57
58impl<S, F> MutateState<S, F> {
59    pub fn new(state_ref: Rc<RefCell<S>>, mutate: F) -> MutateState<S, F> {
60        MutateState { state_ref: Some(state_ref), mutate }
61    }
62}
63
64impl<S, F> Effect for MutateState<S, F>
65where S: 'static,
66      F: 'static + FnOnce(&mut S)
67{
68    fn action(mut self: Box<Self>) {
69        let state_ref = self.state_ref.take().unwrap();
70        let mut state = state_ref.borrow_mut();
71        (self.mutate)(&mut state)
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    use Context;
80
81    use tests::State;
82
83    #[test]
84    fn test_effect_interceptor() {
85        let mut context: Context<()> = Context::new(vec![]);
86        let i: HandleEffects<()> = HandleEffects::new();
87
88        let state = Rc::new(RefCell::new(State(0)));
89        let e = MutateState::new(Rc::clone(&state), |state: &mut State| state.0 = 10);
90        context.effects.push(Box::new(e));
91        i.after(context);
92
93        assert_eq!(state.borrow().0, 10);
94    }
95}