use std::{io, path::PathBuf};
use thiserror::Error as ThisError;
#[derive(ThisError, Debug, Clone)]
pub enum FileSystemError {
#[error("Path not found: {path}")]
NotFound {
path: PathBuf,
},
#[error("Permission denied for path: {path}")]
PermissionDenied {
path: PathBuf,
},
#[error("I/O error accessing path '{path}': {message}")]
Io {
path: PathBuf,
message: String,
},
#[error("Expected a directory but found a file: {path}")]
NotADirectory {
path: PathBuf,
},
#[error("Expected a file but found a directory: {path}")]
NotAFile {
path: PathBuf,
},
#[error("Failed to decode UTF-8 content in file: {path} - {message}")]
Utf8Decode {
path: PathBuf,
message: String,
},
#[error("Path validation failed for '{path}': {reason}")]
Validation {
path: PathBuf,
reason: String,
},
#[error("Operation failed: {0}")]
Operation(String),
}
impl FileSystemError {
pub fn validation(path: impl Into<PathBuf>, reason: impl Into<String>) -> Self {
Self::Validation { path: path.into(), reason: reason.into() }
}
}
impl FileSystemError {
#[allow(clippy::needless_pass_by_value)]
pub fn from_io(error: io::Error, path: impl Into<PathBuf>) -> Self {
let path_buf = path.into();
match error.kind() {
io::ErrorKind::NotFound => Self::NotFound { path: path_buf },
io::ErrorKind::PermissionDenied => Self::PermissionDenied { path: path_buf },
_ => Self::Io { path: path_buf, message: error.to_string() },
}
}
}
impl From<io::Error> for FileSystemError {
fn from(error: io::Error) -> Self {
let path = PathBuf::from("<unknown>");
match error.kind() {
io::ErrorKind::NotFound => Self::NotFound { path },
io::ErrorKind::PermissionDenied => Self::PermissionDenied { path },
_ => Self::Io { path, message: error.to_string() },
}
}
}
impl AsRef<str> for FileSystemError {
fn as_ref(&self) -> &str {
match self {
FileSystemError::NotFound { .. } => "FileSystemError::NotFound",
FileSystemError::PermissionDenied { .. } => "FileSystemError::PermissionDenied",
FileSystemError::Io { .. } => "FileSystemError::Io",
FileSystemError::NotADirectory { .. } => "FileSystemError::NotADirectory",
FileSystemError::NotAFile { .. } => "FileSystemError::NotAFile",
FileSystemError::Utf8Decode { .. } => "FileSystemError::Utf8Decode",
FileSystemError::Validation { .. } => "FileSystemError::Validation",
FileSystemError::Operation(_) => "FileSystemError::Operation",
}
}
}