#![no_std]
use core::fmt::Debug;
#[cfg(feature = "inspect")]
pub mod schema;
#[cfg(feature = "inspect")]
pub use schema::{EventSchema, Inspectable, MachineSchema, SuperstateSchema, TransitionSchema};
pub trait MachineState: Copy + Eq + Debug + Send + Sync + 'static {}
impl<T> MachineState for T where T: Copy + Eq + Debug + Send + Sync + 'static {}
pub trait SubstateOf<Super> {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TransitionError<S>
where
S: MachineState,
{
pub from: S,
pub event: &'static str,
pub kind: TransitionErrorKind,
}
impl<S> TransitionError<S>
where
S: MachineState,
{
pub fn invalid_transition(from: S, event: &'static str) -> Self {
Self {
from,
event,
kind: TransitionErrorKind::InvalidTransition,
}
}
pub fn guard_failed(from: S, event: &'static str, guard: &'static str) -> Self {
Self {
from,
event,
kind: TransitionErrorKind::GuardFailed { guard },
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TransitionErrorKind {
InvalidTransition,
GuardFailed { guard: &'static str },
ActionFailed { action: &'static str },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GuardError {
pub guard: &'static str,
pub event: &'static str,
pub kind: TransitionErrorKind,
}
impl GuardError {
pub const fn new(guard: &'static str, event: &'static str) -> Self {
Self {
guard,
event,
kind: TransitionErrorKind::GuardFailed { guard },
}
}
pub const fn with_kind(
guard: &'static str,
event: &'static str,
kind: TransitionErrorKind,
) -> Self {
Self { guard, event, kind }
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CallbackError<E> {
pub action: &'static str,
pub event: &'static str,
pub source: E,
}
impl<E> CallbackError<E> {
pub fn new(action: &'static str, event: &'static str, source: E) -> Self {
Self {
action,
event,
source,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EventError<E> {
Guard(GuardError),
Callback(CallbackError<E>),
}
impl<E> EventError<E> {
pub const fn guard(err: GuardError) -> Self {
Self::Guard(err)
}
pub fn callback(action: &'static str, event: &'static str, source: E) -> Self {
Self::Callback(CallbackError::new(action, event, source))
}
}
#[doc(hidden)]
pub trait FallibleCallbackReturn<E> {
fn into_result(self) -> Result<(), E>;
}
impl<E> FallibleCallbackReturn<E> for () {
fn into_result(self) -> Result<(), E> {
Ok(())
}
}
impl<E> FallibleCallbackReturn<E> for Result<(), E> {
fn into_result(self) -> Result<(), E> {
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DynamicError<E = ()> {
InvalidTransition {
from: &'static str,
event: &'static str,
},
GuardFailed {
guard: &'static str,
event: &'static str,
},
ActionFailed {
action: &'static str,
event: &'static str,
},
CallbackFailed {
action: &'static str,
event: &'static str,
source: E,
},
WrongState {
expected: &'static str,
actual: &'static str,
operation: &'static str,
},
}
impl<E> DynamicError<E> {
pub fn invalid_transition(from: &'static str, event: &'static str) -> Self {
Self::InvalidTransition { from, event }
}
pub fn guard_failed(guard: &'static str, event: &'static str) -> Self {
Self::GuardFailed { guard, event }
}
pub fn action_failed(action: &'static str, event: &'static str) -> Self {
Self::ActionFailed { action, event }
}
pub fn callback_failed(action: &'static str, event: &'static str, source: E) -> Self {
Self::CallbackFailed {
action,
event,
source,
}
}
pub fn wrong_state(
expected: &'static str,
actual: &'static str,
operation: &'static str,
) -> Self {
Self::WrongState {
expected,
actual,
operation,
}
}
pub fn from_guard_error(err: GuardError) -> Self {
match err.kind {
TransitionErrorKind::GuardFailed { guard } => Self::GuardFailed {
guard,
event: err.event,
},
TransitionErrorKind::ActionFailed { action } => Self::ActionFailed {
action,
event: err.event,
},
TransitionErrorKind::InvalidTransition => Self::InvalidTransition {
from: "",
event: err.event,
},
}
}
pub fn from_event_error(err: EventError<E>) -> Self {
match err {
EventError::Guard(err) => Self::from_guard_error(err),
EventError::Callback(err) => Self::callback_failed(err.action, err.event, err.source),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AroundStage {
Before,
AfterSuccess,
}
#[derive(Debug, Clone)]
pub enum AroundOutcome<S>
where
S: MachineState,
{
Proceed,
Abort(TransitionError<S>),
}