1use core::{fmt::Display, num::NonZeroU32};
7
8pub type Result<T> = core::result::Result<T, Error>;
28
29#[derive(Debug, PartialEq, Clone, Copy, Eq)]
35#[repr(C)]
36pub enum Error {
37 FailedToInitializeFileSystem = 1,
39 PermissionDenied,
41 NotFound,
43 AlreadyExists,
45 DirectoryAlreadyExists,
47 FileSystemFull,
49 FileSystemError,
51 InvalidPath,
53 InvalidFile,
55 InvalidDirectory,
57 InvalidSymbolicLink,
59 Unknown,
61 InvalidIdentifier,
63 FailedToGetTaskInformations,
65 FailedToGetUsersInformations,
67 TooManyMountedFileSystems,
69 TooManyOpenFiles,
71 InternalError,
73 InvalidMode,
75 UnsupportedOperation,
77 RessourceBusy,
79 AlreadyInitialized,
81 NotInitialized,
83 FailedToGetUsersManagerInstance,
85 FailedToGetTaskManagerInstance,
87 InvalidParameter,
89 InvalidFlags,
91 NotDirectory,
93 IsDirectory,
95 InputOutput,
97 DirectoryNotEmpty,
99 FileTooLarge,
101 NoAttribute,
103 NameTooLong,
105 Corrupted,
107 NoMemory,
109 NoSpaceLeft,
111 TimeError,
113 InvalidInode,
115 NotMounted,
117 AlreadyMounted,
119 InvalidContext,
121 Other,
123}
124
125impl core::error::Error for Error {}
126
127impl Error {
128 pub fn get_discriminant(&self) -> NonZeroU32 {
148 unsafe { NonZeroU32::new_unchecked(*self as u32) }
149 }
150}
151
152impl From<task::Error> for Error {
156 fn from(_: task::Error) -> Self {
157 Error::FailedToGetTaskInformations
158 }
159}
160
161impl From<users::Error> for Error {
165 fn from(_: users::Error) -> Self {
166 Error::FailedToGetUsersInformations
167 }
168}
169
170impl From<Error> for NonZeroU32 {
174 fn from(error: Error) -> Self {
175 error.get_discriminant()
176 }
177}
178
179impl Display for Error {
183 fn fmt(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
184 let string = match self {
185 Error::FailedToInitializeFileSystem => "Failed to initialize file system",
186 Error::PermissionDenied => "Permission denied",
187 Error::NotFound => "Not found",
188 Error::AlreadyExists => "Already exists",
189 Error::DirectoryAlreadyExists => "Directory already exists",
190 Error::FileSystemFull => "File system full",
191 Error::FileSystemError => "File system error",
192 Error::InvalidPath => "Invalid path",
193 Error::InvalidFile => "Invalid file",
194 Error::InvalidDirectory => "Invalid directory",
195 Error::InvalidSymbolicLink => "Invalid symbolic link",
196 Error::Unknown => "Unknown",
197 Error::InvalidIdentifier => "Invalid identifier",
198 Error::FailedToGetTaskInformations => "Failed to get task informations",
199 Error::FailedToGetUsersInformations => "Failed to get users informations",
200 Error::TooManyMountedFileSystems => "Too many mounted file systems",
201 Error::TooManyOpenFiles => "Too many open files",
202 Error::InternalError => "Internal error",
203 Error::InvalidMode => "Invalid mode",
204 Error::UnsupportedOperation => "Unsupported operation",
205 Error::RessourceBusy => "Ressource busy",
206 Error::AlreadyInitialized => "Already initialized",
207 Error::NotInitialized => "Not initialized",
208 Error::FailedToGetUsersManagerInstance => "Failed to get users manager instance",
209 Error::FailedToGetTaskManagerInstance => "Failed to get task manager instance",
210 Error::InvalidParameter => "Invalid parameter",
211 Error::InvalidFlags => "Invalid flags",
212 Error::NotDirectory => "Not directory",
213 Error::IsDirectory => "Is directory",
214 Error::InputOutput => "Input output",
215 Error::DirectoryNotEmpty => "Directory not empty",
216 Error::FileTooLarge => "File too large",
217 Error::NoAttribute => "No attribute",
218 Error::NameTooLong => "Name too long",
219 Error::Corrupted => "Corrupted",
220 Error::NoMemory => "No memory",
221 Error::NoSpaceLeft => "No space left",
222 Error::TimeError => "Time error",
223 Error::InvalidInode => "Invalid inode",
224 Error::NotMounted => "Not mounted",
225 Error::AlreadyMounted => "Already mounted",
226 Error::InvalidContext => "Invalid context",
227 Error::Other => "Other",
228 };
229
230 write!(formatter, "{string}")
231 }
232}
233
234impl embedded_io_async::Error for Error {
235 fn kind(&self) -> embedded_io_async::ErrorKind {
236 match self {
237 Error::PermissionDenied => embedded_io_async::ErrorKind::PermissionDenied,
238 Error::NotFound => embedded_io_async::ErrorKind::NotFound,
239 Error::AlreadyExists | Error::DirectoryAlreadyExists => {
240 embedded_io_async::ErrorKind::AlreadyExists
241 }
242 Error::FileSystemFull | Error::NoSpaceLeft => embedded_io_async::ErrorKind::OutOfMemory,
243 Error::InputOutput => embedded_io_async::ErrorKind::Interrupted,
244 _ => embedded_io_async::ErrorKind::Other,
245 }
246 }
247}
248
249#[cfg(test)]
250mod tests {
251 use super::*;
252 use alloc::format;
253
254 #[test]
255 fn test_error_discriminants() {
256 assert_eq!(
258 Error::FailedToInitializeFileSystem.get_discriminant().get(),
259 1
260 );
261 assert_eq!(Error::PermissionDenied.get_discriminant().get(), 2);
262 assert_eq!(Error::NotFound.get_discriminant().get(), 3);
263 assert_eq!(Error::AlreadyExists.get_discriminant().get(), 4);
264 assert_eq!(Error::DirectoryAlreadyExists.get_discriminant().get(), 5);
265
266 assert_eq!(Error::FileSystemFull.get_discriminant().get(), 6);
268 assert_eq!(Error::FileSystemError.get_discriminant().get(), 7);
269 assert_eq!(Error::InvalidPath.get_discriminant().get(), 8);
270 }
271
272 #[test]
273 fn test_error_display() {
274 assert_eq!(
276 format!("{}", Error::FailedToInitializeFileSystem),
277 "Failed to initialize file system"
278 );
279 assert_eq!(format!("{}", Error::PermissionDenied), "Permission denied");
280 assert_eq!(format!("{}", Error::NotFound), "Not found");
281 assert_eq!(format!("{}", Error::AlreadyExists), "Already exists");
282 assert_eq!(
283 format!("{}", Error::DirectoryAlreadyExists),
284 "Directory already exists"
285 );
286 assert_eq!(format!("{}", Error::FileSystemFull), "File system full");
287 assert_eq!(format!("{}", Error::FileSystemError), "File system error");
288 assert_eq!(format!("{}", Error::InvalidPath), "Invalid path");
289 assert_eq!(format!("{}", Error::InvalidFile), "Invalid file");
290 assert_eq!(format!("{}", Error::InvalidDirectory), "Invalid directory");
291 assert_eq!(
292 format!("{}", Error::InvalidSymbolicLink),
293 "Invalid symbolic link"
294 );
295 assert_eq!(format!("{}", Error::Unknown), "Unknown");
296 assert_eq!(
297 format!("{}", Error::InvalidIdentifier),
298 "Invalid identifier"
299 );
300 assert_eq!(
301 format!("{}", Error::FailedToGetTaskInformations),
302 "Failed to get task informations"
303 );
304 assert_eq!(
305 format!("{}", Error::FailedToGetUsersInformations),
306 "Failed to get users informations"
307 );
308 assert_eq!(
309 format!("{}", Error::TooManyMountedFileSystems),
310 "Too many mounted file systems"
311 );
312 assert_eq!(
313 format!("{}", Error::TooManyOpenFiles),
314 "Too many open files"
315 );
316 assert_eq!(format!("{}", Error::InternalError), "Internal error");
317 assert_eq!(format!("{}", Error::InvalidMode), "Invalid mode");
318 assert_eq!(
319 format!("{}", Error::UnsupportedOperation),
320 "Unsupported operation"
321 );
322 assert_eq!(format!("{}", Error::RessourceBusy), "Ressource busy");
323 assert_eq!(
324 format!("{}", Error::AlreadyInitialized),
325 "Already initialized"
326 );
327 assert_eq!(format!("{}", Error::NotInitialized), "Not initialized");
328 assert_eq!(
329 format!("{}", Error::FailedToGetUsersManagerInstance),
330 "Failed to get users manager instance"
331 );
332 assert_eq!(
333 format!("{}", Error::FailedToGetTaskManagerInstance),
334 "Failed to get task manager instance"
335 );
336 assert_eq!(format!("{}", Error::InvalidParameter), "Invalid parameter");
337 assert_eq!(format!("{}", Error::InvalidFlags), "Invalid flags");
338 assert_eq!(format!("{}", Error::NotDirectory), "Not directory");
339 assert_eq!(format!("{}", Error::IsDirectory), "Is directory");
340 assert_eq!(format!("{}", Error::InputOutput), "Input output");
341 assert_eq!(
342 format!("{}", Error::DirectoryNotEmpty),
343 "Directory not empty"
344 );
345 assert_eq!(format!("{}", Error::FileTooLarge), "File too large");
346 assert_eq!(format!("{}", Error::NoAttribute), "No attribute");
347 assert_eq!(format!("{}", Error::NameTooLong), "Name too long");
348 assert_eq!(format!("{}", Error::Corrupted), "Corrupted");
349 assert_eq!(format!("{}", Error::NoMemory), "No memory");
350 assert_eq!(format!("{}", Error::NoSpaceLeft), "No space left");
351 assert_eq!(format!("{}", Error::TimeError), "Time error");
352 assert_eq!(format!("{}", Error::InvalidInode), "Invalid inode");
353 assert_eq!(format!("{}", Error::Other), "Other");
354 }
355
356 #[test]
357 fn test_error_debug() {
358 let error = Error::PermissionDenied;
360 let debug_str = format!("{error:?}");
361 assert_eq!(debug_str, "PermissionDenied");
362 }
363
364 #[test]
365 fn test_error_equality() {
366 let error1 = Error::NotFound;
368 let error2 = Error::NotFound;
369 let error3 = Error::PermissionDenied;
370
371 assert_eq!(error1, error2);
372 assert_ne!(error1, error3);
373
374 let cloned = error1;
375 assert_eq!(error1, cloned);
376 }
377
378 #[test]
379 fn test_error_conversions() {
380 let error = Error::NotFound;
382 let discriminant: NonZeroU32 = error.into();
383 assert_eq!(discriminant.get(), 3);
384
385 assert_eq!(error.get_discriminant().get(), 3);
387 }
388
389 #[test]
390 fn test_result_type() {
391 let success: Result<i32> = Ok(42);
393 let failure: Result<i32> = Err(Error::PermissionDenied);
394
395 assert_eq!(success, Ok(42));
396
397 assert_eq!(failure, Err(Error::PermissionDenied));
398 }
399
400 #[test]
401 fn test_error_categories() {
402 assert!(matches!(
406 Error::FailedToInitializeFileSystem.get_discriminant().get(),
407 1
408 ));
409 assert!(matches!(
410 Error::AlreadyInitialized.get_discriminant().get(),
411 22
412 ));
413 assert!(matches!(Error::NotInitialized.get_discriminant().get(), 23));
414
415 assert!(matches!(
417 Error::PermissionDenied.get_discriminant().get(),
418 2
419 ));
420 assert!(matches!(Error::InvalidMode.get_discriminant().get(), 19));
421
422 assert!(matches!(Error::NotFound.get_discriminant().get(), 3));
424 assert!(matches!(Error::AlreadyExists.get_discriminant().get(), 4));
425 assert!(matches!(
426 Error::DirectoryAlreadyExists.get_discriminant().get(),
427 5
428 ));
429 }
430
431 #[test]
432 fn test_error_copy_semantics() {
433 let error = Error::FileSystemFull;
435 let copied = error; assert_eq!(error, Error::FileSystemFull);
439 assert_eq!(copied, Error::FileSystemFull);
440 assert_eq!(error, copied);
441 }
442
443 #[test]
444 fn test_error_size() {
445 use core::mem::size_of;
447
448 assert!(size_of::<Error>() <= 4); }
451
452 #[test]
453 fn test_nonzero_conversion() {
454 let errors = [
456 Error::FailedToInitializeFileSystem,
457 Error::PermissionDenied,
458 Error::NotFound,
459 Error::AlreadyExists,
460 Error::DirectoryAlreadyExists,
461 Error::FileSystemFull,
462 Error::FileSystemError,
463 Error::InvalidPath,
464 Error::InvalidFile,
465 Error::InvalidDirectory,
466 Error::InvalidSymbolicLink,
467 Error::Unknown,
468 Error::InvalidIdentifier,
469 Error::FailedToGetTaskInformations,
470 Error::FailedToGetUsersInformations,
471 Error::TooManyMountedFileSystems,
472 Error::TooManyOpenFiles,
473 Error::InternalError,
474 Error::InvalidMode,
475 Error::UnsupportedOperation,
476 Error::RessourceBusy,
477 Error::AlreadyInitialized,
478 Error::NotInitialized,
479 Error::FailedToGetUsersManagerInstance,
480 Error::FailedToGetTaskManagerInstance,
481 Error::InvalidParameter,
482 Error::InvalidFlags,
483 Error::NotDirectory,
484 Error::IsDirectory,
485 Error::InputOutput,
486 Error::DirectoryNotEmpty,
487 Error::FileTooLarge,
488 Error::NoAttribute,
489 Error::NameTooLong,
490 Error::Corrupted,
491 Error::NoMemory,
492 Error::NoSpaceLeft,
493 Error::TimeError,
494 Error::InvalidInode,
495 Error::Other,
496 ];
497
498 for error in errors.iter() {
499 let discriminant = error.get_discriminant();
500 assert!(discriminant.get() > 0);
501
502 let converted: NonZeroU32 = (*error).into();
503 assert_eq!(discriminant, converted);
504 }
505 }
506}