use thiserror::Error;
#[derive(Error, Debug, Clone)]
pub enum NeofetchError {
#[error("Failed to read file '{path}': {message}")]
FileRead { path: String, message: String },
#[error("Failed to write file '{path}': {message}")]
FileWrite { path: String, message: String },
#[error("Failed to parse {field}: {reason}")]
ParseError { field: String, reason: String },
#[error("Failed to execute command '{command}': {message}")]
CommandExecution { command: String, message: String },
#[error("Command '{command}' failed with exit code {code}")]
CommandFailed { command: String, code: i32 },
#[cfg(windows)]
#[error("WMI query failed: {0}")]
WmiError(String),
#[error("System call failed: {0}")]
SystemCall(String),
#[error("Feature not available on this platform")]
UnsupportedPlatform,
#[error("Data not available: {0}")]
DataUnavailable(String),
#[error("Invalid UTF-8 data: {0}")]
Utf8Error(String),
#[error("Task join error: {0}")]
JoinError(String),
#[error("I/O error: {0}")]
Io(String),
#[error("Failed to parse integer: {0}")]
ParseInt(String),
#[error("Failed to parse float: {0}")]
ParseFloat(String),
}
impl From<std::io::Error> for NeofetchError {
fn from(err: std::io::Error) -> Self {
NeofetchError::Io(err.to_string())
}
}
impl From<std::string::FromUtf8Error> for NeofetchError {
fn from(err: std::string::FromUtf8Error) -> Self {
NeofetchError::Utf8Error(err.to_string())
}
}
impl From<tokio::task::JoinError> for NeofetchError {
fn from(err: tokio::task::JoinError) -> Self {
NeofetchError::JoinError(err.to_string())
}
}
impl From<std::num::ParseIntError> for NeofetchError {
fn from(err: std::num::ParseIntError) -> Self {
NeofetchError::ParseInt(err.to_string())
}
}
impl From<std::num::ParseFloatError> for NeofetchError {
fn from(err: std::num::ParseFloatError) -> Self {
NeofetchError::ParseFloat(err.to_string())
}
}
pub type Result<T> = std::result::Result<T, NeofetchError>;
impl NeofetchError {
pub fn file_read(path: impl Into<String>, source: std::io::Error) -> Self {
Self::FileRead {
path: path.into(),
message: source.to_string(),
}
}
pub fn file_write(path: impl Into<String>, source: std::io::Error) -> Self {
Self::FileWrite {
path: path.into(),
message: source.to_string(),
}
}
pub fn parse_error(field: impl Into<String>, reason: impl Into<String>) -> Self {
Self::ParseError {
field: field.into(),
reason: reason.into(),
}
}
pub fn command_execution(command: impl Into<String>, source: std::io::Error) -> Self {
Self::CommandExecution {
command: command.into(),
message: source.to_string(),
}
}
pub fn command_failed(command: impl Into<String>, code: i32) -> Self {
Self::CommandFailed {
command: command.into(),
code,
}
}
pub fn data_unavailable(message: impl Into<String>) -> Self {
Self::DataUnavailable(message.into())
}
pub fn system_call(message: impl Into<String>) -> Self {
Self::SystemCall(message.into())
}
#[cfg(windows)]
pub fn wmi_error(message: impl Into<String>) -> Self {
Self::WmiError(message.into())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = NeofetchError::parse_error("cpu_speed", "invalid number");
assert_eq!(err.to_string(), "Failed to parse cpu_speed: invalid number");
}
#[test]
fn test_data_unavailable() {
let err = NeofetchError::data_unavailable("GPU information");
assert_eq!(err.to_string(), "Data not available: GPU information");
}
}