use thiserror::Error as ThisError;
#[cfg(feature = "colored")]
use colored::Colorize;
const RATE_LIMIT: &str = "we might be getting rate-limited here";
const CONFIG_PATHS: &str = "config file locations:
./nvrs.toml
$XDG_CONFIG_HOME/nvrs/nvrs.toml
$HOME/.config/nvrs.toml";
const NOT_EMPTY: &str = "make sure the file is not empty";
const EXAMPLE_CONFIG_TABLE: &str = "example:
[__config__]
oldver = \"oldver.json\"
newver = \"newver.json\"";
#[derive(Debug, ThisError)]
pub enum Error {
#[error("request error: {0}")]
RequestError(#[from] reqwest::Error),
#[error("io error: {0}")]
IOError(#[from] std::io::Error),
#[error("json parsing error: {0}")]
JSONError(#[from] serde_json::Error),
#[error("toml parsing error: {0}")]
TOMLError(#[from] toml::de::Error),
#[error("toml parsing error: {0}")]
TOMLErrorSer(#[from] toml::ser::Error),
#[error("env error: {0}")]
EnvError(#[from] std::env::VarError),
#[error("{0}: request status != OK\n{1}")]
RequestNotOK(String, String),
#[error("{0}: request returned 430\n{RATE_LIMIT}")]
RequestForbidden(String),
#[error("{0}: version not found")]
NoVersion(String),
#[error("specified config file not found")]
NoConfigSpecified,
#[error("no config found\n{CONFIG_PATHS}\n{NOT_EMPTY}")]
NoConfig,
#[error("__config__ not specified\n{EXAMPLE_CONFIG_TABLE}")]
NoConfigTable,
#[error("specified keyfile not found\n{NOT_EMPTY}")]
NoKeyfile,
#[error("oldver & newver not specified\n{EXAMPLE_CONFIG_TABLE}")]
NoXVer,
#[error("unsupported verfile version\nplease update your verfiles")]
VerfileVer,
#[error("{0}: package not in newver")]
PkgNotInNewver(String),
#[error("{0}: package not in config")]
PkgNotInConfig(String),
#[error("source {0} not found")]
SourceNotFound(String),
#[error("shell command failed: {0}")]
ShellCommandFailed(String),
}
impl Error {
#[cfg(feature = "colored")]
pub fn pretty(&self) {
let mut lines: Vec<String> = self
.to_string()
.lines()
.map(|line| line.to_string())
.collect();
let first = lines.remove(0);
let first_split = first.split_once(':').unwrap_or(("", &first));
if first_split.0.is_empty() {
println!("{} {}", "!".red().bold().on_black(), first_split.1.red());
} else {
println!(
"{} {}:{}",
"!".red().bold().on_black(),
first_split.0,
first_split.1.red()
);
}
for line in lines {
println!("{} {}", "!".red().on_black(), line)
}
}
}
pub type Result<T> = std::result::Result<T, Error>;
#[test]
fn test_error() {
let message = "nvrs died. now why could that be...?";
let error = Error::from(std::io::Error::other(message));
assert_eq!(
format!("\"io error: {message}\""),
format!("{:?}", error.to_string())
)
}