1use std::fmt;
5
6use rgb::Rgb;
7use strum::EnumCount;
8use tinyrand::{RandRange, StdRand};
9
10use super::ExtendedColour;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumCount)]
14#[allow(missing_docs)]
15pub enum Blue {
16 PowderBlue,
17 CadetBlue,
18 SteelBlue,
19 CornflowerBlue,
20 DeepSkyBlue,
21 DodgerBlue,
22 LightBlue,
23 SkyBlue,
24 LightSkyBlue,
25 MidnightBlue,
26 Navy,
27 DarkBlue,
28 MediumBlue,
29 Blue,
30 RoyalBlue,
31 Azure,
32 LightSteelBlue,
33}
34
35impl fmt::Display for Blue {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 Self::PowderBlue => write!(f, "#B0E0E6"),
39 Self::CadetBlue => write!(f, "#5F9EA0"),
40 Self::SteelBlue => write!(f, "#4682B4"),
41 Self::CornflowerBlue => write!(f, "#6495ED"),
42 Self::DeepSkyBlue => write!(f, "#00BFFF"),
43 Self::DodgerBlue => write!(f, "#1E90FF"),
44 Self::LightBlue => write!(f, "#ADD8E6"),
45 Self::SkyBlue => write!(f, "#87CEEB"),
46 Self::LightSkyBlue => write!(f, "#87CEFA"),
47 Self::LightSteelBlue => write!(f, "#B0C4DE"),
48 Self::MidnightBlue => write!(f, "#191970"),
49 Self::Navy => write!(f, "#000080"),
50 Self::DarkBlue => write!(f, "#00008B"),
51 Self::MediumBlue => write!(f, "#0000CD"),
52 Self::Blue => write!(f, "#0000FF"),
53 Self::RoyalBlue => write!(f, "#4169E1"),
54 Self::Azure => write!(f, "#F0FFFF"),
55 }
56 }
57}
58
59impl_colour_methods!(Blue);
60
61impl Blue {
62 pub fn parse(name: &str) -> Option<Self> {
75 match name.to_lowercase().as_str() {
76 "#b0e0e6" | "b0e0e6" | "powderblue" => Some(Self::PowderBlue),
77 "#5f9ea0" | "5f9ea0" | "cadetblue" => Some(Self::CadetBlue),
78 "#4682b4" | "4682b4" | "steelblue" => Some(Self::SteelBlue),
79 "#6495ed" | "6495ed" | "cornflowerblue" => Some(Self::CornflowerBlue),
80 "#00bfff" | "00bfff" | "deepskyblue" => Some(Self::DeepSkyBlue),
81 "#1e90ff" | "1e90ff" | "dodgerblue" => Some(Self::DodgerBlue),
82 "#add8e6" | "add8e6" | "lightblue" => Some(Self::LightBlue),
83 "#87ceeb" | "87ceeb" | "skyblue" => Some(Self::SkyBlue),
84 "#b0c4de" | "b0c4de" | "lightsteelblue" => Some(Self::LightSteelBlue),
85 "#87cefa" | "87cefa" | "lightskyblue" => Some(Self::LightSkyBlue),
86 "#191970" | "191970" | "midnightblue" => Some(Self::MidnightBlue),
87 "#000080" | "000080" | "navy" => Some(Self::Navy),
88 "#00008b" | "00008b" | "darkblue" => Some(Self::DarkBlue),
89 "#0000cd" | "0000cd" | "mediumblue" => Some(Self::MediumBlue),
90 "#0000ff" | "0000ff" | "blue" => Some(Self::Blue),
91 "#4169e1" | "4169e1" | "royalblue" => Some(Self::RoyalBlue),
92 "#f0ffff" | "f0ffff" | "azure" => Some(Self::Azure),
93 _ => None,
94 }
95 }
96
97 pub fn random() -> Self {
109 let mut rand = StdRand::default();
110
111 match rand.next_range(0..Self::COUNT) {
112 0 => Self::PowderBlue,
113 1 => Self::CadetBlue,
114 2 => Self::SteelBlue,
115 3 => Self::CornflowerBlue,
116 4 => Self::DeepSkyBlue,
117 5 => Self::DodgerBlue,
118 6 => Self::LightBlue,
119 7 => Self::SkyBlue,
120 8 => Self::LightSkyBlue,
121 9 => Self::LightSteelBlue,
122 10 => Self::MidnightBlue,
123 11 => Self::Navy,
124 12 => Self::DarkBlue,
125 13 => Self::MediumBlue,
126 14 => Self::Blue,
127 15 => Self::RoyalBlue,
128 16 => Self::Azure,
129 _ => Self::Blue,
130 }
131 }
132}
133
134impl ExtendedColour for Blue {}
135
136#[cfg(test)]
137mod tests {
138 use std::str::FromStr;
139
140 use crate::Prefix;
141
142 use super::*;
143 use rstest::rstest;
144
145 #[rstest]
146 #[case(Blue::PowderBlue, "rgb(176,224,230)")]
147 #[case(Blue::CadetBlue, "rgb(95,158,160)")]
148 #[case(Blue::SteelBlue, "rgb(70,130,180)")]
149 #[case(Blue::CornflowerBlue, "rgb(100,149,237)")]
150 #[case(Blue::DeepSkyBlue, "rgb(0,191,255)")]
151 #[case(Blue::DodgerBlue, "rgb(30,144,255)")]
152 #[case(Blue::LightBlue, "rgb(173,216,230)")]
153 #[case(Blue::SkyBlue, "rgb(135,206,235)")]
154 #[case(Blue::LightSteelBlue, "rgb(176,196,222)")]
155 #[case(Blue::LightSkyBlue, "rgb(135,206,250)")]
156 #[case(Blue::MidnightBlue, "rgb(25,25,112)")]
157 #[case(Blue::Navy, "rgb(0,0,128)")]
158 #[case(Blue::DarkBlue, "rgb(0,0,139)")]
159 #[case(Blue::MediumBlue, "rgb(0,0,205)")]
160 #[case(Blue::Blue, "rgb(0,0,255)")]
161 #[case(Blue::RoyalBlue, "rgb(65,105,225)")]
162 #[case(Blue::Azure, "rgb(240,255,255)")]
163
164 fn test_rgb_string(#[case] colour: Blue, #[case] expected: String) {
165 let rgb_colour = colour.to_rgb();
166 let string = rgb_colour.to_string();
167
168 assert_eq!(expected, string);
169 }
170
171 #[rstest]
172 #[case(Blue::PowderBlue, "B0E0E6")]
173 #[case(Blue::CadetBlue, "5F9EA0")]
174 #[case(Blue::SteelBlue, "4682B4")]
175 #[case(Blue::CornflowerBlue, "6495ED")]
176 #[case(Blue::DeepSkyBlue, "00BFFF")]
177 #[case(Blue::DodgerBlue, "1E90FF")]
178 #[case(Blue::LightBlue, "ADD8E6")]
179 #[case(Blue::SkyBlue, "87CEEB")]
180 #[case(Blue::LightSteelBlue, "B0C4DE")]
181 #[case(Blue::LightSkyBlue, "87CEFA")]
182 #[case(Blue::MidnightBlue, "191970")]
183 #[case(Blue::Navy, "000080")]
184 #[case(Blue::DarkBlue, "00008B")]
185 #[case(Blue::MediumBlue, "0000CD")]
186 #[case(Blue::Blue, "0000FF")]
187 #[case(Blue::RoyalBlue, "4169E1")]
188 #[case(Blue::Azure, "F0FFFF")]
189
190 fn test_hex_triplet_string(
191 #[case] colour: Blue,
192 #[values(Prefix::None, Prefix::Hash)] prefix: Prefix,
193 #[case] expected: String,
194 ) {
195 let prefix_string = match prefix {
196 Prefix::None => "".to_string(),
197 Prefix::Hash => "#".to_string(),
198 };
199
200 let expected = format!("{prefix_string}{expected}");
201
202 let hex_colour = colour.to_hex_triplet(prefix);
203
204 assert_eq!(expected, hex_colour);
205 }
206
207 #[rstest]
208 #[case("#b0e0e6", Blue::PowderBlue)]
209 #[case("b0e0e6", Blue::PowderBlue)]
210 #[case("powderblue", Blue::PowderBlue)]
211 #[case("#5f9ea0", Blue::CadetBlue)]
212 #[case("5f9ea0", Blue::CadetBlue)]
213 #[case("cadetblue", Blue::CadetBlue)]
214 #[case("#4682b4", Blue::SteelBlue)]
215 #[case("4682b4", Blue::SteelBlue)]
216 #[case("steelblue", Blue::SteelBlue)]
217 #[case("#6495ed", Blue::CornflowerBlue)]
218 #[case("6495ed", Blue::CornflowerBlue)]
219 #[case("cornflowerblue", Blue::CornflowerBlue)]
220 #[case("#00bfff", Blue::DeepSkyBlue)]
221 #[case("00bfff", Blue::DeepSkyBlue)]
222 #[case("deepskyblue", Blue::DeepSkyBlue)]
223 #[case("#1e90ff", Blue::DodgerBlue)]
224 #[case("1e90ff", Blue::DodgerBlue)]
225 #[case("dodgerblue", Blue::DodgerBlue)]
226 #[case("#add8e6", Blue::LightBlue)]
227 #[case("add8e6", Blue::LightBlue)]
228 #[case("lightblue", Blue::LightBlue)]
229 #[case("#87ceeb", Blue::SkyBlue)]
230 #[case("87ceeb", Blue::SkyBlue)]
231 #[case("skyblue", Blue::SkyBlue)]
232 #[case("#b0c4de", Blue::LightSteelBlue)]
233 #[case("b0c4de", Blue::LightSteelBlue)]
234 #[case("lightsteelblue", Blue::LightSteelBlue)]
235 #[case("#87cefa", Blue::LightSkyBlue)]
236 #[case("87cefa", Blue::LightSkyBlue)]
237 #[case("lightskyblue", Blue::LightSkyBlue)]
238 #[case("#191970", Blue::MidnightBlue)]
239 #[case("191970", Blue::MidnightBlue)]
240 #[case("midnightblue", Blue::MidnightBlue)]
241 #[case("#000080", Blue::Navy)]
242 #[case("000080", Blue::Navy)]
243 #[case("navy", Blue::Navy)]
244 #[case("#00008b", Blue::DarkBlue)]
245 #[case("00008b", Blue::DarkBlue)]
246 #[case("darkblue", Blue::DarkBlue)]
247 #[case("#0000cd", Blue::MediumBlue)]
248 #[case("0000cd", Blue::MediumBlue)]
249 #[case("mediumblue", Blue::MediumBlue)]
250 #[case("#0000ff", Blue::Blue)]
251 #[case("0000ff", Blue::Blue)]
252 #[case("blue", Blue::Blue)]
253 #[case("#4169e1", Blue::RoyalBlue)]
254 #[case("4169e1", Blue::RoyalBlue)]
255 #[case("royalblue", Blue::RoyalBlue)]
256 #[case("#f0ffff", Blue::Azure)]
257 #[case("f0ffff", Blue::Azure)]
258 #[case("azure", Blue::Azure)]
259 fn test_from_str(#[case] input: &str, #[case] expected: Blue) {
260 assert_eq!(expected, Blue::from_str(input).unwrap())
261 }
262
263 #[rstest]
264 #[case("#b0e0e6", Some(Blue::PowderBlue))]
265 #[case("b0e0e6", Some(Blue::PowderBlue))]
266 #[case("powderblue", Some(Blue::PowderBlue))]
267 #[case("#5f9ea0", Some(Blue::CadetBlue))]
268 #[case("5f9ea0", Some(Blue::CadetBlue))]
269 #[case("cadetblue", Some(Blue::CadetBlue))]
270 #[case("#4682b4", Some(Blue::SteelBlue))]
271 #[case("4682b4", Some(Blue::SteelBlue))]
272 #[case("steelblue", Some(Blue::SteelBlue))]
273 #[case("#6495ed", Some(Blue::CornflowerBlue))]
274 #[case("6495ed", Some(Blue::CornflowerBlue))]
275 #[case("cornflowerblue", Some(Blue::CornflowerBlue))]
276 #[case("#00bfff", Some(Blue::DeepSkyBlue))]
277 #[case("00bfff", Some(Blue::DeepSkyBlue))]
278 #[case("deepskyblue", Some(Blue::DeepSkyBlue))]
279 #[case("#1e90ff", Some(Blue::DodgerBlue))]
280 #[case("1e90ff", Some(Blue::DodgerBlue))]
281 #[case("dodgerblue", Some(Blue::DodgerBlue))]
282 #[case("#add8e6", Some(Blue::LightBlue))]
283 #[case("add8e6", Some(Blue::LightBlue))]
284 #[case("lightblue", Some(Blue::LightBlue))]
285 #[case("#87ceeb", Some(Blue::SkyBlue))]
286 #[case("87ceeb", Some(Blue::SkyBlue))]
287 #[case("skyblue", Some(Blue::SkyBlue))]
288 #[case("#b0c4de", Some(Blue::LightSteelBlue))]
289 #[case("b0c4de", Some(Blue::LightSteelBlue))]
290 #[case("lightsteelblue", Some(Blue::LightSteelBlue))]
291 #[case("#87cefa", Some(Blue::LightSkyBlue))]
292 #[case("87cefa", Some(Blue::LightSkyBlue))]
293 #[case("lightskyblue", Some(Blue::LightSkyBlue))]
294 #[case("#191970", Some(Blue::MidnightBlue))]
295 #[case("191970", Some(Blue::MidnightBlue))]
296 #[case("midnightblue", Some(Blue::MidnightBlue))]
297 #[case("#000080", Some(Blue::Navy))]
298 #[case("000080", Some(Blue::Navy))]
299 #[case("navy", Some(Blue::Navy))]
300 #[case("#00008b", Some(Blue::DarkBlue))]
301 #[case("00008b", Some(Blue::DarkBlue))]
302 #[case("darkblue", Some(Blue::DarkBlue))]
303 #[case("#0000cd", Some(Blue::MediumBlue))]
304 #[case("0000cd", Some(Blue::MediumBlue))]
305 #[case("mediumblue", Some(Blue::MediumBlue))]
306 #[case("#0000ff", Some(Blue::Blue))]
307 #[case("0000ff", Some(Blue::Blue))]
308 #[case("blue", Some(Blue::Blue))]
309 #[case("#4169e1", Some(Blue::RoyalBlue))]
310 #[case("4169e1", Some(Blue::RoyalBlue))]
311 #[case("royalblue", Some(Blue::RoyalBlue))]
312 #[case("#f0ffff", Some(Blue::Azure))]
313 #[case("f0ffff", Some(Blue::Azure))]
314 #[case("azure", Some(Blue::Azure))]
315 #[case("012345", None)]
316 fn test_name_colour(#[case] input: &str, #[case] expected: Option<Blue>) {
317 assert_eq!(expected, Blue::name_colour(input))
318 }
319}