Finite state machines in rust; bendns fork to add types.
Diffstat (limited to 'src/machine_wrapper.rs')
| -rw-r--r-- | src/machine_wrapper.rs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/machine_wrapper.rs b/src/machine_wrapper.rs new file mode 100644 index 0000000..a48cb1a --- /dev/null +++ b/src/machine_wrapper.rs @@ -0,0 +1,52 @@ +use crate::StateMachine; + +/// A convenience wrapper around the `StateMachine` trait that encapsulates the +/// state and transition and output function calls. +pub struct StateMachineWrapper<T: StateMachine> { + state: T::State, +} + +impl<T> StateMachineWrapper<T> +where + T: StateMachine, +{ + /// Create a new instance of this wrapper which encapsulates the initial + /// state. + pub fn new() -> Self { + StateMachineWrapper { + state: T::INITIAL_STATE, + } + } + + /// Consumes the provided input, gives an output and performs a state + /// transition. If a state transition with the current state and the + /// provided input is not allowed, returns an error. + pub fn consume(&mut self, input: &T::Input) -> Result<Option<T::Output>, ()> { + // Operations are reodered for optimization. When the transition is not + // allowed this code exits as soon as possible without calculating the + // output. + let state = match T::transition(&self.state, input) { + Some(state) => state, + None => return Err(()), + }; + let output = T::output(&self.state, input); + self.state = state; + Ok(output) + } + + /// Consumes the provided input, gives an output and performs a state + /// transition. If a state transition is not allowed, this function just + /// provides an output. + pub fn consume_anyway(&mut self, input: &T::Input) -> Option<T::Output> { + let output = T::output(&self.state, input); + if let Some(state) = T::transition(&self.state, input) { + self.state = state; + } + output + } + + /// Returns the current state. + pub fn state(&self) -> &T::State { + &self.state + } +} |