use std::fmt::{Debug, Formatter}; use std::marker::PhantomData; pub trait CoordinateSpace {} #[derive(PartialEq, Eq, Clone, Copy)] pub struct Coordinates, S: CoordinateSpace> { pub x: T, pub y: T, space: PhantomData, } impl + Debug, S: CoordinateSpace> Debug for Coordinates { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_tuple("@") .field(&self.x) .field(&self.y) .finish() } } pub trait CoordLimits { type Data: Sized; const MIN: Self::Data; const MAX: Self::Data; } impl CoordLimits for u8 { type Data = u8; const MIN: u8 = 0; const MAX: u8 = 255; } impl CoordLimits for u16 { type Data = u16; const MIN: u16 = u16::MIN; const MAX: u16 = u16::MAX; } impl CoordLimits for usize { type Data = usize; const MIN: usize = usize::MIN; const MAX: usize = usize::MAX; } impl, S: CoordinateSpace> Coordinates { pub const fn new(x: T, y: T) -> Self { Self { x, y, space: PhantomData, } } fn top_left() -> Self { Self::new(T::MIN, T::MIN) } fn top_right() -> Self { Self::new(T::MAX, T::MIN) } fn bottom_left() -> Self { Self::new(T::MIN, T::MAX) } fn bottom_right() -> Self { Self::new(T::MAX, T::MAX) } } #[derive(PartialEq, Debug, Copy, Clone)] pub struct Virtual {} impl CoordinateSpace for Virtual {} #[derive(PartialEq, Debug, Copy, Clone)] pub struct Physical {} impl CoordinateSpace for Physical {} #[derive(PartialEq, Debug, Copy, Clone)] pub struct Coord8 { x: u8, y: u8, space: PhantomData } pub type VirtualCoordinates = Coordinates; pub type PhysicalCoordinates = Coordinates; #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct Rectangle, Space: CoordinateSpace> { pub top_left: Coordinates, pub bottom_right: Coordinates } impl, Space: CoordinateSpace> Rectangle { pub fn new(top_left: Coordinates, bottom_right: Coordinates) -> Self { Self { top_left, bottom_right } } pub fn everything() -> Self { Self { top_left: Coordinates::::top_left(), bottom_right: Coordinates::::bottom_right() } } }