use rstmt_traits::Numerical;
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
feature = "serde",
derive(serde::Deserialize, serde::Serialize),
serde(transparent)
)]
#[repr(transparent)]
pub struct Pitch<T = f64>(pub T);
pub trait RawPitch
where
Self: Send + Sync + core::fmt::Debug + core::fmt::Display + PartialEq + PartialOrd,
{
private! {}
}
pub trait NumPitch: RawPitch + Numerical {}
pub trait AsPitch<T>
where
T: RawPitch,
{
fn as_pitch(&self) -> Pitch<T>;
}
pub trait IntoPitch<T>
where
T: RawPitch,
{
fn into_pitch(self) -> Pitch<T>;
private! {}
}
pub trait Pitched<T>
where
T: RawPitch,
{
fn pitch(&self) -> Pitch<&T>;
}
impl<U, T> AsPitch<T> for U
where
U: Clone + IntoPitch<T>,
T: RawPitch,
{
fn as_pitch(&self) -> Pitch<T> {
self.clone().into_pitch()
}
}
impl<U, T> IntoPitch<T> for U
where
U: Into<Pitch<T>>,
T: RawPitch,
{
fn into_pitch(self) -> Pitch<T> {
self.into()
}
seal! {}
}
impl<T> RawPitch for &T
where
T: RawPitch,
{
seal! {}
}
impl<T> RawPitch for &mut T
where
T: RawPitch,
{
seal! {}
}
impl<T> NumPitch for T where T: RawPitch + Numerical {}
macro_rules! impl_raw_pitch {
($($tgt:ty),* $(,)?) => {
$(
impl RawPitch for $tgt {
seal! {}
}
)*
};
}
impl_raw_pitch! {
u8, u16, u32, u64, u128, usize,
i8, i16, i32, i64, i128, isize,
f32, f64
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pitch_creation() {
let a4 = Pitch(440f64);
assert_eq! { a4, 440.0 }
}
}