1use core::{fmt, num::NonZeroU32};
2use internationalization::translate;
3
4pub type Result<T> = core::result::Result<T, Error>;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[repr(u8)]
8pub enum Error {
9 InvalidTaskIdentifier = 1,
10 InvalidSpawnerIdentifier,
11 ThreadNotRegistered,
12 ThreadAlreadyRegistered,
13 FailedToCreateThread,
14 NoThreadForTask,
15 FailedToSpawnThread,
16 InvalidEnvironmentVariable,
17 TooManyTasks,
18 TooManySpawners,
19 AlreadyInitialized,
20 AlreadySet,
21 NotInitialized,
22 NoSpawnerAvailable,
23}
24
25impl fmt::Display for Error {
26 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
27 match self {
28 Error::InvalidTaskIdentifier => write!(f, translate!("InvalidTaskIdentifier")),
29 Error::InvalidSpawnerIdentifier => write!(f, translate!("InvalidSpawnerIdentifier")),
30 Error::ThreadNotRegistered => write!(f, translate!("ThreadNotRegistered")),
31 Error::ThreadAlreadyRegistered => write!(f, translate!("ThreadAlreadyRegistered")),
32 Error::FailedToCreateThread => write!(f, translate!("FailedToCreateThread")),
33 Error::NoThreadForTask => write!(f, translate!("NoThreadForTask")),
34 Error::FailedToSpawnThread => write!(f, translate!("FailedToSpawnThread")),
35 Error::InvalidEnvironmentVariable => {
36 write!(f, translate!("InvalidEnvironmentVariable"))
37 }
38 Error::TooManyTasks => write!(f, translate!("TooManyTasks")),
39 Error::TooManySpawners => write!(f, translate!("TooManySpawners")),
40 Error::AlreadyInitialized => write!(f, translate!("AlreadyInitialized")),
41 Error::AlreadySet => write!(f, translate!("AlreadySet")),
42 Error::NotInitialized => write!(f, translate!("NotInitialized")),
43 Error::NoSpawnerAvailable => write!(f, translate!("NoSpawnerAvailable")),
44 }
45 }
46}
47
48impl core::error::Error for Error {}
49
50impl From<Error> for NonZeroU32 {
51 fn from(error: Error) -> Self {
52 unsafe { NonZeroU32::new_unchecked(error as u32) }
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use std::format;
60 use std::string::{String, ToString};
61 use std::vec;
62
63 #[test]
64 fn test_error_type_display() {
65 let error = Error::InvalidTaskIdentifier;
66 let display_string = format!("{error}");
67 assert_eq!(display_string, "Invalid task identifier");
68
69 let error = Error::TooManyTasks;
70 let display_string = format!("{error}");
71 assert_eq!(display_string, "Too many tasks");
72 }
73
74 #[test]
75 fn test_error_type_debug() {
76 let error = Error::InvalidSpawnerIdentifier;
77 let debug_string = format!("{error:?}");
78 assert_eq!(debug_string, "InvalidSpawnerIdentifier");
79
80 let error = Error::ThreadNotRegistered;
81 let debug_string = format!("{error:?}");
82 assert_eq!(debug_string, "ThreadNotRegistered");
83 }
84
85 #[test]
86 fn test_error_type_clone() {
87 let error1 = Error::FailedToCreateThread;
88 let error2 = error1.clone();
89
90 assert_eq!(format!("{error1:?}"), format!("{:?}", error2));
91 }
92
93 #[test]
94 fn test_all_error_variants() {
95 let errors = vec![
96 Error::InvalidTaskIdentifier,
97 Error::InvalidSpawnerIdentifier,
98 Error::ThreadNotRegistered,
99 Error::ThreadAlreadyRegistered,
100 Error::FailedToCreateThread,
101 Error::NoThreadForTask,
102 Error::FailedToSpawnThread,
103 Error::InvalidEnvironmentVariable,
104 Error::TooManyTasks,
105 Error::TooManySpawners,
106 Error::AlreadyInitialized,
107 Error::AlreadySet,
108 Error::NotInitialized,
109 Error::NoSpawnerAvailable,
110 ];
111
112 for error in errors {
114 let debug_str = format!("{error:?}");
115 let display_str = format!("{error}");
116
117 assert!(!debug_str.is_empty());
118 assert!(!display_str.is_empty());
119 }
120 }
121
122 #[test]
123 fn test_error_to_nonzero_u32_conversion() {
124 let errors_and_expected_values = vec![
125 (Error::InvalidTaskIdentifier, 1u32),
126 (Error::InvalidSpawnerIdentifier, 2u32),
127 (Error::ThreadNotRegistered, 3u32),
128 (Error::ThreadAlreadyRegistered, 4u32),
129 (Error::FailedToCreateThread, 5u32),
130 (Error::NoThreadForTask, 6u32),
131 (Error::FailedToSpawnThread, 7u32),
132 (Error::InvalidEnvironmentVariable, 8u32),
133 (Error::TooManyTasks, 9u32),
134 (Error::TooManySpawners, 10u32),
135 (Error::AlreadyInitialized, 11u32),
136 (Error::AlreadySet, 12u32),
137 (Error::NotInitialized, 13u32),
138 (Error::NoSpawnerAvailable, 14u32),
139 ];
140
141 for (error, expected_value) in errors_and_expected_values {
142 let non_zero: NonZeroU32 = error.into();
143 assert_eq!(non_zero.get(), expected_value);
144 }
145 }
146
147 #[test]
148 fn test_result_type_ok() {
149 let result: Result<i32> = Ok(42);
150 assert!(result.is_ok());
151 if let Ok(value) = result {
152 assert_eq!(value, 42);
153 }
154 }
155
156 #[test]
157 fn test_result_type_err() {
158 let result: Result<i32> = Err(Error::InvalidTaskIdentifier);
159 assert!(result.is_err());
160
161 if let Err(error) = result {
162 assert_eq!(format!("{error:?}"), "InvalidTaskIdentifier");
163 }
164 }
165
166 #[test]
167 fn test_error_in_result_chain() {
168 fn might_fail(should_fail: bool) -> Result<String> {
169 if should_fail {
170 Err(Error::TooManyTasks)
171 } else {
172 Ok("Success".to_string())
173 }
174 }
175
176 let success_result = might_fail(false);
177 assert!(success_result.is_ok());
178 if let Ok(value) = success_result {
179 assert_eq!(value, "Success");
180 }
181
182 let failure_result = might_fail(true);
183 assert!(failure_result.is_err());
184
185 if let Err(error) = failure_result {
186 assert_eq!(format!("{error:?}"), "TooManyTasks");
187 }
188 }
189
190 #[test]
191 fn test_error_propagation() {
192 fn inner_function() -> Result<i32> {
193 Err(Error::NotInitialized)
194 }
195
196 fn outer_function() -> Result<String> {
197 let _value = inner_function()?;
198 Ok("This won't be reached".to_string())
199 }
200
201 let result = outer_function();
202 assert!(result.is_err());
203
204 if let Err(error) = result {
205 assert_eq!(format!("{error:?}"), "NotInitialized");
206 }
207 }
208
209 #[test]
210 fn test_error_size() {
211 assert!(std::mem::size_of::<Error>() <= 8);
213 }
214
215 #[test]
216 fn test_specific_error_scenarios() {
217 let env_error = Error::InvalidEnvironmentVariable;
219 let display_str = format!("{env_error}");
220 let non_zero: NonZeroU32 = env_error.into();
221 assert_eq!(non_zero.get(), 8u32);
222 assert_eq!(display_str, "Invalid environment variable");
223
224 let task_error = Error::InvalidTaskIdentifier;
226 assert_eq!(format!("{task_error}"), "Invalid task identifier");
227
228 let spawner_error = Error::InvalidSpawnerIdentifier;
229 assert_eq!(format!("{spawner_error}"), "Invalid spawner identifier");
230 }
231}