| use std::error::Error as StdError; | |
| use std::fmt; | |
| use std::io; | |
| use std::path::PathBuf; | |
| #[derive(Debug, Clone, Copy)] | |
| pub(crate) enum ErrorKind { | |
| OpenFile, | |
| CreateFile, | |
| CreateDir, | |
| SyncFile, | |
| SetLen, | |
| Metadata, | |
| Clone, | |
| SetPermissions, | |
| Read, | |
| Seek, | |
| Write, | |
| Flush, | |
| ReadDir, | |
| RemoveFile, | |
| RemoveDir, | |
| Canonicalize, | |
| ReadLink, | |
| SymlinkMetadata, | |
| #[allow(dead_code)] | |
| FileExists, | |
| #[cfg(windows)] | |
| SeekRead, | |
| #[cfg(windows)] | |
| SeekWrite, | |
| #[cfg(unix)] | |
| ReadAt, | |
| #[cfg(unix)] | |
| WriteAt, | |
| } | |
| /// Contains an IO error that has a file path attached. | |
| /// | |
| /// This type is never returned directly, but is instead wrapped inside yet | |
| /// another IO error. | |
| #[derive(Debug)] | |
| pub(crate) struct Error { | |
| kind: ErrorKind, | |
| source: io::Error, | |
| path: PathBuf, | |
| } | |
| impl Error { | |
| pub fn build(source: io::Error, kind: ErrorKind, path: impl Into<PathBuf>) -> io::Error { | |
| io::Error::new( | |
| source.kind(), | |
| Self { | |
| kind, | |
| source, | |
| path: path.into(), | |
| }, | |
| ) | |
| } | |
| } | |
| impl fmt::Display for Error { | |
| fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| use ErrorKind::*; | |
| let path = self.path.display(); | |
| match self.kind { | |
| OpenFile => write!(formatter, "failed to open file `{}`", path), | |
| CreateFile => write!(formatter, "failed to create file `{}`", path), | |
| CreateDir => write!(formatter, "failed to create directory `{}`", path), | |
| SyncFile => write!(formatter, "failed to sync file `{}`", path), | |
| SetLen => write!(formatter, "failed to set length of file `{}`", path), | |
| Metadata => write!(formatter, "failed to query metadata of file `{}`", path), | |
| Clone => write!(formatter, "failed to clone handle for file `{}`", path), | |
| SetPermissions => write!(formatter, "failed to set permissions for file `{}`", path), | |
| Read => write!(formatter, "failed to read from file `{}`", path), | |
| Seek => write!(formatter, "failed to seek in file `{}`", path), | |
| Write => write!(formatter, "failed to write to file `{}`", path), | |
| Flush => write!(formatter, "failed to flush file `{}`", path), | |
| ReadDir => write!(formatter, "failed to read directory `{}`", path), | |
| RemoveFile => write!(formatter, "failed to remove file `{}`", path), | |
| RemoveDir => write!(formatter, "failed to remove directory `{}`", path), | |
| Canonicalize => write!(formatter, "failed to canonicalize path `{}`", path), | |
| ReadLink => write!(formatter, "failed to read symbolic link `{}`", path), | |
| SymlinkMetadata => write!(formatter, "failed to query metadata of symlink `{}`", path), | |
| FileExists => write!(formatter, "failed to check file existance `{}`", path), | |
| #[cfg(windows)] | |
| SeekRead => write!(formatter, "failed to seek and read from `{}`", path), | |
| #[cfg(windows)] | |
| SeekWrite => write!(formatter, "failed to seek and write to `{}`", path), | |
| #[cfg(unix)] | |
| ReadAt => write!(formatter, "failed to read with offset from `{}`", path), | |
| #[cfg(unix)] | |
| WriteAt => write!(formatter, "failed to write with offset to `{}`", path), | |
| } | |
| } | |
| } | |
| impl StdError for Error { | |
| fn cause(&self) -> Option<&dyn StdError> { | |
| self.source() | |
| } | |
| fn source(&self) -> Option<&(dyn StdError + 'static)> { | |
| Some(&self.source) | |
| } | |
| } | |
| #[derive(Debug, Clone, Copy)] | |
| pub(crate) enum SourceDestErrorKind { | |
| Copy, | |
| HardLink, | |
| Rename, | |
| SoftLink, | |
| #[cfg(unix)] | |
| Symlink, | |
| #[cfg(windows)] | |
| SymlinkDir, | |
| #[cfg(windows)] | |
| SymlinkFile, | |
| } | |
| /// Error type used by functions like `fs::copy` that holds two paths. | |
| #[derive(Debug)] | |
| pub(crate) struct SourceDestError { | |
| kind: SourceDestErrorKind, | |
| source: io::Error, | |
| from_path: PathBuf, | |
| to_path: PathBuf, | |
| } | |
| impl SourceDestError { | |
| pub fn build( | |
| source: io::Error, | |
| kind: SourceDestErrorKind, | |
| from_path: impl Into<PathBuf>, | |
| to_path: impl Into<PathBuf>, | |
| ) -> io::Error { | |
| io::Error::new( | |
| source.kind(), | |
| Self { | |
| kind, | |
| source, | |
| from_path: from_path.into(), | |
| to_path: to_path.into(), | |
| }, | |
| ) | |
| } | |
| } | |
| impl fmt::Display for SourceDestError { | |
| fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| let from = self.from_path.display(); | |
| let to = self.to_path.display(); | |
| match self.kind { | |
| SourceDestErrorKind::Copy => { | |
| write!(formatter, "failed to copy file from {} to {}", from, to) | |
| } | |
| SourceDestErrorKind::HardLink => { | |
| write!(formatter, "failed to hardlink file from {} to {}", from, to) | |
| } | |
| SourceDestErrorKind::Rename => { | |
| write!(formatter, "failed to rename file from {} to {}", from, to) | |
| } | |
| SourceDestErrorKind::SoftLink => { | |
| write!(formatter, "failed to softlink file from {} to {}", from, to) | |
| } | |
| #[cfg(unix)] | |
| SourceDestErrorKind::Symlink => { | |
| write!(formatter, "failed to symlink file from {} to {}", from, to) | |
| } | |
| #[cfg(windows)] | |
| SourceDestErrorKind::SymlinkFile => { | |
| write!(formatter, "failed to symlink file from {} to {}", from, to) | |
| } | |
| #[cfg(windows)] | |
| SourceDestErrorKind::SymlinkDir => { | |
| write!(formatter, "failed to symlink dir from {} to {}", from, to) | |
| } | |
| } | |
| } | |
| } | |
| impl StdError for SourceDestError { | |
| fn cause(&self) -> Option<&dyn StdError> { | |
| self.source() | |
| } | |
| fn source(&self) -> Option<&(dyn StdError + 'static)> { | |
| Some(&self.source) | |
| } | |
| } |