From ff019143282e0bc07c40d5e7e7d53e317ed8dc87 Mon Sep 17 00:00:00 2001 From: Peter Hebden Date: Sat, 5 Aug 2023 14:25:59 +0100 Subject: [PATCH] Parse hex colour codes in `serde::de::Deserialize` (#801) --- src/style/types/color.rs | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/style/types/color.rs b/src/style/types/color.rs index 4e05420be..6c42c079f 100644 --- a/src/style/types/color.rs +++ b/src/style/types/color.rs @@ -271,7 +271,7 @@ impl<'de> serde::de::Deserialize<'de> for Color { type Value = Color; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str( - "`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)`", + "`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`", ) } fn visit_str(self, value: &str) -> Result @@ -304,6 +304,20 @@ impl<'de> serde::de::Deserialize<'de> for Color { let g = results[1].parse::(); let b = results[2].parse::(); + if r.is_ok() && g.is_ok() && b.is_ok() { + return Ok(Color::Rgb { + r: r.unwrap(), + g: g.unwrap(), + b: b.unwrap(), + }); + } + } + } else if let Some(hex) = value.strip_prefix('#') { + if hex.is_ascii() && hex.len() == 6 { + let r = u8::from_str_radix(&hex[0..2], 16); + let g = u8::from_str_radix(&hex[2..4], 16); + let b = u8::from_str_radix(&hex[4..6], 16); + if r.is_ok() && g.is_ok() && b.is_ok() { return Ok(Color::Rgb { r: r.unwrap(), @@ -476,4 +490,24 @@ mod serde_tests { assert!(serde_json::from_str::("\"rgb_(255,255,255,255)\"").is_err()); assert!(serde_json::from_str::("\"rgb_(256,255,255)\"").is_err()); } + + #[test] + fn test_deserial_rgb_hex() { + assert_eq!( + serde_json::from_str::("\"#ffffff\"").unwrap(), + Color::from((255, 255, 255)) + ); + assert_eq!( + serde_json::from_str::("\"#FFFFFF\"").unwrap(), + Color::from((255, 255, 255)) + ); + } + + #[test] + fn test_deserial_unvalid_rgb_hex() { + assert!(serde_json::from_str::("\"#FFFFFFFF\"").is_err()); + assert!(serde_json::from_str::("\"#FFGFFF\"").is_err()); + // Ferris is 4 bytes so this will be considered the correct length. + assert!(serde_json::from_str::("\"#ff🦀\"").is_err()); + } }