use std::path::PathBuf;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("Failed to read file '{path}': {source}")]
FileRead {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Failed to write file '{path}': {source}")]
FileWrite {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Failed to create directory '{path}': {source}")]
DirectoryCreate {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Failed to read directory '{path}': {source}")]
DirectoryRead {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Failed to delete file '{path}': {source}")]
FileDelete {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Path not found: {0}")]
PathNotFound(String),
#[error("Failed to serialize data: {0}")]
Serialize(#[from] serde_json::Error),
#[error("Failed to parse settings: {0}")]
Parse(String),
#[error("Setting not found: {0}")]
SettingNotFound(String),
#[error("Invalid setting value for {key}: {reason}")]
InvalidSettingValue { key: String, reason: String },
#[error("Invalid setting metadata for {key}: {reason}")]
InvalidSettingMetadata { key: String, reason: String },
#[error("Settings schema not registered")]
SchemaNotRegistered,
#[error("Type mismatch for {key}: expected {expected}, got {actual}")]
TypeMismatch {
key: String,
expected: String,
actual: String,
},
#[error("Sub-settings type '{0}' not registered")]
SubSettingsNotRegistered(String),
#[error("Sub-settings entry '{0}' not found")]
SubSettingsEntryNotFound(String),
#[error("Backup failed: {0}")]
BackupFailed(String),
#[error("Restore failed: {0}")]
RestoreFailed(String),
#[error("Invalid backup: {0}")]
InvalidBackup(String),
#[error("Backup password required")]
PasswordRequired,
#[error("Invalid backup password")]
InvalidPassword,
#[error("Version mismatch: expected {expected}, found {found}")]
VersionMismatch { expected: String, found: String },
#[cfg(feature = "backup")]
#[error("Archive error: {0}")]
Archive(String),
#[cfg(feature = "backup")]
#[error("Zip error: {0}")]
Zip(#[from] zip::result::ZipError),
#[error("Configuration error: {0}")]
Config(String),
#[error("Manager not initialized")]
NotInitialized,
#[error("Credential error: {0}")]
Credential(String),
#[cfg(feature = "profiles")]
#[error("Profile '{0}' not found")]
ProfileNotFound(String),
#[cfg(feature = "profiles")]
#[error("Profile '{0}' already exists")]
ProfileAlreadyExists(String),
#[cfg(feature = "profiles")]
#[error("Cannot delete active profile '{0}'")]
CannotDeleteActiveProfile(String),
#[cfg(feature = "profiles")]
#[error("Cannot delete the last remaining profile")]
CannotDeleteLastProfile,
#[cfg(feature = "profiles")]
#[error("Invalid profile name: {0}")]
InvalidProfileName(String),
#[cfg(feature = "profiles")]
#[error("Profiles not enabled")]
ProfilesNotEnabled,
#[cfg(feature = "profiles")]
#[error("Profile migration failed: {0}")]
ProfileMigrationFailed(String),
#[error("Invalid cache strategy: {0}")]
InvalidCacheStrategy(String),
#[error(
"Internal lock was poisoned - possible thread panic. The operation may have left data in an inconsistent state."
)]
LockPoisoned,
#[error("Lock error: {0}")]
LockError(String),
}
impl Error {
#[must_use]
pub fn is_not_found(&self) -> bool {
matches!(
self,
Error::PathNotFound(_) | Error::SettingNotFound(_) | Error::SubSettingsEntryNotFound(_)
)
}
#[must_use]
pub fn is_backup_error(&self) -> bool {
matches!(
self,
Error::BackupFailed(_)
| Error::RestoreFailed(_)
| Error::InvalidBackup(_)
| Error::PasswordRequired
| Error::InvalidPassword
| Error::VersionMismatch { .. }
)
}
}
#[cfg(feature = "backup")]
use std::path::Path;
#[cfg(feature = "backup")]
pub fn create_dir(path: &Path) -> Result<()> {
std::fs::create_dir_all(path).map_err(|e| Error::DirectoryCreate {
path: path.to_path_buf(),
source: e,
})
}
#[cfg(feature = "backup")]
pub fn copy_file(src: &Path, dest: &Path) -> Result<u64> {
std::fs::copy(src, dest).map_err(|e| Error::FileRead {
path: src.to_path_buf(),
source: e,
})
}
#[cfg(feature = "backup")]
pub fn write_file(path: &Path, contents: impl AsRef<[u8]>) -> Result<()> {
std::fs::write(path, contents).map_err(|e| Error::FileWrite {
path: path.to_path_buf(),
source: e,
})
}
#[cfg(feature = "backup")]
pub fn read_dir(path: &Path) -> Result<std::fs::ReadDir> {
std::fs::read_dir(path).map_err(|e| Error::DirectoryRead {
path: path.to_path_buf(),
source: e,
})
}
#[cfg(feature = "backup")]
#[inline]
pub fn file_size(path: &Path) -> u64 {
std::fs::metadata(path).map(|m| m.len()).unwrap_or(0)
}