tokio_interceptor/
lib.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
16extern crate anymap;
17#[macro_use]
18extern crate futures;
19#[macro_use]
20extern crate log;
21extern crate tokio_core;
22
23
24use std::mem;
25use std::sync::Arc;
26use std::rc::Rc;
27
28use anymap::AnyMap;
29use futures::{future,Async,Future};
30
31mod app;
32pub use app::App;
33
34mod coeffects;
35pub use coeffects::{Coeffect,NewCoeffect,InjectCoeffect};
36
37mod db;
38pub use db::Db;
39
40mod effects;
41pub use effects::{Effect,HandleEffects};
42
43mod events;
44pub use events::{Event,EventDispatcher,EventInterceptor,Dispatch,Dispatcher};
45
46mod queue;
47pub use queue::InterceptorQueue;
48
49pub struct Context<E> {
50    pub coeffects: AnyMap,
51    pub effects: Vec<Box<Effect>>,
52    pub queue: InterceptorQueue<E>,
53    pub stack: Vec<Rc<Box<Interceptor<Error = E>>>>,
54}
55
56impl<E> Context<E> {
57    pub fn new(interceptors: Vec<Rc<Box<Interceptor<Error = E>>>>) -> Context<E> {
58        Context {
59            coeffects: AnyMap::new(),
60            effects: vec![],
61            queue: interceptors.into_iter().collect(),
62            stack: vec![],
63        }
64    }
65
66    pub fn push_effect<Eff: 'static + Effect>(&mut self, effect: Eff) {
67        self.effects.push(Box::new(effect));
68    }
69
70    pub fn next(self) -> Box<Future<Item = Context<E>, Error = E>>
71    where E: 'static
72    {
73        Box::new(future::ok(self))
74    }
75}
76
77pub trait Interceptor {
78    type Error: 'static;
79
80    fn before(&self, context: Context<Self::Error>) -> Box<Future<Item = Context<Self::Error>,
81                                                                  Error = Self::Error>> {
82        Box::new(future::ok(context))
83    }
84
85    fn after(&self, context: Context<Self::Error>) -> Box<Future<Item = Context<Self::Error>,
86                                                                 Error = Self::Error>> {
87        Box::new(future::ok(context))
88    }
89}
90
91impl<I: Interceptor + ?Sized> Interceptor for Arc<I> {
92    type Error = I::Error;
93
94    fn before(&self, context: Context<Self::Error>) -> Box<Future<Item = Context<Self::Error>,
95                                                                  Error = Self::Error>> {
96        (**self).before(context)
97    }
98
99    fn after(&self, context: Context<Self::Error>) -> Box<Future<Item = Context<Self::Error>,
100                                                                 Error = Self::Error>> {
101        (**self).after(context)
102    }
103}
104
105impl<I: Interceptor + ?Sized> Interceptor for Rc<I> {
106    type Error = I::Error;
107
108    fn before(&self, context: Context<Self::Error>) -> Box<Future<Item = Context<Self::Error>,
109                                                                  Error = Self::Error>> {
110        (**self).before(context)
111    }
112
113    fn after(&self, context: Context<Self::Error>) -> Box<Future<Item = Context<Self::Error>,
114                                                                 Error = Self::Error>> {
115        (**self).after(context)
116    }
117}
118
119pub trait NewInterceptor
120{
121    type Error: 'static;
122    type Interceptor: Interceptor<Error = Self::Error>;
123
124    fn new_interceptor(&self) -> Self::Interceptor;
125}
126
127
128impl<I: Copy + Interceptor> NewInterceptor for I {
129    type Error = I::Error;
130    type Interceptor = I;
131
132    fn new_interceptor(&self) -> I {
133        *self
134    }
135}
136
137enum Direction {
138    Forwards, Backwards
139}
140
141impl Direction {
142    fn call<E>(&self, interceptor: Rc<Box<Interceptor<Error = E>>>, context: Context<E>) -> Box<Future<Item = Context<E>, Error = E>>
143    where E: 'static
144    {
145        match *self {
146            Direction::Forwards => interceptor.before(context),
147            Direction::Backwards => interceptor.after(context),
148        }
149    }
150
151    fn is_forwards(&self) -> bool {
152        match *self {
153            Direction::Forwards => true,
154            Direction::Backwards => false,
155        }
156    }
157
158    #[allow(dead_code)]
159    fn is_backwards(&self) -> bool {
160        match *self {
161            Direction::Forwards => false,
162            Direction::Backwards => true,
163        }
164    }
165}
166
167/// Dispatched represents the eventual completion of an Event
168/// being fully processed by a chain of Interceptors.  First, the
169/// chain is iterated in order threading the Context through each
170/// `before` method. On reaching the end of the chain, the
171/// interceptors are iterated in the reverse order, and the
172/// Context is threaded through their `after` methods.
173struct Dispatched<E> {
174    direction: Direction,
175    next_ctx: Box<Future<Item = Context<E>, Error = E>>,
176}
177
178impl<E> Dispatched<E> {
179    pub fn new(next_ctx: Box<Future<Item = Context<E>, Error = E>>) -> Dispatched<E> {
180        Dispatched {
181            direction: Direction::Forwards,
182            next_ctx,
183        }
184    }
185}
186
187impl<E: 'static> Future for Dispatched<E> {
188    type Item = Context<E>;
189    type Error = E;
190
191    fn poll(&mut self) -> Result<Async<Context<E>>, E> {
192        loop {
193            let mut ctx = try_ready!(self.next_ctx.poll());
194            if let Some(next) = ctx.queue.pop_front() {
195                ctx.stack.push(Rc::clone(&next));
196                self.next_ctx = self.direction.call(next, ctx);
197                continue;
198            } else {
199                if self.direction.is_forwards() {
200                    self.direction = Direction::Backwards;
201                    let stack = mem::replace(&mut ctx.stack, vec![]);
202                    ctx.queue = stack.into_iter().rev().collect();
203                    self.next_ctx = Box::new(future::ok(ctx));
204                    continue;
205                } else {
206                    return Ok(Async::Ready(ctx));
207                }
208            }
209        }
210    }
211}
212
213#[cfg(test)]
214pub mod tests {
215    use super::*;
216
217    use std::cell::RefCell;
218    use std::rc::Rc;
219
220
221    #[derive(Debug,PartialEq)]
222    pub struct State(pub u8);
223
224    pub struct StateHolder(pub Rc<State>);
225
226    impl NewCoeffect for StateHolder {
227        type Instance = Rc<State>;
228
229        fn new_coeffect(&self) -> Rc<State> {
230            Rc::clone(&self.0)
231        }
232    }
233
234    impl Coeffect for State {}
235
236    #[test]
237    fn test_coeffect_map() {
238        let mut cmap = AnyMap::new();
239        cmap.insert(State(1));
240        assert_eq!(Some(&State(1)), cmap.get::<State>())
241    }
242
243    struct BeforeEvent(pub Rc<RefCell<bool>>);
244
245    impl Event<()> for BeforeEvent {
246        fn handle(self: Box<Self>, context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
247            let mut called = self.0.borrow_mut();
248            *called = true;
249            Box::new(future::ok(context))
250        }
251    }
252
253    #[test]
254    fn test_dispatcher_calls_event_before() {
255        let mut app = EventDispatcher::new();
256        app.register_event::<BeforeEvent>(vec![]);
257        let called = Rc::new(RefCell::new(false));
258        app.dispatch(BeforeEvent(Rc::clone(&called))).wait();
259        assert_eq!(true, *called.borrow());
260    }
261
262    struct BeforeInter(pub Rc<RefCell<bool>>);
263
264    impl Interceptor for BeforeInter {
265        type Error = ();
266
267        fn before(&self, context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
268            let mut called = self.0.borrow_mut();
269            *called = true;
270            Box::new(future::ok(context))
271        }
272    }
273
274    struct IdentityEvent;
275    impl Event<()> for IdentityEvent {
276        fn handle(self: Box<Self>, context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
277            Box::new(future::ok(context))
278        }
279    }
280
281    #[test]
282    fn test_dispatcher_calls_interceptor_before() {
283        let mut app = EventDispatcher::new();
284
285        let called_first = Rc::new(RefCell::new(false));
286        let before_inter = BeforeInter(Rc::clone(&called_first));
287        app.register_event::<BeforeEvent>(vec![Box::new(before_inter)]);
288
289        let called_second = Rc::new(RefCell::new(false));
290        app.dispatch(BeforeEvent(Rc::clone(&called_second))).wait();
291
292        assert_eq!(true, *called_first.borrow());
293        assert_eq!(true, *called_second.borrow());
294    }
295
296    struct AfterInter(pub Rc<RefCell<bool>>);
297
298    impl Interceptor for AfterInter {
299        type Error = ();
300
301        fn after(&self, context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
302            let mut called = self.0.borrow_mut();
303            *called = true;
304            Box::new(future::ok(context))
305        }
306    }
307
308    #[test]
309    fn test_dispatcher_calls_interceptor_after() {
310        let mut app = EventDispatcher::new();
311
312        let called_first = Rc::new(RefCell::new(false));
313        let before_inter = BeforeInter(Rc::clone(&called_first));
314
315        let called_third = Rc::new(RefCell::new(false));
316        let after_inter = AfterInter(Rc::clone(&called_third));
317
318        app.register_event::<BeforeEvent>(vec![Box::new(before_inter),
319                                               Box::new(after_inter)]);
320
321        let called_second = Rc::new(RefCell::new(false));
322        app.dispatch(BeforeEvent(Rc::clone(&called_second))).wait();
323
324        assert_eq!(true, *called_first.borrow());
325        assert_eq!(true, *called_second.borrow());
326        assert_eq!(true, *called_third.borrow());
327    }
328}