1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
use std::{error::Error, fmt, num::TryFromIntError, path::PathBuf, sync::LazyLock};
// https://gist.github.com/abritinthebay/d80eb99b2726c83feb0d97eab95206c4
// https://talyian.github.io/ansicolors/
// ANSI Color Codes:
pub const RED: &str = "\x1b[31m";
pub const GREEN: &str = "\x1b[32m";
pub const YELLOW: &str = "\x1b[33m";
pub const BLUE: &str = "\x1b[34m";
pub const RESET: &str = "\x1b[0m";
/// A value which is initialized on the first access
pub static ERROR: LazyLock<String> = LazyLock::new(|| format!("{RED}Error{RESET}"));
pub static HELP: LazyLock<String> =
LazyLock::new(|| format!("For more information, try '{GREEN}--help{RESET}'."));
#[derive(Debug)]
/// The `WSError` enum defines the error values
///
/// <https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/define_error_type.html>
pub enum WSError<'a> {
/// Directory path must exist
Parent(PathBuf),
/// Unable to obtain minimum value
MinValue,
/// Missing value
MissingValue(&'a str),
/// Invalid value
InvalidValue(&'a str),
/// At least value
AtLeastValue(&'a str, u32),
/// Unexpected argument
UnexpectedArg(String),
/// Try to performs the conversion
TryInto(String),
}
impl fmt::Display for WSError<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Closure with Parameter
let green = |num: &u32| format!("{GREEN}{num}{RESET}");
let yellow = |s: &str| format!("{YELLOW}{s}{RESET}");
match self {
WSError::Parent(path) => write!(f, "Wallpaper dir {path:?} does not exist."),
WSError::MinValue => write!(f, "Unable to obtain minimum value!"),
WSError::MissingValue(arg) => write!(
f,
"{e}: missing value for '{a}'\n\n{h}",
e = *ERROR,
a = yellow(arg),
h = *HELP
),
WSError::InvalidValue(arg) => write!(
f,
"{e}: invalid value for '{a}'\n\n{h}",
e = *ERROR,
a = yellow(arg),
h = *HELP
),
WSError::AtLeastValue(arg, num) => {
write!(
f,
"{e}: '{a}' must be at least {n}\n\n{h}",
e = *ERROR,
a = yellow(arg),
n = green(num),
h = *HELP
)
}
WSError::UnexpectedArg(arg) => {
write!(
f,
"{e}: unexpected argument '{a}' found\n\n{h}",
e = *ERROR,
a = yellow(arg),
h = *HELP
)
}
WSError::TryInto(err) => write!(f, "{err}"),
}
}
}
impl Error for WSError<'_> {}
// Implementing the From trait for multiple types that you want to map into WSError.
// https://stackoverflow.com/questions/62238827/less-verbose-type-for-map-err-closure-argument
// let monitor: u8 = value.try_into().map_err(WSError::from)?;
impl From<TryFromIntError> for WSError<'_> {
fn from(err: TryFromIntError) -> Self {
Self::TryInto(err.to_string())
}
}