use std::ops::{Add, Sub, Neg};
pub trait CoordInt:
Copy + Clone +
PartialEq + Eq +
PartialOrd + Ord +
Add<Output = Self> +
Sub<Output = Self> +
Neg<Output = Self> +
Send + Sync +
std::fmt::Debug
{
const ZERO: Self;
fn from_i64(v: i64) -> Self;
fn shift_left(self, bits: u32) -> Self;
fn shift_right(self, bits: u32) -> Self;
fn into_i128(self) -> i128;
}
impl CoordInt for i64 {
const ZERO: Self = 0;
fn from_i64(v: i64) -> Self { v }
fn shift_left(self, bits: u32) -> Self { self << bits }
fn shift_right(self, bits: u32) -> Self { self >> bits }
fn into_i128(self) -> i128 { i128::from(self) }
}
impl CoordInt for i128 {
const ZERO: Self = 0;
fn from_i64(v: i64) -> Self { Self::from(v) }
fn shift_left(self, bits: u32) -> Self { self << bits }
fn shift_right(self, bits: u32) -> Self { self >> bits }
fn into_i128(self) -> i128 { self }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Coord<T: CoordInt>(T);
pub type Coord64 = Coord<i64>;
pub type Coord128 = Coord<i128>;
impl<T: CoordInt> Coord<T> {
pub const ZERO: Self = Self(T::ZERO);
pub const fn from_raw(raw: T) -> Self { Self(raw) }
pub fn from_um(um: i64) -> Self { Self(T::from_i64(um).shift_left(32)) }
pub fn from_mm(mm: i64) -> Self { Self::from_um(mm * 1_000) }
pub fn from_m(m: i64) -> Self { Self::from_um(m * 1_000_000) }
pub const fn raw(self) -> T { self.0 }
pub fn whole_um(self) -> T { self.0.shift_right(32) }
pub fn into_i128(self) -> i128 { self.0.into_i128() }
}
impl Coord64 {
pub fn from_f32(um: f32) -> Self {
Self::from_raw((f64::from(um) * (1i64 << 32) as f64) as i64)
}
pub fn from_f64(um: f64) -> Self {
Self::from_raw((um * (1i64 << 32) as f64) as i64)
}
pub fn to_f32(self) -> f32 {
self.0 as f32 / (1i64 << 32) as f32
}
pub fn to_f64(self) -> f64 {
self.0 as f64 / (1i64 << 32) as f64
}
}
impl<T: CoordInt> Add for Coord<T> {
type Output = Self;
fn add(self, rhs: Self) -> Self { Self(self.0 + rhs.0) }
}
impl<T: CoordInt> Sub for Coord<T> {
type Output = Self;
fn sub(self, rhs: Self) -> Self { Self(self.0 - rhs.0) }
}
impl<T: CoordInt> Neg for Coord<T> {
type Output = Self;
fn neg(self) -> Self { Self(-self.0) }
}