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