Struct EventInterceptor

Source
pub struct EventInterceptor<T: Event<E>, E>(/* private fields */);

Implementations§

Source§

impl<T: Event<E>, E> EventInterceptor<T, E>

Source

pub fn new(event: T) -> EventInterceptor<T, E>

Examples found in repository?
examples/todo.rs (line 95)
88    fn handle(self: Box<Self>, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
89        {
90            let db = context.coeffects.get::<Db<AppState>>().unwrap();
91            match db.borrow().mode {
92                Mode::Menu     => {
93                    let interceptors: Vec<Box<Interceptor<Error = ()>>> = vec![
94                        Box::new(EmptyInputHandler(Mode::Quitting)),
95                        Box::new(EventInterceptor::new(MenuInput))
96                    ];
97                    context.queue.extend(interceptors);
98                },
99                Mode::Adding   => {
100                    let interceptors: Vec<Box<Interceptor<Error = ()>>> = vec![
101                        Box::new(EmptyInputHandler(Mode::Menu)),
102                        Box::new(EventInterceptor::new(AddTodo))
103                    ];
104                    context.queue.extend(interceptors);
105                },
106                Mode::Removing => {
107                    let interceptors: Vec<Box<Interceptor<Error = ()>>> = vec![
108                        Box::new(EmptyInputHandler(Mode::Menu)),
109                        Box::new(ParseIndex),
110                        Box::new(EventInterceptor::new(RemoveTodo))
111                    ];
112                    context.queue.extend(interceptors);
113                },
114                Mode::Marking  => {
115                    let interceptors: Vec<Box<Interceptor<Error = ()>>> = vec![
116                        Box::new(EmptyInputHandler(Mode::Menu)),
117                        Box::new(ParseIndex),
118                        Box::new(EventInterceptor::new(ToggleMark))
119                    ];
120                    context.queue.extend(interceptors);
121                },
122                Mode::Quitting => context.queue.push_back(Box::new(EventInterceptor::new(Quit(0))) as Box<Interceptor<Error = ()>>),
123            }
124        }
125        let input = *self;
126        context.coeffects.insert(input);
127        context.next()
128    }
129}
130
131struct NonEmptyInput(String);
132
133struct EmptyInputHandler(Mode);
134
135impl Interceptor for EmptyInputHandler {
136    type Error = ();
137
138    fn before(&self, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
139        match context.coeffects.remove::<Input>().unwrap().0.as_ref() {
140            "" => {
141                context.queue.clear();
142                let db = context.coeffects.get::<Db<AppState>>().unwrap();
143                let mode = self.0;
144                context.effects.push(Box::new(db.mutate(move |state: &mut AppState| state.mode = mode)));
145                let dispatcher = context.coeffects.get::<Dispatcher<()>>().unwrap();
146                context.effects.push(dispatcher.dispatch(ShowMenu));
147            },
148            input => {
149                context.coeffects.insert(NonEmptyInput(input.to_string()));
150            }
151        };
152
153        context.next()
154    }
155}
156
157struct Index(Result<usize, RemoveError<std::num::ParseIntError>>);
158
159struct ParseIndex;
160
161impl Interceptor for ParseIndex {
162    type Error = ();
163
164    fn before(&self, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
165        let max = {
166            let db = context.coeffects.get::<Db<AppState>>().unwrap();
167            db.borrow().todos.len()
168        };
169        let index_res = context.coeffects.remove::<NonEmptyInput>().unwrap()
170            .0.parse::<isize>()
171            .map_err(RemoveError::ParseError)
172            .and_then(|index| {
173                if index >= 0 && (index as usize) < max {
174                    Ok(index as usize)
175                } else {
176                    Err(RemoveError::OutOfRange(index))
177                }
178            });
179        context.coeffects.insert(Index(index_res));
180        context.next()
181    }
182}
183
184struct MenuInput;
185
186impl Event<()> for MenuInput {
187    fn handle(self: Box<Self>, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
188        {
189            let input = context.coeffects.get::<NonEmptyInput>().unwrap();
190            let next_mode = match input.0.as_ref() {
191                "1" => {
192                    let dispatcher = context.coeffects.get::<Dispatcher<()>>().unwrap();
193                    context.effects.push(dispatcher.dispatch(ShowTodos));
194                    Mode::Menu
195                },
196                "2" => Mode::Adding,
197                "3" => Mode::Marking,
198                "4" => Mode::Removing,
199                _ => Mode::Menu,
200            };
201            let db = context.coeffects.get::<Db<AppState>>().unwrap();
202            context.effects.push(Box::new(db.mutate(move |state: &mut AppState| state.mode = next_mode)));
203        }
204        context.next()
205    }
206}
207
208struct ShowTodos;
209
210impl Event<()> for ShowTodos {
211    fn handle(self: Box<Self>, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
212        {
213            let db = context.coeffects.get::<Db<AppState>>().unwrap();
214            context.effects.push(Box::new(Print(format!("\nTODO:"))));
215            let todos = &db.borrow().todos;
216            if 0 == todos.len() {
217                context.effects.push(Box::new(Print("  Nothing to do.".to_string())));
218            }
219            for (i, todo) in todos.iter().enumerate() {
220                let status = if todo.0 { "✔" } else { " " };
221                context.effects.push(Box::new(Print(format!("  - {}: [{}] {}", i, status, todo.1))));
222            }
223            context.effects.push(Box::new(Print("".to_string())));
224        }
225        context.next()
226    }
227}
228
229struct AddTodo;
230
231impl Event<()> for AddTodo {
232    fn handle(self: Box<Self>, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
233        {
234            let input = context.coeffects.remove::<NonEmptyInput>().unwrap().0;
235            let db = context.coeffects.get::<Db<AppState>>().unwrap();
236            context.effects.push(Box::new(db.mutate(move |state: &mut AppState| state.todos.push((false, input)))));
237        }
238        context.next()
239    }
240}
241
242struct RemoveTodo;
243
244#[derive(Debug)]
245enum RemoveError<E> {
246    ParseError(E),
247    OutOfRange(isize),
248}
249
250impl Event<()> for RemoveTodo {
251    fn handle(self: Box<Self>, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
252        {
253            let index_res = context.coeffects.remove::<Index>().unwrap().0;
254            let db = context.coeffects.get::<Db<AppState>>().unwrap();
255            match index_res {
256                Ok(index) => {
257                    context.effects.push(Box::new(db.mutate(move |state: &mut AppState| {
258                        state.todos.remove(index);
259                    })));
260                },
261                Err(e) => {
262                    context.effects.push(Box::new(Print(format!("Error removing: {:?}", e))))
263                },
264            };
265        }
266        context.next()
267    }
268}
269
270struct ToggleMark;
271
272impl Event<()> for ToggleMark {
273    fn handle(self: Box<Self>, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
274        {
275            let index_res = context.coeffects.remove::<Index>().unwrap().0;
276            let db = context.coeffects.get::<Db<AppState>>().unwrap();
277            match index_res {
278                Ok(index) => {
279                    context.effects.push(Box::new(db.mutate(move |state: &mut AppState| {
280                        let todo = state.todos.get_mut(index).unwrap();
281                        todo.0 = ! todo.0;
282                    })));
283                },
284                Err(e) => {
285                    context.effects.push(Box::new(Print(format!("Error marking: {:?}", e))))
286                },
287            };
288        }
289        context.next()
290    }
291}
292
293struct ShowPrompt;
294
295impl Event<()> for ShowPrompt {
296    fn handle(self: Box<Self>, mut context: Context<()>) -> Box<Future<Item = Context<()>, Error = ()>> {
297        {
298            let db = context.coeffects.get::<Db<AppState>>().unwrap();
299            let dispatcher = context.coeffects.get::<Dispatcher<()>>().unwrap();
300            match db.borrow().mode {
301                Mode::Menu => context.effects.push(dispatcher.dispatch(ShowMenu)),
302                Mode::Adding => {
303                    context.effects.push(dispatcher.dispatch(ShowTodos));
304                },
305                Mode::Removing => {
306                    context.effects.push(dispatcher.dispatch(ShowTodos));
307                },
308                Mode::Marking => {
309                    context.effects.push(dispatcher.dispatch(ShowTodos));
310                },
311                Mode::Quitting => {
312                    context.queue.push_back(Box::new(EventInterceptor::new(Quit(0))) as Box<Interceptor<Error = ()>>);
313                }
314            }
315        }
316        context.next()
317    }

Trait Implementations§

Source§

impl<E: 'static, T: Event<E>> Interceptor for EventInterceptor<T, E>

Source§

type Error = E

Source§

fn before( &self, context: Context<Self::Error>, ) -> Box<dyn Future<Item = Context<Self::Error>, Error = Self::Error>>

Source§

fn after( &self, context: Context<Self::Error>, ) -> Box<dyn Future<Item = Context<Self::Error>, Error = Self::Error>>

Auto Trait Implementations§

§

impl<T, E> !Freeze for EventInterceptor<T, E>

§

impl<T, E> !RefUnwindSafe for EventInterceptor<T, E>

§

impl<T, E> Send for EventInterceptor<T, E>
where E: Send, T: Send,

§

impl<T, E> !Sync for EventInterceptor<T, E>

§

impl<T, E> Unpin for EventInterceptor<T, E>
where E: Unpin, T: Unpin,

§

impl<T, E> UnwindSafe for EventInterceptor<T, E>
where E: UnwindSafe, T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Any for T
where T: Any,