1use core::fmt::{self, Display};
4use core::{num::ParseIntError, str};
5
6#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
8pub struct RGB<T = u8> {
9 pub r: T,
11 pub g: T,
13 pub b: T,
15}
16
17impl<T> RGB<T> {
18 pub const fn new(r: T, g: T, b: T) -> Self {
20 Self { r, g, b }
21 }
22}
23
24impl From<(u8, u8, u8)> for RGB {
25 fn from((r, g, b): (u8, u8, u8)) -> Self {
26 Self { r, g, b }
27 }
28}
29
30impl str::FromStr for RGB {
31 type Err = ParseRGBError;
32
33 fn from_str(mut s: &str) -> Result<Self, Self::Err> {
34 if !s.is_ascii() {
35 return Err(ParseRGBError::new(RGBErrorKind::Invalid));
36 }
37
38 if let Some(stripped) = s.strip_prefix('#') {
39 s = stripped;
40 }
41
42 if s.len() != 6 {
43 return Err(ParseRGBError::new(RGBErrorKind::Size));
44 }
45
46 let r = u8::from_str_radix(&s[..2], 16)
47 .map_err(|e| ParseRGBError::new(RGBErrorKind::Format { error: e, pos: 0 }))?;
48
49 let g = u8::from_str_radix(&s[2..4], 16)
50 .map_err(|e| ParseRGBError::new(RGBErrorKind::Format { error: e, pos: 1 }))?;
51
52 let b = u8::from_str_radix(&s[4..6], 16)
53 .map_err(|e| ParseRGBError::new(RGBErrorKind::Format { error: e, pos: 2 }))?;
54
55 Ok(Self { r, g, b })
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct ParseRGBError {
61 kind: RGBErrorKind,
62}
63
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub enum RGBErrorKind {
66 Size,
67 Invalid,
68 Format { pos: usize, error: ParseIntError },
69}
70
71impl ParseRGBError {
72 fn new(kind: RGBErrorKind) -> Self {
73 Self { kind }
74 }
75
76 #[must_use]
78 pub fn kind(&self) -> &RGBErrorKind {
79 &self.kind
80 }
81}
82
83impl Display for ParseRGBError {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 match &self.kind {
86 RGBErrorKind::Size => {
87 "cannot parse rgb from string with size not equal to 6 (or 7 if '#' is used)".fmt(f)
88 }
89 RGBErrorKind::Invalid => "invalid string which contains UTF8 symbols".fmt(f),
90 RGBErrorKind::Format { pos, error } => {
91 error.fmt(f)?;
92 " on position ".fmt(f)?;
93 pos.fmt(f)
94 }
95 }
96 }
97}
98
99