use std::ops::{Deref, DerefMut};
use bytemuck::{Pod, Zeroable};
use crate::{Point, Vector, Scalar, Space, HcPoint};
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct View2<T> {
pub x: T,
pub y: T,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct View3<T> {
pub x: T,
pub y: T,
pub z: T,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct View4<T> {
pub x: T,
pub y: T,
pub z: T,
pub w: T,
}
unsafe impl<T: Zeroable> Zeroable for View2<T> {}
unsafe impl<T: Zeroable> Zeroable for View3<T> {}
unsafe impl<T: Zeroable> Zeroable for View4<T> {}
unsafe impl<T: Pod> Pod for View2<T> {}
unsafe impl<T: Pod> Pod for View3<T> {}
unsafe impl<T: Pod> Pod for View4<T> {}
macro_rules! impl_view_deref {
($ty:ident, $n:expr, $view_ty:ident $(, $field:ident)?) => {
impl<T: Scalar, S: Space> Deref for $ty<T, $n, S> {
type Target = $view_ty<T>;
fn deref(&self) -> &Self::Target {
bytemuck::cast_ref(&(*self) $(. $field)?)
}
}
impl<T: Scalar, S: Space> DerefMut for $ty<T, $n, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
bytemuck::cast_mut(&mut (*self) $(. $field)?)
}
}
};
}
impl_view_deref!(Vector, 2, View2);
impl_view_deref!(Vector, 3, View3);
impl_view_deref!(Vector, 4, View4);
impl_view_deref!(Point, 2, View2);
impl_view_deref!(Point, 3, View3);
impl_view_deref!(HcPoint, 2, View2, coords);
impl_view_deref!(HcPoint, 3, View3, coords);
pub trait HasX {
type Scalar;
fn x(&self) -> &Self::Scalar;
fn x_mut(&mut self) -> &mut Self::Scalar;
}
pub trait HasY {
type Scalar;
fn y(&self) -> &Self::Scalar;
fn y_mut(&mut self) -> &mut Self::Scalar;
}
pub trait HasZ {
type Scalar;
fn z(&self) -> &Self::Scalar;
fn z_mut(&mut self) -> &mut Self::Scalar;
}
pub trait HasW {
type Scalar;
fn w(&self) -> &Self::Scalar;
fn w_mut(&mut self) -> &mut Self::Scalar;
}
macro_rules! impl_has_axis {
($ty:ident, $d:expr, $trait:ident, $i:expr, $axis:ident, $axis_mut:ident) => {
impl<T: Scalar, S: Space> $trait for $ty<T, $d, S> {
type Scalar = T;
fn $axis(&self) -> &Self::Scalar {
&self[$i]
}
fn $axis_mut(&mut self) -> &mut Self::Scalar {
&mut self[$i]
}
}
};
}
impl_has_axis!(Vector, 2, HasX, 0, x, x_mut);
impl_has_axis!(Vector, 3, HasX, 0, x, x_mut);
impl_has_axis!(Vector, 4, HasX, 0, x, x_mut);
impl_has_axis!(Point, 2, HasX, 0, x, x_mut);
impl_has_axis!(Point, 3, HasX, 0, x, x_mut);
impl_has_axis!(Vector, 2, HasY, 1, y, y_mut);
impl_has_axis!(Vector, 3, HasY, 1, y, y_mut);
impl_has_axis!(Vector, 4, HasY, 1, y, y_mut);
impl_has_axis!(Point, 2, HasY, 1, y, y_mut);
impl_has_axis!(Point, 3, HasY, 1, y, y_mut);
impl_has_axis!(Vector, 3, HasZ, 2, z, z_mut);
impl_has_axis!(Vector, 4, HasZ, 2, z, z_mut);
impl_has_axis!(Point, 3, HasZ, 2, z, z_mut);
impl_has_axis!(Vector, 4, HasW, 3, w, w_mut);