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}