use std::cmp;
use gazebo::prelude::*;
use crate::{content::LinesExt, Line};
#[derive(Debug, Copy, Clone, Dupe, Eq, PartialEq, Default)]
pub struct Dimensions {
pub x: usize,
pub y: usize,
}
#[derive(Debug, Copy, Clone, Dupe, Eq, PartialEq)]
pub enum Direction {
Horizontal,
Vertical,
}
impl From<(u16, u16)> for Dimensions {
fn from((x, y): (u16, u16)) -> Self {
Self {
x: x.into(),
y: y.into(),
}
}
}
impl From<(usize, usize)> for Dimensions {
fn from((x, y): (usize, usize)) -> Self {
Self { x, y }
}
}
impl Dimensions {
pub fn new(x: usize, y: usize) -> Self {
Self { x, y }
}
pub fn dimension(self, direction: Direction) -> usize {
match direction {
Direction::Horizontal => self.x,
Direction::Vertical => self.y,
}
}
pub fn multiply(self, multiplicand: f64, direction: Direction) -> Self {
fn mul(lhs: usize, rhs: f64) -> usize {
let lhs = lhs as f64; let result = lhs * rhs;
result as usize }
let Self { x, y } = self;
match direction {
Direction::Horizontal => Self {
x: mul(x, multiplicand),
y,
},
Direction::Vertical => Self {
x,
y: mul(y, multiplicand),
},
}
}
pub fn saturating_sub(self, subtractor: usize, direction: Direction) -> Self {
let Self { x, y } = self;
match direction {
Direction::Horizontal => Self {
x: x.saturating_sub(subtractor),
y,
},
Direction::Vertical => Self {
x,
y: y.saturating_sub(subtractor),
},
}
}
#[allow(clippy::ptr_arg)]
pub fn dimension_from_output_truncated(output: &Vec<Line>, direction: Direction) -> usize {
match direction {
Direction::Horizontal => output.max_line_length(),
Direction::Vertical => output.len(),
}
}
pub fn intersect(self, Self { x, y }: Self) -> Self {
Self {
x: cmp::min(self.x, x),
y: cmp::min(self.y, y),
}
}
pub fn union(self, Self { x, y }: Self) -> Self {
Self {
x: cmp::max(self.x, x),
y: cmp::max(self.y, y),
}
}
pub fn contains(self, Self { x, y }: Self) -> bool {
x <= self.x && y <= self.y
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_intersect() {
let lhs = Dimensions { x: 5, y: 10 };
let rhs = Dimensions { x: 8, y: 3 };
let intersect = lhs.intersect(rhs);
assert_eq!(intersect, Dimensions { x: 5, y: 3 });
}
#[test]
fn test_union() {
let lhs = Dimensions { x: 5, y: 10 };
let rhs = Dimensions { x: 8, y: 3 };
let union = lhs.union(rhs);
assert_eq!(union, Dimensions { x: 8, y: 10 });
}
#[test]
fn test_contains() {
let lhs = Dimensions { x: 8, y: 10 };
let rhs = Dimensions { x: 5, y: 3 };
assert!(lhs.contains(rhs));
assert!(!rhs.contains(lhs));
assert!(lhs.contains(lhs));
}
}