Finite state machines in rust; bendns fork to add types.
Diffstat (limited to 'src/machine_wrapper.rs')
-rw-r--r--src/machine_wrapper.rs52
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
+ }
+}