Finite state machines in rust; bendns fork to add types.
enhance undos
bendn 5 months ago
parent 337ee39 · commit 6026db1
-rw-r--r--rust-fsm/src/lib.rs22
-rw-r--r--rust-fsm/tests/circuit_breaker_dsl.rs2
-rw-r--r--rust-fsm/tests/circuit_breaker_dsl_custom_types.rs6
3 files changed, 19 insertions, 11 deletions
diff --git a/rust-fsm/src/lib.rs b/rust-fsm/src/lib.rs
index 3240fdd..e894ee9 100644
--- a/rust-fsm/src/lib.rs
+++ b/rust-fsm/src/lib.rs
@@ -229,7 +229,7 @@ You can see an example of the Circuit Breaker state machine in the
#![cfg_attr(not(feature = "std"), no_std)]
-use core::fmt;
+use core::fmt::{self, Debug, Display};
#[cfg(feature = "std")]
use std::error::Error;
@@ -262,14 +262,17 @@ pub trait StateMachineImpl: Sized {
fn consume(
&mut self,
input: Self::Input,
- ) -> Result<Option<Self::Output>, TransitionImpossibleError>
+ ) -> Result<Option<Self::Output>, TransitionImpossibleError<Self, Self::Input>>
where
Self::Input: Clone,
Self: Clone,
{
self.clone()
.transition(input.clone())
- .ok_or(TransitionImpossibleError)
+ .ok_or_else(|| TransitionImpossibleError {
+ state: self.clone(),
+ input: input.clone(),
+ })
.map(|state| std::mem::replace(self, state).output(input))
}
}
@@ -277,19 +280,24 @@ pub trait StateMachineImpl: Sized {
#[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;
+pub struct TransitionImpossibleError<S, I> {
+ state: S,
+ input: I,
+}
-impl fmt::Display for TransitionImpossibleError {
+impl<S: Debug, I: Debug> fmt::Display for TransitionImpossibleError<S, I> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
- "cannot perform a state transition from the current state with the provided input"
+ "cannot perform a state transition from the current state ({:?}) with the provided input ({:?})",
+ self.state,
+ self.input
)
}
}
#[cfg(feature = "std")]
-impl Error for TransitionImpossibleError {
+impl<S: Debug, I: Debug> Error for TransitionImpossibleError<S, I> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
diff --git a/rust-fsm/tests/circuit_breaker_dsl.rs b/rust-fsm/tests/circuit_breaker_dsl.rs
index c49787e..61b82fc 100644
--- a/rust-fsm/tests/circuit_breaker_dsl.rs
+++ b/rust-fsm/tests/circuit_breaker_dsl.rs
@@ -9,7 +9,7 @@ state_machine! {
/// A dummy implementation of the Circuit Breaker pattern to demonstrate
/// capabilities of its library DSL for defining finite state machines.
/// https://martinfowler.com/bliki/CircuitBreaker.html
- #[derive(Clone, Copy)]
+ #[derive(Clone, Copy, Debug)]
pub CircuitBreaker => Result => Action
Closed => Unsuccessful => Open [SetupTimer],
diff --git a/rust-fsm/tests/circuit_breaker_dsl_custom_types.rs b/rust-fsm/tests/circuit_breaker_dsl_custom_types.rs
index 4b22e08..72c5f34 100644
--- a/rust-fsm/tests/circuit_breaker_dsl_custom_types.rs
+++ b/rust-fsm/tests/circuit_breaker_dsl_custom_types.rs
@@ -5,21 +5,21 @@ use rust_fsm::*;
use std::sync::{Arc, Mutex};
use std::time::Duration;
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub enum Input {
Successful,
Unsuccessful,
TimerTriggered,
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub enum State {
Closed,
HalfOpen,
Open,
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub enum Output {
SetupTimer,
}