use core::marker::PhantomData;
use glam::DVec3;
use uom::si::{Dimension, Quantity, SI};
use crate::derive_utils::{
impl_clone_phantom, impl_copy_phantom, impl_debug_phantom, impl_partial_eq_phantom,
};
use crate::frame::Frame;
#[repr(C)]
pub struct Qty3<D: ?Sized + Dimension, F: Frame> {
pub x: Quantity<D, SI<f64>, f64>,
pub y: Quantity<D, SI<f64>, f64>,
pub z: Quantity<D, SI<f64>, f64>,
_f: PhantomData<F>,
}
impl<D: ?Sized + Dimension, F: Frame> Qty3<D, F> {
#[inline]
pub const fn new(
x: Quantity<D, SI<f64>, f64>,
y: Quantity<D, SI<f64>, f64>,
z: Quantity<D, SI<f64>, f64>,
) -> Self {
Self {
x,
y,
z,
_f: PhantomData,
}
}
#[inline(always)]
pub fn raw_si(&self) -> DVec3 {
DVec3::new(self.x.value, self.y.value, self.z.value)
}
#[inline(always)]
pub fn from_raw_si(v: DVec3) -> Self {
Self {
x: Quantity {
dimension: PhantomData,
units: PhantomData,
value: v.x,
},
y: Quantity {
dimension: PhantomData,
units: PhantomData,
value: v.y,
},
z: Quantity {
dimension: PhantomData,
units: PhantomData,
value: v.z,
},
_f: PhantomData,
}
}
#[inline]
pub fn zero() -> Self {
Self::from_raw_si(DVec3::ZERO)
}
#[inline(always)]
pub fn relabel_to<F2: Frame>(self) -> Qty3<D, F2> {
Qty3 {
x: self.x,
y: self.y,
z: self.z,
_f: PhantomData,
}
}
}
impl_copy_phantom!([D: ?Sized + Dimension, F: Frame] Qty3[D, F]);
impl_clone_phantom!([D: ?Sized + Dimension, F: Frame] Qty3[D, F]);
impl_debug_phantom!(
[D: ?Sized + Dimension, F: Frame] Qty3[D, F],
|this, f| write!(
f,
"Qty3<{}>({}, {}, {})",
core::any::type_name::<F>(),
this.x.value,
this.y.value,
this.z.value
)
);
impl_partial_eq_phantom!(
[D: ?Sized + Dimension, F: Frame] Qty3[D, F],
|this, other| this.x.value == other.x.value
&& this.y.value == other.y.value
&& this.z.value == other.z.value
);
impl<D: ?Sized + Dimension, F: Frame> Default for Qty3<D, F> {
#[inline]
fn default() -> Self {
Self::zero()
}
}
#[cfg(feature = "serde")]
impl<D: ?Sized + Dimension, F: Frame> serde::Serialize for Qty3<D, F> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let v = self.raw_si();
[v.x, v.y, v.z].serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, D: ?Sized + Dimension, F: Frame> serde::Deserialize<'de> for Qty3<D, F> {
fn deserialize<De: serde::Deserializer<'de>>(deserializer: De) -> Result<Self, De::Error> {
let [x, y, z] = <[f64; 3]>::deserialize(deserializer)?;
Ok(Self::from_raw_si(DVec3::new(x, y, z)))
}
}