use crate::pitch::{Accidental, PitchClassRepr, RawPitchClass};
use rstmt_traits::PitchMod;
pub trait IntoPitchClass<P, K>
where
P: RawPitchClass<Tag = K>,
K: Accidental,
{
fn into_pitch_class(self) -> PitchClass<P, K>;
private! {}
}
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
feature = "serde",
derive(serde::Deserialize, serde::Serialize),
serde(rename_all = "lowercase")
)]
#[repr(C)]
pub struct PitchClass<P = super::CNote, K = <P as RawPitchClass>::Tag>
where
P: RawPitchClass<Tag = K>,
K: Accidental,
{
pub(crate) class: P,
pub(crate) kind: K,
}
macro_rules! classes {
(@impl $name:ident::<Natural>) => {
paste::paste! {
pub type $name = $crate::pitch::PitchClass<$crate::pitch::[<$name Note>], $crate::pitch::Natural>;
}
};
(@impl $name:ident::<$kind:ident>) => {
paste::paste! {
pub type [<$name $kind>] = $crate::pitch::PitchClass<$crate::pitch::[<$name $kind Note>], $crate::pitch::$kind>;
}
};
(@impl $name:ident::<$($kind:ident),+ $(,)?>) => {
$(classes! { @impl $name::<$kind> })*
};
($($name:ident::<$($K:ident),* $(,)?>),* $(,)?) => {
$(classes! { @impl $name::<Natural, $($K),*> })*
};
}
classes! {
C::<Sharp>,
D::<Flat, Sharp>,
E::<Flat>,
F::<Sharp>,
G::<Flat, Sharp>,
A::<Flat, Sharp>,
B::<Flat>,
}
impl<P, K> IntoPitchClass<P, K> for isize
where
P: PitchClassRepr<Tag = K>,
K: Accidental,
{
seal! {}
fn into_pitch_class(self) -> PitchClass<P, K> {
match self.pmod() {
x if x == P::IDX => PitchClass::new(),
_ => panic!("cannot convert {self} into pitch class"),
}
}
}