ready_active_safe/error.rs
1//! Crate-level error types.
2
3use core::fmt;
4
5/// Errors that can occur during lifecycle operations.
6///
7/// All variants include enough context to diagnose the failure without
8/// a debugger. Uses `#[non_exhaustive]` so new variants can be added
9/// in minor versions without breaking downstream code.
10///
11/// # Examples
12///
13/// ```
14/// use ready_active_safe::LifecycleError;
15///
16/// let err: LifecycleError<&str> = LifecycleError::TransitionDenied {
17/// from: "active",
18/// to: "ready",
19/// reason: "backward transitions are not allowed",
20/// };
21/// assert_eq!(
22/// err.to_string(),
23/// "transition denied from active to ready: backward transitions are not allowed",
24/// );
25/// ```
26#[derive(Debug, Clone, PartialEq, Eq)]
27#[non_exhaustive]
28pub enum LifecycleError<M> {
29 /// A mode transition was rejected by the [`Policy`](crate::Policy).
30 TransitionDenied {
31 /// The mode the system was in when the transition was attempted.
32 from: M,
33 /// The mode the system attempted to transition to.
34 to: M,
35 /// A human-readable explanation of why the transition was denied.
36 reason: &'static str,
37 },
38}
39
40impl<M: fmt::Display> fmt::Display for LifecycleError<M> {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 Self::TransitionDenied { from, to, reason } => {
44 write!(f, "transition denied from {from} to {to}: {reason}")
45 }
46 }
47 }
48}
49
50#[cfg(feature = "std")]
51impl<M: fmt::Debug + fmt::Display> std::error::Error for LifecycleError<M> {}