Skip to content

Commit ff01914

Browse files
authored
Parse hex colour codes in serde::de::Deserialize (#801)
1 parent 2cb2658 commit ff01914

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

src/style/types/color.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ impl<'de> serde::de::Deserialize<'de> for Color {
271271
type Value = Color;
272272
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
273273
formatter.write_str(
274-
"`black`, `blue`, `dark_blue`, `cyan`, `dark_cyan`, `green`, `dark_green`, `grey`, `dark_grey`, `magenta`, `dark_magenta`, `red`, `dark_red`, `white`, `yellow`, `dark_yellow`, `ansi_(value)`, or `rgb_(r,g,b)`",
274+
"`black`, `blue`, `dark_blue`, `cyan`, `dark_cyan`, `green`, `dark_green`, `grey`, `dark_grey`, `magenta`, `dark_magenta`, `red`, `dark_red`, `white`, `yellow`, `dark_yellow`, `ansi_(value)`, or `rgb_(r,g,b)` or `#rgbhex`",
275275
)
276276
}
277277
fn visit_str<E>(self, value: &str) -> Result<Color, E>
@@ -304,6 +304,20 @@ impl<'de> serde::de::Deserialize<'de> for Color {
304304
let g = results[1].parse::<u8>();
305305
let b = results[2].parse::<u8>();
306306

307+
if r.is_ok() && g.is_ok() && b.is_ok() {
308+
return Ok(Color::Rgb {
309+
r: r.unwrap(),
310+
g: g.unwrap(),
311+
b: b.unwrap(),
312+
});
313+
}
314+
}
315+
} else if let Some(hex) = value.strip_prefix('#') {
316+
if hex.is_ascii() && hex.len() == 6 {
317+
let r = u8::from_str_radix(&hex[0..2], 16);
318+
let g = u8::from_str_radix(&hex[2..4], 16);
319+
let b = u8::from_str_radix(&hex[4..6], 16);
320+
307321
if r.is_ok() && g.is_ok() && b.is_ok() {
308322
return Ok(Color::Rgb {
309323
r: r.unwrap(),
@@ -476,4 +490,24 @@ mod serde_tests {
476490
assert!(serde_json::from_str::<Color>("\"rgb_(255,255,255,255)\"").is_err());
477491
assert!(serde_json::from_str::<Color>("\"rgb_(256,255,255)\"").is_err());
478492
}
493+
494+
#[test]
495+
fn test_deserial_rgb_hex() {
496+
assert_eq!(
497+
serde_json::from_str::<Color>("\"#ffffff\"").unwrap(),
498+
Color::from((255, 255, 255))
499+
);
500+
assert_eq!(
501+
serde_json::from_str::<Color>("\"#FFFFFF\"").unwrap(),
502+
Color::from((255, 255, 255))
503+
);
504+
}
505+
506+
#[test]
507+
fn test_deserial_unvalid_rgb_hex() {
508+
assert!(serde_json::from_str::<Color>("\"#FFFFFFFF\"").is_err());
509+
assert!(serde_json::from_str::<Color>("\"#FFGFFF\"").is_err());
510+
// Ferris is 4 bytes so this will be considered the correct length.
511+
assert!(serde_json::from_str::<Color>("\"#ff🦀\"").is_err());
512+
}
479513
}

0 commit comments

Comments
 (0)