1extern 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
167struct 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}