use std::{fmt, path::PathBuf};
pub type AppResult<T> = Result<T, AppError>;
#[derive(Debug)]
pub enum AppError {
Backup(BackupError),
Config(ConfigError),
Mail(MailerError),
}
#[derive(Debug)]
pub enum ConfigError {
FileNotFoundError(PathBuf),
DeserializationError(String, toml::de::Error),
ProjectPathNotFoundError,
EnvVarSubstitutionError(String),
}
#[derive(Debug)]
pub enum MailerError {
SendError,
ConfigError(String),
}
#[derive(Debug)]
pub enum BackupError {
DirectoryReadError(PathBuf),
MakeDirectoryError(PathBuf),
MissingTempError(PathBuf),
MissingHomeError(PathBuf),
InvalidHomeError(PathBuf),
CreateArchiveError(CreateArchiveError),
S3CopyError(S3CopyError),
S3InvalidFile(PathBuf),
ZipError(String),
DeleteTempError(PathBuf),
}
#[derive(Debug)]
pub struct CreateArchiveError {
pub path: PathBuf,
pub user: String,
}
#[derive(Debug)]
pub struct S3CopyError {
pub src: String,
pub dest: String,
pub std_err: String,
pub std_out: String,
}
impl fmt::Display for ConfigError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ConfigError::FileNotFoundError(path) => {
write!(f, "Configuration file not found. {path:?}")
}
ConfigError::DeserializationError(_, err) => {
write!(f, "Failed to deserialize the configuration file: {err}")
}
ConfigError::ProjectPathNotFoundError => {
write!(f, "Could not determine project directories.")
}
ConfigError::EnvVarSubstitutionError(var) => {
write!(f, "Could not find environment variable: {var}")
}
}
}
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AppError::Config(ce) => ce.fmt(f),
AppError::Backup(be) => be.fmt(f),
AppError::Mail(me) => me.fmt(f),
}
}
}
impl fmt::Display for MailerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Unable to send email")
}
}
impl fmt::Display for BackupError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BackupError::ZipError(s) => {
write!(f, "Unable to run zip to compress the archive: {s}")
}
BackupError::DirectoryReadError(path) => {
write!(
f,
"Unable to read directory during backup: {}",
path.display()
)
}
BackupError::MakeDirectoryError(path) => {
write!(
f,
"Unable to create directory during backup: {}",
path.display()
)
}
BackupError::MissingHomeError(path) => {
write!(f, "Unable to find home folder: {}", path.display())
}
BackupError::MissingTempError(path) => {
write!(f, "Missing temp directory: {}", path.display())
}
BackupError::DeleteTempError(path) => {
write!(f, "Unable to delete temp file: {}", path.display())
}
BackupError::InvalidHomeError(path) => {
write!(f, "Invalid home directory: {}", path.display())
}
BackupError::CreateArchiveError(create_archive_error) => {
write!(
f,
"Unable to create archive at: {} for user: {}",
create_archive_error.path.display(),
create_archive_error.user
)
}
BackupError::S3InvalidFile(file) => {
write!(f, "Invalid source file: {}", file.display())
}
BackupError::S3CopyError(s3_copy_error) => {
write!(
f,
"Unable to copy from: {} to {}: {}",
s3_copy_error.src, s3_copy_error.dest, s3_copy_error.std_err
)
}
}
}
}
impl std::error::Error for ConfigError {}
impl From<ConfigError> for AppError {
fn from(error: ConfigError) -> Self {
AppError::Config(error)
}
}
impl From<MailerError> for AppError {
fn from(error: MailerError) -> Self {
AppError::Mail(error)
}
}
impl From<BackupError> for AppError {
fn from(error: BackupError) -> Self {
AppError::Backup(error)
}
}