canlink_hal/state.rs
1//! Backend state management.
2//!
3//! This module defines the lifecycle states of a backend.
4
5/// Backend lifecycle state.
6///
7/// Represents the current state of a backend in its lifecycle.
8/// Backends transition through these states during initialization,
9/// operation, and shutdown.
10///
11/// # State Transitions
12///
13/// ```text
14/// Uninitialized -> Initializing -> Ready -> Closing -> Closed
15/// ↓ ↓
16/// Error ←--------┘
17/// ```
18///
19/// # Examples
20///
21/// ```
22/// use canlink_hal::BackendState;
23///
24/// let state = BackendState::Uninitialized;
25/// assert!(!state.is_ready());
26///
27/// let state = BackendState::Ready;
28/// assert!(state.is_ready());
29/// ```
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
31pub enum BackendState {
32 /// Backend has not been initialized
33 #[default]
34 Uninitialized,
35
36 /// Backend is currently initializing
37 Initializing,
38
39 /// Backend is ready for operations
40 Ready,
41
42 /// Backend is closing
43 Closing,
44
45 /// Backend has been closed
46 Closed,
47
48 /// Backend encountered an error
49 Error,
50}
51
52impl BackendState {
53 /// Check if the backend is ready for operations.
54 ///
55 /// # Examples
56 ///
57 /// ```
58 /// use canlink_hal::BackendState;
59 ///
60 /// assert!(BackendState::Ready.is_ready());
61 /// assert!(!BackendState::Uninitialized.is_ready());
62 /// ```
63 #[must_use]
64 pub const fn is_ready(&self) -> bool {
65 matches!(self, Self::Ready)
66 }
67
68 /// Check if the backend is in an error state.
69 ///
70 /// # Examples
71 ///
72 /// ```
73 /// use canlink_hal::BackendState;
74 ///
75 /// assert!(BackendState::Error.is_error());
76 /// assert!(!BackendState::Ready.is_error());
77 /// ```
78 #[must_use]
79 pub const fn is_error(&self) -> bool {
80 matches!(self, Self::Error)
81 }
82
83 /// Check if the backend is closed.
84 ///
85 /// # Examples
86 ///
87 /// ```
88 /// use canlink_hal::BackendState;
89 ///
90 /// assert!(BackendState::Closed.is_closed());
91 /// assert!(!BackendState::Ready.is_closed());
92 /// ```
93 #[must_use]
94 pub const fn is_closed(&self) -> bool {
95 matches!(self, Self::Closed)
96 }
97
98 /// Check if the backend can accept operations.
99 ///
100 /// Returns true only if the backend is in the Ready state.
101 ///
102 /// # Examples
103 ///
104 /// ```
105 /// use canlink_hal::BackendState;
106 ///
107 /// assert!(BackendState::Ready.can_operate());
108 /// assert!(!BackendState::Initializing.can_operate());
109 /// assert!(!BackendState::Error.can_operate());
110 /// ```
111 #[must_use]
112 pub const fn can_operate(&self) -> bool {
113 matches!(self, Self::Ready)
114 }
115
116 /// Get a human-readable description of the state.
117 ///
118 /// # Examples
119 ///
120 /// ```
121 /// use canlink_hal::BackendState;
122 ///
123 /// assert_eq!(BackendState::Ready.description(), "Ready");
124 /// assert_eq!(BackendState::Error.description(), "Error");
125 /// ```
126 #[must_use]
127 pub const fn description(&self) -> &'static str {
128 match self {
129 Self::Uninitialized => "Uninitialized",
130 Self::Initializing => "Initializing",
131 Self::Ready => "Ready",
132 Self::Closing => "Closing",
133 Self::Closed => "Closed",
134 Self::Error => "Error",
135 }
136 }
137}
138
139impl std::fmt::Display for BackendState {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 write!(f, "{}", self.description())
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_state_checks() {
151 assert!(BackendState::Ready.is_ready());
152 assert!(!BackendState::Uninitialized.is_ready());
153
154 assert!(BackendState::Error.is_error());
155 assert!(!BackendState::Ready.is_error());
156
157 assert!(BackendState::Closed.is_closed());
158 assert!(!BackendState::Ready.is_closed());
159 }
160
161 #[test]
162 fn test_can_operate() {
163 assert!(BackendState::Ready.can_operate());
164 assert!(!BackendState::Uninitialized.can_operate());
165 assert!(!BackendState::Initializing.can_operate());
166 assert!(!BackendState::Closing.can_operate());
167 assert!(!BackendState::Closed.can_operate());
168 assert!(!BackendState::Error.can_operate());
169 }
170
171 #[test]
172 fn test_description() {
173 assert_eq!(BackendState::Uninitialized.description(), "Uninitialized");
174 assert_eq!(BackendState::Initializing.description(), "Initializing");
175 assert_eq!(BackendState::Ready.description(), "Ready");
176 assert_eq!(BackendState::Closing.description(), "Closing");
177 assert_eq!(BackendState::Closed.description(), "Closed");
178 assert_eq!(BackendState::Error.description(), "Error");
179 }
180
181 #[test]
182 fn test_display() {
183 assert_eq!(format!("{}", BackendState::Ready), "Ready");
184 assert_eq!(format!("{}", BackendState::Error), "Error");
185 }
186
187 #[test]
188 fn test_default() {
189 assert_eq!(BackendState::default(), BackendState::Uninitialized);
190 }
191}