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}