Skip to main content

cubic_chat/
color.rs

1use std::fmt::{Display, Formatter};
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
6#[serde(rename_all = "snake_case")]
7pub enum DefaultColor {
8    Black,
9    DarkBlue,
10    DarkGreen,
11    DarkAqua,
12    DarkRed,
13    DarkPurple,
14    Gold,
15    Gray,
16    DarkGray,
17    Blue,
18    Green,
19    Aqua,
20    Red,
21    LightPurple,
22    Yellow,
23    White,
24}
25
26#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
27#[serde(try_from = "String", into = "String")]
28pub struct HexColor {
29    pub r: u8,
30    pub g: u8,
31    pub b: u8,
32}
33
34#[derive(Debug)]
35pub enum HexColorError {
36    BadHex
37}
38
39#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
40#[serde(untagged)]
41pub enum Color {
42    Default(DefaultColor),
43    Hex(HexColor),
44}
45
46impl Display for HexColorError {
47    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48        match self {
49            HexColorError::BadHex => write!(f, "Bad hex string"),
50        }
51    }
52}
53
54impl TryFrom<String> for HexColor {
55    type Error = HexColorError;
56
57    fn try_from(value: String) -> Result<Self, Self::Error> {
58        match value.len() == 7 {
59            true => {
60                let value_hex_num = i32::from_str_radix(&value[1..], 16)
61                    .map_err(|_| HexColorError::BadHex)?;
62                Ok(HexColor {
63                    r: (value_hex_num >> 16 & 0xff) as u8,
64                    g: (value_hex_num >> 8 & 0xff) as u8,
65                    b: (value_hex_num & 0xff) as u8,
66                })
67            },
68            false => Err(HexColorError::BadHex),
69        }
70    }
71}
72
73impl Display for HexColor {
74    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
75        write!(f, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b)
76    }
77}
78
79impl From<HexColor> for String {
80    fn from(color: HexColor) -> Self {
81        color.to_string()
82    }
83}
84
85impl From<DefaultColor> for Color {
86    fn from(color: DefaultColor) -> Self {
87        Color::Default(color)
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn success_hex_color_test() {
97        let hex_color = HexColor::try_from("#0f0f0f".to_string()).unwrap();
98        assert_eq!(hex_color.r, 15);
99        assert_eq!(hex_color.g, 15);
100        assert_eq!(hex_color.b, 15);
101        assert_eq!(hex_color.to_string(), "#0f0f0f");
102    }
103
104    #[test]
105    fn success_color_test() {
106        let color: Color = serde_json::from_str("\"#0f0f0f\"").unwrap();
107        assert_eq!(color, Color::Hex(HexColor::try_from("#0f0f0f".to_string()).unwrap()))
108    }
109
110}