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
use ::MealyAutomaton; pub struct Timeout<M, T> { inner: M, timed_out: bool, limit: T, } pub enum TimeoutInput<I, T> { Input(I), UpdateTime(T), } impl<M, T, I, O> Timeout<M, T> where M: MealyAutomaton<Input = I, Output = O> { pub fn new(m: M, times_out_at: T) -> Timeout<M, T> { Timeout { inner: m, timed_out: false, limit: times_out_at, } } } impl<M, T, I, O> MealyAutomaton for Timeout<M, T> where M: MealyAutomaton<Input = I, Output = O>, T: PartialOrd { type Input = TimeoutInput<I, T>; type Output = Option<O>; fn transition(mut self, input: Self::Input) -> (Self, Self::Output) { if self.halted() { return (self, None); } match input { TimeoutInput::Input(inner_input) => { let output; self.inner = { let (new_state, ioutput) = self.inner.transition(inner_input); output = ioutput; new_state }; (self, Some(output)) } TimeoutInput::UpdateTime(now) => { if now >= self.limit { self.timed_out = true; (self, None) } else { (self, None) } } } } fn failed(&self) -> bool { self.timed_out || self.inner.failed() } fn done(&self) -> bool { self.inner.done() } }