use std::hash::{BuildHasherDefault, Hasher}; #[derive(Debug, Clone, Copy, Default)] pub struct IdentityHasher(usize); impl Hasher for IdentityHasher { fn finish(&self) -> u64 { self.0 as u64 } fn write(&mut self, _bytes: &[u8]) { unimplemented!("IdentityHasher only supports usize keys") } fn write_u64(&mut self, i: u64) { self.0 = i as usize; } fn write_usize(&mut self, i: usize) { self.0 = i; } } pub type BuildIdentityHasher = BuildHasherDefault; pub use point::Point; pub use size::Size; mod size { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] pub struct Size where I: num_traits::PrimInt + num_traits::Zero, { pub width: I, pub height: I, } impl std::ops::Add for Size where I: num_traits::PrimInt + num_traits::Zero, { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self { width: self.width + rhs.width, height: self.height + rhs.height, } } } impl std::ops::Sub for Size where I: num_traits::PrimInt + num_traits::Zero, { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self { width: self.width - rhs.width, height: self.height - rhs.height, } } } impl num_traits::Zero for Size where I: num_traits::PrimInt + num_traits::Zero, { fn zero() -> Self { Self::default() } fn is_zero(&self) -> bool { self.width == I::zero() && self.height == I::zero() } } impl Default for Size where I: num_traits::PrimInt + num_traits::Zero, { fn default() -> Self { Self { width: I::zero(), height: I::zero(), } } } impl From<(I, I)> for Size where I: num_traits::PrimInt + num_traits::Zero, { fn from(value: (I, I)) -> Self { Self::from_tuple(value) } } impl From> for Size where I: num_traits::PrimInt + num_traits::Zero, { fn from(value: super::point::Point) -> Self { Self::new(value.x, value.y) } } impl Size where I: num_traits::PrimInt + num_traits::Zero, { pub fn new(width: I, height: I) -> Self { Self { width, height } } pub fn from_tuple(tuple: (I, I)) -> Self { Self::new(tuple.0, tuple.1) } pub fn as_tuple(&self) -> (I, I) { (self.width, self.height) } pub fn clamp(self, other: Self) -> Self { Self::new( self.width.min(other.width), self.height.min(other.height), ) } pub fn map(self, f: F) -> Self where F: FnOnce(I, I) -> Self, { f(self.width, self.height) } } } mod point { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] pub struct Point where I: num_traits::PrimInt + num_traits::Zero, { pub x: I, pub y: I, } impl std::ops::Add for Point where I: num_traits::PrimInt + num_traits::Zero, { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self { x: self.x + rhs.x, y: self.y + rhs.y, } } } impl std::ops::Sub for Point where I: num_traits::PrimInt + num_traits::Zero, { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self { x: self.x - rhs.x, y: self.y - rhs.y, } } } impl num_traits::Zero for Point where I: num_traits::PrimInt + num_traits::Zero, { fn zero() -> Self { Self::default() } fn is_zero(&self) -> bool { self.x == I::zero() && self.y == I::zero() } } impl Default for Point where I: num_traits::PrimInt + num_traits::Zero, { fn default() -> Self { Self { x: I::zero(), y: I::zero(), } } } impl From<(I, I)> for Point where I: num_traits::PrimInt + num_traits::Zero, { fn from(value: (I, I)) -> Self { Self::from_tuple(value) } } impl From> for Point where I: num_traits::PrimInt + num_traits::Zero, { fn from(value: super::size::Size) -> Self { Self::new(value.width, value.height) } } impl Point where I: num_traits::PrimInt + num_traits::Zero, { pub fn new(x: I, y: I) -> Self { Self { x, y } } pub fn from_tuple(tuple: (I, I)) -> Self { Self::new(tuple.0, tuple.1) } pub fn as_tuple(&self) -> (I, I) { (self.x, self.y) } pub fn map(self, f: F) -> T where F: FnOnce(I, I) -> T, { f(self.x, self.y) } } }