use std::io;
use std::path::PathBuf;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("Configuration error: {0}")]
Config(#[from] ConfigError),
#[error("File error: {0}")]
File(#[from] FileError),
#[error("Database error: {0}")]
Database(#[from] DatabaseError),
#[error("Parse error: {0}")]
Parse(#[from] ParseError),
#[error("SQL log parser error: {0}")]
Parser(#[from] ParserError),
#[error("Export error: {0}")]
Export(#[from] ExportError),
#[error("IO error: {0}")]
Io(#[from] io::Error),
}
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("Configuration file not found: {0}")]
NotFound(PathBuf),
#[error("Failed to parse configuration file {path}: {reason}")]
ParseFailed { path: PathBuf, reason: String },
#[error("Invalid log level '{level}', valid values: {}", valid_levels.join(", "))]
InvalidLogLevel {
level: String,
valid_levels: Vec<String>,
},
#[error("Invalid configuration value {field} = '{value}': {reason}")]
InvalidValue {
field: String,
value: String,
reason: String,
},
#[error("At least one exporter must be configured (database/csv)")]
NoExporters,
}
#[derive(Debug, Error)]
pub enum FileError {
#[error("File already exists: {path} (set overwrite=true to replace)")]
AlreadyExists { path: PathBuf },
#[error("Failed to write file {path}: {reason}")]
WriteFailed { path: PathBuf, reason: String },
#[error("Failed to create directory {path}: {reason}")]
CreateDirectoryFailed { path: PathBuf, reason: String },
}
#[derive(Debug, Error)]
pub enum DatabaseError {}
#[derive(Debug, Error)]
pub enum ParseError {}
#[derive(Debug, Error)]
pub enum ParserError {
#[error("Path not found: {path}")]
PathNotFound { path: PathBuf },
#[error("Invalid path {path}: {reason}")]
InvalidPath { path: PathBuf, reason: String },
#[error("Failed to read directory {path}: {reason}")]
ReadDirFailed { path: PathBuf, reason: String },
}
#[derive(Debug, Error)]
#[allow(clippy::enum_variant_names)]
pub enum ExportError {
#[error("CSV export failed {path}: {reason}")]
CsvExportFailed { path: PathBuf, reason: String },
#[error("Failed to create output file {path}: {reason}")]
FileCreateFailed { path: PathBuf, reason: String },
#[error("Failed to write file {path}: {reason}")]
FileWriteFailed { path: PathBuf, reason: String },
#[cfg(any(feature = "sqlite", feature = "duckdb", feature = "postgres"))]
#[error("Database error: {reason}")]
DatabaseError { reason: String },
#[cfg(feature = "dm")]
#[error("IO error {path}: {reason}")]
IoError { path: PathBuf, reason: String },
#[cfg(feature = "dm")]
#[error("External tool '{tool}' failed: {reason}")]
ExternalToolError { tool: String, reason: String },
}
pub type Result<T> = std::result::Result<T, Error>;
#[macro_export]
macro_rules! config_error {
($variant:ident { $($field:ident: $value:expr),+ $(,)? }) => {
$crate::error::Error::Config($crate::error::ConfigError::$variant {
$($field: $value),+
})
};
}
#[macro_export]
macro_rules! file_error {
($variant:ident { $($field:ident: $value:expr),+ $(,)? }) => {
$crate::error::Error::File($crate::error::FileError::$variant {
$($field: $value),+
})
};
}
#[macro_export]
macro_rules! database_error {
($variant:ident { $($field:ident: $value:expr),+ $(,)? }) => {
$crate::error::Error::Database($crate::error::DatabaseError::$variant {
$($field: $value),+
})
};
}
#[macro_export]
macro_rules! parse_error {
($variant:ident { $($field:ident: $value:expr),+ $(,)? }) => {
$crate::error::Error::Parse($crate::error::ParseError::$variant {
$($field: $value),+
})
};
}
#[macro_export]
macro_rules! export_error {
($variant:ident { $($field:ident: $value:expr),+ $(,)? }) => {
$crate::error::Error::Export($crate::error::ExportError::$variant {
$($field: $value),+
})
};
}