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.
This commit is contained in:
Tobias Decking 2024-03-15 21:58:46 +01:00 committed by GitHub
parent c1f1c5e75f
commit 24e7cfb0d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -58,24 +58,23 @@ pub fn hex_to_hsla(s: &str) -> Result<RGBAColor, String> {
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::<String>();
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,