use crate::{Colors, Config, DigitWidth};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub struct Dimension {
pub width: u64,
pub height: u64,
}
impl Default for Dimension {
fn default() -> Self {
Dimension {
width: 3840,
height: 2160,
}
}
}
impl Dimension {
pub fn minimum(&self) -> u64 {
self.height.min(self.width)
}
pub fn maximum(&self) -> u64 {
self.height.max(self.width)
}
pub fn is_valid(&self, config: &Config) -> bool {
config.in_range(self.minimum()) && config.in_range(self.maximum())
}
pub fn get_log_min(&self, config: &Config) -> String {
let num = self.maximum().digit_width();
let min = self.minimum();
let min_str = format!("{min:>num$}");
if !config.in_range(self.minimum()) {
format!(
"Minimum dimension: {min}. The condition ({config_min} <= {min} <= {config_max}) is false.\n",
min = min_str.yellow(),
config_min = config.min_dimension.green(),
config_max = config.max_dimension.green(),
)
} else {
"".to_string()
}
}
pub fn get_log_max(&self, config: &Config) -> String {
if !config.in_range(self.maximum()) {
format!(
"Maximum dimension: {max}. The condition ({config_min} <= {max} <= {config_max}) is false.\n",
max = self.maximum().yellow(),
config_min = config.min_dimension.green(),
config_max = config.max_dimension.green(),
)
} else {
"".to_string()
}
}
}
impl fmt::Display for Dimension {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let height = self.height;
let width = self.width;
let max = height.max(width);
let num = max.digit_width();
write!(
f,
"Dimension {{ height: {height:>num$}, width: {width:>num$} }}",
)
}
}
#[cfg(test)]
mod tests_dimension {
use super::*;
#[test]
fn test_default_dimension() {
let default_dim = Dimension::default();
assert_eq!(default_dim.width, 3840);
assert_eq!(default_dim.height, 2160);
}
#[test]
fn test_minimum_and_maximum() {
let landscape = Dimension {
width: 1920,
height: 1080,
};
assert_eq!(landscape.minimum(), 1080);
assert_eq!(landscape.maximum(), 1920);
let portrait = Dimension {
width: 1080,
height: 1920,
};
assert_eq!(portrait.minimum(), 1080);
assert_eq!(portrait.maximum(), 1920);
let square = Dimension {
width: 1000,
height: 1000,
};
assert_eq!(square.minimum(), 1000);
assert_eq!(square.maximum(), 1000);
}
#[test]
fn test_display_formatting() {
let dim = Dimension {
width: 120,
height: 8,
};
let formatted = format!("{}", dim);
assert!(formatted.contains("height: 8"));
assert!(formatted.contains("width: 120"));
}
#[test]
fn test_validation_and_logs() {
let config = Config {
min_dimension: 100,
max_dimension: 5000,
..Default::default()
};
let valid_dim = Dimension {
width: 1920,
height: 1080,
};
assert!(valid_dim.is_valid(&config));
assert_eq!(valid_dim.get_log_min(&config), "");
assert_eq!(valid_dim.get_log_max(&config), "");
let small_dim = Dimension {
width: 50,
height: 1080,
};
assert!(!small_dim.is_valid(&config));
assert!(!small_dim.get_log_min(&config).is_empty());
let large_dim = Dimension {
width: 6000,
height: 1080,
};
assert!(!large_dim.is_valid(&config));
assert!(!large_dim.get_log_max(&config).is_empty());
}
}