use std::{error::Error, fmt::Display, num::ParseIntError, str::FromStr};
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
#[derive(Debug)]
pub enum ParseColorError {
ParseIntError(ParseIntError),
InvalidLengthError,
}
impl Display for ParseColorError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ParseIntError(e) => write!(f, "error while parsing number: {e}"),
Self::InvalidLengthError => write!(f, "invalid length for color"),
}
}
}
impl Error for ParseColorError {
#[allow(deprecated)]
fn description(&self) -> &str {
match self {
Self::InvalidLengthError => "invalid length for color",
Self::ParseIntError(e) => e.description(),
}
}
}
impl FromStr for Color {
type Err = ParseColorError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let hex = |start: usize| {
u8::from_str_radix(&s[start..=(start + 1)], 16).map_err(ParseColorError::ParseIntError)
};
match s.len() {
6 => Ok(Color {
r: hex(0)?,
g: hex(2)?,
b: hex(4)?,
a: u8::MAX,
}),
8 => Ok(Color {
r: hex(0)?,
g: hex(2)?,
b: hex(4)?,
a: hex(6)?,
}),
_ => Err(ParseColorError::InvalidLengthError),
}
}
}
impl Color {
pub fn rgba(&self) -> [u8; 4] {
[self.r, self.g, self.b, self.a]
}
pub fn argb(&self) -> [u8; 4] {
[self.a, self.r, self.g, self.b]
}
}