1use core::{fmt::Display, num::NonZeroU32};
7use internationalization::translate;
8
9pub type Result<T> = core::result::Result<T, Error>;
29
30#[derive(Debug, PartialEq, Clone, Copy, Eq)]
36#[repr(C)]
37pub enum Error {
38 FailedToInitializeFileSystem = 1,
40 PermissionDenied,
42 NotFound,
44 AlreadyExists,
46 DirectoryAlreadyExists,
48 FileSystemFull,
50 FileSystemError,
52 InvalidPath,
54 InvalidFile,
56 InvalidDirectory,
58 InvalidSymbolicLink,
60 Unknown,
62 InvalidIdentifier,
64 FailedToGetTaskInformations,
66 FailedToGetUsersInformations,
68 TooManyMountedFileSystems,
70 TooManyOpenFiles,
72 InternalError,
74 InvalidMode,
76 UnsupportedOperation,
78 RessourceBusy,
80 AlreadyInitialized,
82 NotInitialized,
84 FailedToGetUsersManagerInstance,
86 FailedToGetTaskManagerInstance,
88 InvalidParameter,
90 InvalidFlags,
92 NotDirectory,
94 IsDirectory,
96 InputOutput,
98 DirectoryNotEmpty,
100 FileTooLarge,
102 NoAttribute,
104 NameTooLong,
106 Corrupted,
108 NoMemory,
110 NoSpaceLeft,
112 TimeError,
114 InvalidInode,
116 NotMounted,
118 AlreadyMounted,
120 InvalidContext,
122 Other,
124}
125
126impl core::error::Error for Error {}
127
128impl Error {
129 pub fn get_discriminant(&self) -> NonZeroU32 {
149 unsafe { NonZeroU32::new_unchecked(*self as u32) }
150 }
151}
152
153impl From<task::Error> for Error {
157 fn from(_: task::Error) -> Self {
158 Error::FailedToGetTaskInformations
159 }
160}
161
162impl From<users::Error> for Error {
166 fn from(_: users::Error) -> Self {
167 Error::FailedToGetUsersInformations
168 }
169}
170
171impl From<Error> for NonZeroU32 {
175 fn from(error: Error) -> Self {
176 error.get_discriminant()
177 }
178}
179
180impl Display for Error {
184 fn fmt(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
185 let string = match self {
186 Error::FailedToInitializeFileSystem => translate!("Failed to initialize file system"),
187 Error::PermissionDenied => translate!("Permission denied"),
188 Error::NotFound => translate!("Not found"),
189 Error::AlreadyExists => translate!("Already exists"),
190 Error::DirectoryAlreadyExists => translate!("Directory already exists"),
191 Error::FileSystemFull => translate!("File system full"),
192 Error::FileSystemError => translate!("File system error"),
193 Error::InvalidPath => translate!("Invalid path"),
194 Error::InvalidFile => translate!("Invalid file"),
195 Error::InvalidDirectory => translate!("Invalid directory"),
196 Error::InvalidSymbolicLink => translate!("Invalid symbolic link"),
197 Error::Unknown => translate!("Unknown"),
198 Error::InvalidIdentifier => translate!("Invalid identifier"),
199 Error::FailedToGetTaskInformations => translate!("Failed to get task informations"),
200 Error::FailedToGetUsersInformations => translate!("Failed to get users informations"),
201 Error::TooManyMountedFileSystems => translate!("Too many mounted file systems"),
202 Error::TooManyOpenFiles => translate!("Too many open files"),
203 Error::InternalError => translate!("Internal error"),
204 Error::InvalidMode => translate!("Invalid mode"),
205 Error::UnsupportedOperation => translate!("Unsupported operation"),
206 Error::RessourceBusy => translate!("Ressource busy"),
207 Error::AlreadyInitialized => translate!("Already initialized"),
208 Error::NotInitialized => translate!("Not initialized"),
209 Error::FailedToGetUsersManagerInstance => {
210 translate!("Failed to get users manager instance")
211 }
212 Error::FailedToGetTaskManagerInstance => {
213 translate!("Failed to get task manager instance")
214 }
215 Error::InvalidParameter => translate!("Invalid parameter"),
216 Error::InvalidFlags => translate!("Invalid flags"),
217 Error::NotDirectory => translate!("Not directory"),
218 Error::IsDirectory => translate!("Is directory"),
219 Error::InputOutput => translate!("Input output"),
220 Error::DirectoryNotEmpty => translate!("Directory not empty"),
221 Error::FileTooLarge => translate!("File too large"),
222 Error::NoAttribute => translate!("No attribute"),
223 Error::NameTooLong => translate!("Name too long"),
224 Error::Corrupted => translate!("Corrupted"),
225 Error::NoMemory => translate!("No memory"),
226 Error::NoSpaceLeft => translate!("No space left"),
227 Error::TimeError => translate!("Time error"),
228 Error::InvalidInode => translate!("Invalid inode"),
229 Error::NotMounted => translate!("Not mounted"),
230 Error::AlreadyMounted => translate!("Already mounted"),
231 Error::InvalidContext => translate!("Invalid context"),
232 Error::Other => translate!("Other"),
233 };
234
235 write!(formatter, "{string}")
236 }
237}
238
239impl embedded_io_async::Error for Error {
240 fn kind(&self) -> embedded_io_async::ErrorKind {
241 match self {
242 Error::PermissionDenied => embedded_io_async::ErrorKind::PermissionDenied,
243 Error::NotFound => embedded_io_async::ErrorKind::NotFound,
244 Error::AlreadyExists | Error::DirectoryAlreadyExists => {
245 embedded_io_async::ErrorKind::AlreadyExists
246 }
247 Error::FileSystemFull | Error::NoSpaceLeft => embedded_io_async::ErrorKind::OutOfMemory,
248 Error::InputOutput => embedded_io_async::ErrorKind::Interrupted,
249 _ => embedded_io_async::ErrorKind::Other,
250 }
251 }
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257 use alloc::format;
258
259 #[test]
260 fn test_error_discriminants() {
261 assert_eq!(
263 Error::FailedToInitializeFileSystem.get_discriminant().get(),
264 1
265 );
266 assert_eq!(Error::PermissionDenied.get_discriminant().get(), 2);
267 assert_eq!(Error::NotFound.get_discriminant().get(), 3);
268 assert_eq!(Error::AlreadyExists.get_discriminant().get(), 4);
269 assert_eq!(Error::DirectoryAlreadyExists.get_discriminant().get(), 5);
270
271 assert_eq!(Error::FileSystemFull.get_discriminant().get(), 6);
273 assert_eq!(Error::FileSystemError.get_discriminant().get(), 7);
274 assert_eq!(Error::InvalidPath.get_discriminant().get(), 8);
275 }
276
277 #[test]
278 fn test_error_display() {
279 assert_eq!(
281 format!("{}", Error::FailedToInitializeFileSystem),
282 "Failed to initialize file system"
283 );
284 assert_eq!(format!("{}", Error::PermissionDenied), "Permission denied");
285 assert_eq!(format!("{}", Error::NotFound), "Not found");
286 assert_eq!(format!("{}", Error::AlreadyExists), "Already exists");
287 assert_eq!(
288 format!("{}", Error::DirectoryAlreadyExists),
289 "Directory already exists"
290 );
291 assert_eq!(format!("{}", Error::FileSystemFull), "File system full");
292 assert_eq!(format!("{}", Error::FileSystemError), "File system error");
293 assert_eq!(format!("{}", Error::InvalidPath), "Invalid path");
294 assert_eq!(format!("{}", Error::InvalidFile), "Invalid file");
295 assert_eq!(format!("{}", Error::InvalidDirectory), "Invalid directory");
296 assert_eq!(
297 format!("{}", Error::InvalidSymbolicLink),
298 "Invalid symbolic link"
299 );
300 assert_eq!(format!("{}", Error::Unknown), "Unknown");
301 assert_eq!(
302 format!("{}", Error::InvalidIdentifier),
303 "Invalid identifier"
304 );
305 assert_eq!(
306 format!("{}", Error::FailedToGetTaskInformations),
307 "Failed to get task informations"
308 );
309 assert_eq!(
310 format!("{}", Error::FailedToGetUsersInformations),
311 "Failed to get users informations"
312 );
313 assert_eq!(
314 format!("{}", Error::TooManyMountedFileSystems),
315 "Too many mounted file systems"
316 );
317 assert_eq!(
318 format!("{}", Error::TooManyOpenFiles),
319 "Too many open files"
320 );
321 assert_eq!(format!("{}", Error::InternalError), "Internal error");
322 assert_eq!(format!("{}", Error::InvalidMode), "Invalid mode");
323 assert_eq!(
324 format!("{}", Error::UnsupportedOperation),
325 "Unsupported operation"
326 );
327 assert_eq!(format!("{}", Error::RessourceBusy), "Ressource busy");
328 assert_eq!(
329 format!("{}", Error::AlreadyInitialized),
330 "Already initialized"
331 );
332 assert_eq!(format!("{}", Error::NotInitialized), "Not initialized");
333 assert_eq!(
334 format!("{}", Error::FailedToGetUsersManagerInstance),
335 "Failed to get users manager instance"
336 );
337 assert_eq!(
338 format!("{}", Error::FailedToGetTaskManagerInstance),
339 "Failed to get task manager instance"
340 );
341 assert_eq!(format!("{}", Error::InvalidParameter), "Invalid parameter");
342 assert_eq!(format!("{}", Error::InvalidFlags), "Invalid flags");
343 assert_eq!(format!("{}", Error::NotDirectory), "Not directory");
344 assert_eq!(format!("{}", Error::IsDirectory), "Is directory");
345 assert_eq!(format!("{}", Error::InputOutput), "Input output");
346 assert_eq!(
347 format!("{}", Error::DirectoryNotEmpty),
348 "Directory not empty"
349 );
350 assert_eq!(format!("{}", Error::FileTooLarge), "File too large");
351 assert_eq!(format!("{}", Error::NoAttribute), "No attribute");
352 assert_eq!(format!("{}", Error::NameTooLong), "Name too long");
353 assert_eq!(format!("{}", Error::Corrupted), "Corrupted");
354 assert_eq!(format!("{}", Error::NoMemory), "No memory");
355 assert_eq!(format!("{}", Error::NoSpaceLeft), "No space left");
356 assert_eq!(format!("{}", Error::TimeError), "Time error");
357 assert_eq!(format!("{}", Error::InvalidInode), "Invalid inode");
358 assert_eq!(format!("{}", Error::Other), "Other");
359 }
360
361 #[test]
362 fn test_error_debug() {
363 let error = Error::PermissionDenied;
365 let debug_str = format!("{error:?}");
366 assert_eq!(debug_str, "PermissionDenied");
367 }
368
369 #[test]
370 fn test_error_equality() {
371 let error1 = Error::NotFound;
373 let error2 = Error::NotFound;
374 let error3 = Error::PermissionDenied;
375
376 assert_eq!(error1, error2);
377 assert_ne!(error1, error3);
378
379 let cloned = error1;
380 assert_eq!(error1, cloned);
381 }
382
383 #[test]
384 fn test_error_conversions() {
385 let error = Error::NotFound;
387 let discriminant: NonZeroU32 = error.into();
388 assert_eq!(discriminant.get(), 3);
389
390 assert_eq!(error.get_discriminant().get(), 3);
392 }
393
394 #[test]
395 fn test_result_type() {
396 let success: Result<i32> = Ok(42);
398 let failure: Result<i32> = Err(Error::PermissionDenied);
399
400 assert_eq!(success, Ok(42));
401
402 assert_eq!(failure, Err(Error::PermissionDenied));
403 }
404
405 #[test]
406 fn test_error_categories() {
407 assert!(matches!(
411 Error::FailedToInitializeFileSystem.get_discriminant().get(),
412 1
413 ));
414 assert!(matches!(
415 Error::AlreadyInitialized.get_discriminant().get(),
416 22
417 ));
418 assert!(matches!(Error::NotInitialized.get_discriminant().get(), 23));
419
420 assert!(matches!(
422 Error::PermissionDenied.get_discriminant().get(),
423 2
424 ));
425 assert!(matches!(Error::InvalidMode.get_discriminant().get(), 19));
426
427 assert!(matches!(Error::NotFound.get_discriminant().get(), 3));
429 assert!(matches!(Error::AlreadyExists.get_discriminant().get(), 4));
430 assert!(matches!(
431 Error::DirectoryAlreadyExists.get_discriminant().get(),
432 5
433 ));
434 }
435
436 #[test]
437 fn test_error_copy_semantics() {
438 let error = Error::FileSystemFull;
440 let copied = error; assert_eq!(error, Error::FileSystemFull);
444 assert_eq!(copied, Error::FileSystemFull);
445 assert_eq!(error, copied);
446 }
447
448 #[test]
449 fn test_error_size() {
450 use core::mem::size_of;
452
453 assert!(size_of::<Error>() <= 4); }
456
457 #[test]
458 fn test_nonzero_conversion() {
459 let errors = [
461 Error::FailedToInitializeFileSystem,
462 Error::PermissionDenied,
463 Error::NotFound,
464 Error::AlreadyExists,
465 Error::DirectoryAlreadyExists,
466 Error::FileSystemFull,
467 Error::FileSystemError,
468 Error::InvalidPath,
469 Error::InvalidFile,
470 Error::InvalidDirectory,
471 Error::InvalidSymbolicLink,
472 Error::Unknown,
473 Error::InvalidIdentifier,
474 Error::FailedToGetTaskInformations,
475 Error::FailedToGetUsersInformations,
476 Error::TooManyMountedFileSystems,
477 Error::TooManyOpenFiles,
478 Error::InternalError,
479 Error::InvalidMode,
480 Error::UnsupportedOperation,
481 Error::RessourceBusy,
482 Error::AlreadyInitialized,
483 Error::NotInitialized,
484 Error::FailedToGetUsersManagerInstance,
485 Error::FailedToGetTaskManagerInstance,
486 Error::InvalidParameter,
487 Error::InvalidFlags,
488 Error::NotDirectory,
489 Error::IsDirectory,
490 Error::InputOutput,
491 Error::DirectoryNotEmpty,
492 Error::FileTooLarge,
493 Error::NoAttribute,
494 Error::NameTooLong,
495 Error::Corrupted,
496 Error::NoMemory,
497 Error::NoSpaceLeft,
498 Error::TimeError,
499 Error::InvalidInode,
500 Error::Other,
501 ];
502
503 for error in errors.iter() {
504 let discriminant = error.get_discriminant();
505 assert!(discriminant.get() > 0);
506
507 let converted: NonZeroU32 = (*error).into();
508 assert_eq!(discriminant, converted);
509 }
510 }
511}