use std::path::PathBuf;
use thiserror::Error;
pub type StorageResult<T> = Result<T, StorageError>;
#[derive(Error, Debug)]
pub enum StorageError {
#[error("Directory creation failed for {path}: {source}")]
DirectoryCreationFailed {
path: PathBuf,
source: std::io::Error,
},
#[error("IO error on {path} ({operation}): {source}")]
IoError {
path: PathBuf,
operation: IoOperation,
source: std::io::Error,
},
#[error("Failed to parse {path} as {format}: {message}")]
ParseError {
path: PathBuf,
format: String,
message: String,
},
#[error("Invalid configuration value for {field}: {message}")]
ValidationError { field: String, message: String },
#[error("Path resolution failed: {message}")]
PathResolutionError { message: String },
#[error("Environment variable error for {var_name}: {message}")]
EnvVarError { var_name: String, message: String },
#[error("Failed to relocate storage from {from} to {to}: {message}")]
RelocationError {
from: PathBuf,
to: PathBuf,
message: String,
},
#[error("Storage unavailable at {path}: {message}")]
StorageUnavailable { path: PathBuf, message: String },
#[error("First-run confirmation required. Suggested path: {suggested_path}")]
FirstRunConfirmationRequired { suggested_path: PathBuf },
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Internal error: {0}")]
Internal(String),
}
#[derive(Debug, Clone, Copy)]
pub enum IoOperation {
Read,
Write,
Delete,
Move,
}
impl std::fmt::Display for IoOperation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IoOperation::Read => write!(f, "read"),
IoOperation::Write => write!(f, "write"),
IoOperation::Delete => write!(f, "delete"),
IoOperation::Move => write!(f, "move"),
}
}
}
impl StorageError {
pub fn directory_creation_failed(path: PathBuf, source: std::io::Error) -> Self {
StorageError::DirectoryCreationFailed { path, source }
}
pub fn io_error(path: PathBuf, operation: IoOperation, source: std::io::Error) -> Self {
StorageError::IoError {
path,
operation,
source,
}
}
pub fn parse_error(
path: PathBuf,
format: impl Into<String>,
message: impl Into<String>,
) -> Self {
StorageError::ParseError {
path,
format: format.into(),
message: message.into(),
}
}
pub fn validation_error(field: impl Into<String>, message: impl Into<String>) -> Self {
StorageError::ValidationError {
field: field.into(),
message: message.into(),
}
}
pub fn path_resolution_error(message: impl Into<String>) -> Self {
StorageError::PathResolutionError {
message: message.into(),
}
}
pub fn env_var_error(var_name: impl Into<String>, message: impl Into<String>) -> Self {
StorageError::EnvVarError {
var_name: var_name.into(),
message: message.into(),
}
}
pub fn relocation_error(from: PathBuf, to: PathBuf, message: impl Into<String>) -> Self {
StorageError::RelocationError {
from,
to,
message: message.into(),
}
}
pub fn storage_unavailable(path: PathBuf, message: impl Into<String>) -> Self {
StorageError::StorageUnavailable {
path,
message: message.into(),
}
}
pub fn first_run_confirmation_required(suggested_path: PathBuf) -> Self {
StorageError::FirstRunConfirmationRequired { suggested_path }
}
pub fn internal(message: impl Into<String>) -> Self {
StorageError::Internal(message.into())
}
}