1mod constants;
2
3use crate::utils::euclidean_distance;
4pub use constants::{color, colors, Colors, COLORS_DATA};
5
6pub struct Color;
7
8impl Color {
9 pub fn by_enum(&self, color: color) -> [u8; 3] {
22 let _clr = color as usize;
23 (COLORS_DATA)[_clr].1
24 }
25
26 pub fn by_string(&self, color: String) -> Result<[u8; 3], u16> {
43 if color.len() == 0 {
45 Err(404)
46 } else {
47 let mut got = false;
48 let mut col = [0, 0, 0];
49 for c in COLORS_DATA.iter() {
50 if String::from(c.0)
51 == format!(
52 "{}{}",
53 &color.trim().to_uppercase()[0..1],
54 &color.trim().to_lowercase()[1..]
55 )
56 {
57 col = (c.1).to_owned();
58 got = true;
59 break;
60 }
61 }
62 if got {
63 Ok(col)
64 } else {
65 Err(404)
66 }
67 }
68 }
69
70 pub fn val() -> Color {
72 Color
73 }
74
75 pub fn name(rgb: [u8; 3]) -> String {
77 for (name, value) in COLORS_DATA.iter() {
78 if value == &rgb {
79 return format!("{}", name);
80 }
81 }
82
83 format!("404")
84 }
85
86 pub fn similar(rgb: [u8; 3]) -> String {
88 let c = Self::name(rgb);
89 if c == "404" {
90 let mut current_closest_distance = u128::MAX;
91 let mut current_closest_keyword = "";
92
93 for (name, value) in COLORS_DATA.iter() {
94 let distance = euclidean_distance(rgb, *value);
96
97 if value == &rgb {
98 return format!("{}", name);
99 }
100 #[allow(unused_parens)]
102 if (distance < current_closest_distance) {
103 current_closest_distance = distance;
104 current_closest_keyword = name;
105 }
106 }
107 format!("{}", current_closest_keyword)
108 } else {
109 c
110 }
111 }
112
113 pub fn close_to(rgb: [u8; 3]) -> String {
115 Self::similar(rgb)
116 }
117}
118
119#[cfg(test)]
120mod test {
121 use super::*;
122
123 #[test]
124 fn test_lower_const_colors() {
125 assert_eq!(colors::yellow, [255, 255, 0]);
126 assert_eq!(colors::aqua, [0, 255, 255]);
127 }
128
129 #[test]
130 fn test_upper_const_colors() {
131 assert_eq!(Colors::Yellow, [255, 255, 0]);
132 assert_eq!(Colors::Aqua, [0, 255, 255]);
133 }
134
135 #[test]
136 fn test_color_by_enum_fn() {
137 assert_eq!(Color::val().by_enum(color::yellow), [255, 255, 0]);
138 assert_eq!(Color::val().by_enum(color::aqua), [0, 255, 255]);
139 assert_eq!(Color::val().by_enum(color::red), [255, 0, 0]);
140 assert_eq!(Color::val().by_enum(color::black), [0, 0, 0]);
141 }
142
143 #[test]
144 fn test_color_by_string_fn() {
145 assert_eq!(Color::val().by_string(String::from("")), Err(404));
146 assert_eq!(Color::val().by_string(String::from("A")), Err(404));
147 assert_eq!(
148 Color::val().by_string(String::from("Azure")).unwrap(),
149 [240, 255, 255]
150 );
151 assert_eq!(
152 Color::val().by_string(String::from("Chocolate")).unwrap(),
153 [210, 105, 30]
154 );
155 assert_eq!(
156 Color::val().by_string(String::from("Red")).unwrap(),
157 [255, 0, 0]
158 );
159 assert_eq!(
160 Color::val().by_string(String::from("Black")).unwrap(),
161 [0, 0, 0]
162 );
163 assert_eq!(Color::val().by_string(String::from("annymosse")), Err(404));
164 }
165
166 #[test]
167 fn test_color_name_fn() {
168 assert_eq!(Color::name([0, 0, 0]), "Black");
169 assert_eq!(Color::name([0, 1, 1]), "404");
170 assert_eq!(Color::name([0, 195, 0]), "404");
171 }
172
173 #[test]
174 fn test_color_similar_fn() {
175 assert_eq!(Color::similar([195, 40, 10]), "Firebrick");
176 assert_eq!(Color::similar([123, 45, 67]), "Brown");
177 assert_eq!(Color::similar([213, 69, 87]), "Indianred");
178 assert_eq!(Color::similar([87, 33, 26]), "Maroon");
179 assert_eq!(Color::similar([0, 195, 0]), "Lime");
180 }
181
182 #[test]
183 fn test_color_close_to() {
184 assert_eq!(Color::close_to([195, 40, 10]), "Firebrick");
185 assert_eq!(Color::close_to([123, 45, 67]), "Brown");
186 assert_eq!(Color::close_to([213, 69, 87]), "Indianred");
187 assert_eq!(Color::close_to([87, 33, 26]), "Maroon");
188 assert_eq!(Color::close_to([0, 195, 0]), "Lime");
189 }
190
191 #[test]
192 fn test_enum_colors() {
193 assert_eq!(Color::val().by_enum(color::yellow), [255, 255, 0]);
194 assert_eq!(Color::val().by_enum(color::aqua), [0, 255, 255]);
195 assert_eq!(Color::val().by_enum(color::red), [255, 0, 0]);
196 assert_eq!(Color::val().by_enum(color::black), [0, 0, 0]);
197 }
198
199 #[test]
200 fn test_not_found_cases() {
201 assert_eq!(Color::name([0, 195, 0]), "404");
203
204 assert_eq!(
206 Color::val().by_string(String::from("MayMoonsley")),
207 Err(404)
208 );
209 }
210}