From 24e7cfb0d5e5d2efce1dcf2cfb29a2110161ad06 Mon Sep 17 00:00:00 2001 From: Tobias Decking Date: Fri, 15 Mar 2024 21:58:46 +0100 Subject: [PATCH] Fix `hex_to_hsla` inside the color crate (#9412) Previously, when `hex_to_hsla` was called with a color string using the #rgb format, the expansion did not add alpha values, leading to an incorrect result. This patch fixes the issue. In addition to that, parsing has been reworked, and the new function no longer makes calls to the global allocator in addition to generation much smaller code. Parsing should therefore be a bit more performant. --- crates/color/src/color.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/crates/color/src/color.rs b/crates/color/src/color.rs index 4f5946fbde..49bdc53fd1 100644 --- a/crates/color/src/color.rs +++ b/crates/color/src/color.rs @@ -58,24 +58,23 @@ pub fn hex_to_hsla(s: &str) -> Result { let hex = s.trim_start_matches('#'); // Expand shorthand formats #RGB and #RGBA to #RRGGBB and #RRGGBBAA - let hex = match hex.len() { - 3 => hex.chars().map(|c| c.to_string().repeat(2)).collect(), - 4 => { - let (rgb, alpha) = hex.split_at(3); - let rgb = rgb - .chars() - .map(|c| c.to_string().repeat(2)) - .collect::(); - let alpha = alpha.chars().next().unwrap().to_string().repeat(2); - format!("{}{}", rgb, alpha) - } - 6 => format!("{}ff", hex), // Add alpha if missing - 8 => hex.to_string(), // Already in full format + let h = hex.as_bytes(); + let arr: [u8; 8] = match h.len() { + // #RGB => #RRGGBBAA + 3 => [h[0], h[0], h[1], h[1], h[2], h[2], b'f', b'f'], + // #RGBA => #RRGGBBAA + 4 => [h[0], h[0], h[1], h[1], h[2], h[2], h[3], h[3]], + // #RRGGBB => #RRGGBBAA + 6 => [h[0], h[1], h[2], h[3], h[4], h[5], b'f', b'f'], + // Already in #RRGGBBAA + 8 => h.try_into().unwrap(), _ => return Err("Invalid hexadecimal string length".to_string()), }; + let hex = + std::str::from_utf8(&arr).map_err(|_| format!("Invalid hexadecimal string: {}", s))?; let hex_val = - u32::from_str_radix(&hex, 16).map_err(|_| format!("Invalid hexadecimal string: {}", s))?; + u32::from_str_radix(hex, 16).map_err(|_| format!("Invalid hexadecimal string: {}", s))?; Ok(RGBAColor { r: ((hex_val >> 24) & 0xFF) as f32 / 255.0,