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