1 use crate::fs::{PathBuf, PathError}; 2 use alloc::string::FromUtf8Error; 3 use core::fmt::{self, Debug, Display, Formatter}; 4 5 /// All errors that can happen when working with the [`FileSystem`]. 6 /// 7 /// [`FileSystem`]: super::FileSystem 8 #[derive(Debug, Clone, PartialEq, Eq)] 9 pub enum Error { 10 /// IO (low-level UEFI-errors) errors. See [`IoError`]. 11 Io(IoError), 12 /// Path-related errors. See [`PathError`]. 13 Path(PathError), 14 /// Can't parse file content as UTF-8. See [`FromUtf8Error`]. 15 Utf8Encoding(FromUtf8Error), 16 } 17 18 impl Display for Error { fmt(&self, f: &mut Formatter<'_>) -> fmt::Result19 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 20 match self { 21 Self::Io(_) => write!(f, "IO error"), 22 Self::Path(_) => write!(f, "path error"), 23 Self::Utf8Encoding(_) => write!(f, "UTF-8 encoding error"), 24 } 25 } 26 } 27 28 /// UEFI-error with context when working with the underlying UEFI file protocol. 29 #[derive(Debug, Clone, PartialEq, Eq)] 30 pub struct IoError { 31 /// The path that led to the error. 32 pub path: PathBuf, 33 /// The context in which the path was used. 34 pub context: IoErrorContext, 35 /// The underlying UEFI error. 36 pub uefi_error: crate::Error, 37 } 38 39 impl Display for IoError { fmt(&self, f: &mut Formatter<'_>) -> fmt::Result40 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 41 write!(f, "IO error for path {}: {}", self.path, self.context) 42 } 43 } 44 45 /// Enum that further specifies the context in that an [`Error`] occurred. 46 #[derive(Debug, Clone, PartialEq, Eq)] 47 pub enum IoErrorContext { 48 /// Can't delete the directory. 49 CantDeleteDirectory, 50 /// Can't delete the file. 51 CantDeleteFile, 52 /// Error flushing file. 53 FlushFailure, 54 /// Can't open the root directory of the underlying volume. 55 CantOpenVolume, 56 /// Error while reading the metadata of the file. 57 Metadata, 58 /// Could not open the given path. One possible reason is that the file does 59 /// not exist. 60 OpenError, 61 /// Error reading file. 62 ReadFailure, 63 /// Error writing bytes. 64 WriteFailure, 65 /// The path exists but does not correspond to a directory when a directory 66 /// was expected. 67 NotADirectory, 68 /// The path exists but does not correspond to a file when a file was 69 /// expected. 70 NotAFile, 71 } 72 73 impl Display for IoErrorContext { fmt(&self, f: &mut Formatter<'_>) -> fmt::Result74 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 75 let s = match self { 76 Self::CantDeleteDirectory => "failed to delete directory", 77 Self::CantDeleteFile => "failed to delete file", 78 Self::FlushFailure => "failed to flush file", 79 Self::CantOpenVolume => "failed to open volume", 80 Self::Metadata => "failed to read metadata", 81 Self::OpenError => "failed to open file", 82 Self::ReadFailure => "failed to read file", 83 Self::WriteFailure => "failed to write file", 84 Self::NotADirectory => "expected a directory", 85 Self::NotAFile => "expected a file", 86 }; 87 write!(f, "{s}") 88 } 89 } 90 91 impl From<PathError> for Error { from(value: PathError) -> Self92 fn from(value: PathError) -> Self { 93 Self::Path(value) 94 } 95 } 96 97 #[cfg(feature = "unstable")] 98 impl core::error::Error for Error { source(&self) -> Option<&(dyn core::error::Error + 'static)>99 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { 100 match self { 101 Error::Io(err) => Some(err), 102 Error::Path(err) => Some(err), 103 Error::Utf8Encoding(err) => Some(err), 104 } 105 } 106 } 107 108 #[cfg(feature = "unstable")] 109 impl core::error::Error for IoError { source(&self) -> Option<&(dyn core::error::Error + 'static)>110 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { 111 Some(&self.uefi_error) 112 } 113 } 114