Finite state machines in rust; bendns fork to add types.
implement basic proper error type for impossible state transitions
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rw-r--r-- | src/lib.rs | 23 | ||||
| -rw-r--r-- | tests/circuit_breaker.rs | 2 | ||||
| -rw-r--r-- | tests/circuit_breaker_dsl.rs | 2 |
4 files changed, 26 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 67f292a..d57a05a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog][keepachangelog], and this project adheres to [Semantic Versioning][semver]. ## [Unreleased] +### Changed +* State transition error is now represented with `TransitionImpossibleError` + instead of `()`. ## [0.4.0] - 2020-08-25 ### Added @@ -113,6 +113,8 @@ //! //! [repo]: https://github.com/eugene-babichenko/rust-fsm/blob/master/tests/circuit_breaker.rs +use core::fmt; + #[doc(hidden)] pub use rust_fsm_dsl::*; @@ -147,6 +149,11 @@ pub struct StateMachine<T: StateMachineImpl> { state: T::State, } +#[derive(Debug, Clone)] +/// An error type that represents that the state transition is impossible given +/// the current combination of state and input. +pub struct TransitionImpossibleError; + impl<T> StateMachine<T> where T: StateMachineImpl, @@ -166,13 +173,16 @@ where /// 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>, ()> { + pub fn consume( + &mut self, + input: &T::Input, + ) -> Result<Option<T::Output>, TransitionImpossibleError> { if let Some(state) = T::transition(&self.state, input) { let output = T::output(&self.state, input); self.state = state; Ok(output) } else { - Err(()) + Err(TransitionImpossibleError) } } @@ -190,3 +200,12 @@ where Self::new() } } + +impl fmt::Display for TransitionImpossibleError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "cannot perform a state transition from the current state with the provided input" + ) + } +} diff --git a/tests/circuit_breaker.rs b/tests/circuit_breaker.rs index a87921b..aa25a1e 100644 --- a/tests/circuit_breaker.rs +++ b/tests/circuit_breaker.rs @@ -91,7 +91,7 @@ fn circuit_breaker() { std::thread::sleep(Duration::new(1, 0)); let mut lock = machine_try.lock().unwrap(); let res = lock.consume(&CircuitBreakerInput::Successful); - assert_eq!(res, Err(())); + assert!(matches!(res, Err(TransitionImpossibleError))); assert_eq!(lock.state(), &CircuitBreakerState::Open); }); diff --git a/tests/circuit_breaker_dsl.rs b/tests/circuit_breaker_dsl.rs index e593625..2293786 100644 --- a/tests/circuit_breaker_dsl.rs +++ b/tests/circuit_breaker_dsl.rs @@ -45,7 +45,7 @@ fn circit_breaker_dsl() { std::thread::sleep(Duration::new(1, 0)); let mut lock = machine_try.lock().unwrap(); let res = lock.consume(&CircuitBreakerInput::Successful); - assert!(matches!(res, Err(()))); + assert!(matches!(res, Err(TransitionImpossibleError))); assert!(matches!(lock.state(), &CircuitBreakerState::Open)); }); |