Skip to main content

tokio_fsm/
core.rs

1//! Core runtime types for tokio-fsm.
2
3/// Represents a state transition in the FSM.
4///
5/// This type is returned by FSM handlers to indicate which state the machine
6/// should transition to next. It is usually created via the [`Transition::to`]
7/// helper.
8///
9/// # Examples
10///
11/// ```rust
12/// # use tokio_fsm::Transition;
13/// # #[derive(Debug, Clone, Copy)]
14/// # enum MyFsmState { Running }
15/// async fn my_handler() -> Transition<MyFsmState> {
16///     // Perform some async logic...
17///     Transition::to(MyFsmState::Running)
18/// }
19/// ```
20#[derive(Debug)]
21pub enum Transition<T> {
22    /// Transition to the specified target state.
23    To(T),
24}
25
26impl<T> Transition<T> {
27    /// Creates a new transition to the specified target state.
28    ///
29    /// The target state must be a valid state defined within the FSM.
30    #[must_use]
31    pub fn to(state: T) -> Self {
32        Self::To(state)
33    }
34
35    /// Extracts the target state from the transition.
36    ///
37    /// Internal-only: This is typically used by the generated event loop.
38    #[must_use]
39    pub fn into_state(self) -> T {
40        match self {
41            Self::To(state) => state,
42        }
43    }
44}
45
46/// Error type returned by the FSM background task.
47///
48/// This enum distinguishes between logical errors returned by your FSM handlers
49/// and runtime failures of the Tokio task itself (for example, panics or task
50/// aborts).
51///
52/// # Type Parameters
53///
54/// * `E`: The logical error type defined in your `impl` block via `type Error =
55///   ...;`.
56///
57/// # Examples
58///
59/// ```rust,ignore
60/// use tokio_fsm::TaskError;
61///
62/// // Example of a match against a task's result
63/// match task.await {
64///     Ok(final_context) => println!("FSM finished normally."),
65///     Err(TaskError::Fsm(e)) => println!("FSM aborted with a logical error: {}", e),
66///     Err(TaskError::Join(e)) => println!("Tokio task failed (e.g. panicked): {}", e),
67/// }
68/// ```
69#[derive(Debug, thiserror::Error)]
70pub enum TaskError<E> {
71    /// The FSM handler returned a logical error, triggering a shutdown.
72    ///
73    /// This variant is used when your FSM handler returns `Result::Err(...)`.
74    #[error("FSM error: {0}")]
75    Fsm(E),
76    /// The background task failed due to a panic or explicit task abort.
77    ///
78    /// This wraps a [`tokio::task::JoinError`].
79    #[error("Task join error: {0}")]
80    Join(#[from] tokio::task::JoinError),
81}
82
83/// Error returned when applying an event to an FSM.
84///
85/// For direct FSM values, applying an event resolves when the handler has run
86/// and the state transition has either succeeded or failed. For spawned FSM
87/// handles, applying an event also reports runtime-adapter failures such as a
88/// closed event channel or an interrupted in-flight request.
89///
90/// # Type Parameters
91///
92/// * `E`: The event type generated for the FSM.
93/// * `S`: The state type generated for the FSM.
94/// * `H`: The logical error type defined in your `impl` block via `type Error =
95///   ...;`.
96#[derive(Debug, thiserror::Error)]
97pub enum ApplyError<E, S, H> {
98    /// The event has no handler for the current state.
99    #[error("event is not handled in the current FSM state")]
100    Unhandled {
101        /// State observed when the event was applied.
102        state: S,
103        /// Event that was rejected.
104        event: E,
105    },
106    /// The spawned FSM runtime is closed.
107    #[error("FSM runtime is closed")]
108    Closed(
109        /// Event that could not be applied.
110        E,
111    ),
112    /// The FSM stopped before it could answer this apply request.
113    #[error("FSM stopped before answering apply request")]
114    Interrupted,
115    /// The FSM handler failed while processing the event.
116    #[error("FSM handler failed while processing event: {0}")]
117    HandlerFailed(H),
118    /// The handler returned a state that was not declared in its `next` list.
119    #[error("FSM handler returned an undeclared transition target")]
120    InvalidTransition {
121        /// State returned by the handler.
122        state: S,
123    },
124}