use crate::types::BorderItem;
fn parse_color(s: &str) -> Option<(u8, u8, u8)> {
let s = s.trim_start_matches('#');
match s.len() {
6 => {
let r = u8::from_str_radix(&s[0..2], 16).ok()?;
let g = u8::from_str_radix(&s[2..4], 16).ok()?;
let b = u8::from_str_radix(&s[4..6], 16).ok()?;
Some((r, g, b))
}
3 => {
let r = u8::from_str_radix(&s[0..1], 16).ok()?;
let g = u8::from_str_radix(&s[1..2], 16).ok()?;
let b = u8::from_str_radix(&s[2..3], 16).ok()?;
Some((r * 17, g * 17, b * 17))
}
_ => None,
}
}
fn compute_luminance(r: u8, g: u8, b: u8) -> f64 {
let r = r as f64 / 255.0;
let g = g as f64 / 255.0;
let b = b as f64 / 255.0;
0.299 * r + 0.587 * g + 0.114 * b
}
fn is_max_color(a: &str, b: &str) -> bool {
let (ar, ag, ab) = match parse_color(a) {
Some(rgb) => rgb,
None => return false, };
let (br, bg, bb) = match parse_color(b) {
Some(rgb) => rgb,
None => return false, };
let luminance_a = compute_luminance(ar, ag, ab);
let luminance_b = compute_luminance(br, bg, bb);
luminance_b < luminance_a
}
pub(crate) fn is_max_border(a: Option<&BorderItem>, b: Option<&BorderItem>) -> bool {
match (a, b) {
(_, None) => false,
(None, Some(_)) => true,
(Some(item_a), Some(item_b)) => {
if item_a.style < item_b.style {
return true;
} else if item_a.style > item_b.style {
return false;
}
match (&item_a.color, &item_b.color) {
(_, None) => false,
(None, Some(_)) => true,
(Some(color_a), Some(color_b)) => is_max_color(color_a, color_b),
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::BorderStyle;
#[test]
fn compare_borders() {
let b = BorderItem {
style: BorderStyle::Thin,
color: Some("#FFF".to_string()),
};
assert!(is_max_border(None, Some(&b)));
assert!(!is_max_border(Some(&b), None));
}
#[test]
fn basic_colors() {
assert!(is_max_color("#FFFFFF", "#000000"));
assert!(!is_max_color("#000000", "#FFFFFF"));
assert!(is_max_color("#FF0000", "#800000"));
assert!(!is_max_color("#800000", "#FF0000"));
assert!(is_max_color("#00FF00", "#008000"));
assert!(!is_max_color("#008000", "#00FF00"));
assert!(is_max_color("#0000FF", "#000080"));
assert!(!is_max_color("#000080", "#0000FF"));
}
#[test]
fn same_color() {
assert!(!is_max_color("#123456", "#123456"));
}
#[test]
fn edge_cases() {
assert!(!is_max_color("#000000", "#010101"));
assert!(!is_max_color("#FEFEFE", "#FFFFFF"));
assert!(!is_max_color("#7F7F7F", "#808080"));
}
#[test]
fn luminance_ordering() {
assert!(is_max_color("#CCCCCC", "#333333")); assert!(is_max_color("#FFFF00", "#808000")); assert!(is_max_color("#FF00FF", "#800080")); }
#[test]
fn borderline_cases() {
assert!(!is_max_color("#777777", "#777777"));
assert!(!is_max_color("#000000", "#010000"));
}
}