use std::{cmp::Ordering, str::FromStr};
use url::Url;
#[derive(Debug, Clone, Copy, Eq)]
pub struct IconSize {
pub width: u32,
pub height: u32,
}
impl PartialEq for IconSize {
fn eq(&self, other: &Self) -> bool {
self.width == other.width && self.height == other.height
}
}
impl PartialOrd for IconSize {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for IconSize {
fn cmp(&self, other: &Self) -> Ordering {
self.total_pixels().cmp(&other.total_pixels())
}
}
impl IconSize {
pub fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
pub fn total_pixels(&self) -> u32 {
self.width * self.height
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IconInfo {
pub url: Url,
pub size: Option<IconSize>,
}
impl PartialOrd for IconInfo {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for IconInfo {
fn cmp(&self, other: &Self) -> Ordering {
let self_size = self.size.map(|s| s.total_pixels()).unwrap_or(0);
let other_size = other.size.map(|s| s.total_pixels()).unwrap_or(0);
self_size.cmp(&other_size)
}
}
impl IconInfo {
pub fn new(url: Url, sizes_prop: Option<&str>) -> Self {
let size = sizes_prop.map(|sizes_str| {
let width_height: Vec<&str> = sizes_str.split('x').collect();
let width = width_height.first().and_then(|w| u32::from_str(w).ok()).unwrap_or(0);
let height = width_height.get(1).and_then(|h| u32::from_str(h).ok()).unwrap_or(0);
IconSize::new(width, height)
});
Self { url, size }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_icon_size_cmp() {
let size1 = IconSize::new(10, 10);
let size2 = IconSize::new(20, 20);
let size3 = IconSize::new(10, 10);
assert!(size1 < size2);
assert!(size2 > size1);
assert!(size1 == size3);
}
#[test]
fn test_icon_info_new() {
let url = Url::parse("http://example.com/icon.png").unwrap();
let icon_info = IconInfo::new(url.clone(), Some("128x128"));
assert_eq!(icon_info.url, url);
assert_eq!(icon_info.size, Some(IconSize::new(128, 128)));
}
#[test]
fn icon_info_size_parsing() {
let url = Url::parse("https://example.com/icon.png").unwrap();
let info = IconInfo::new(url.clone(), Some("32x32"));
assert_eq!(info.size, Some(IconSize::new(32, 32)));
let info = IconInfo::new(url.clone(), Some("any"));
assert_eq!(info.size.unwrap().total_pixels(), 0); let info = IconInfo::new(url.clone(), None);
assert!(info.size.is_none());
}
}