rstmt_core/pitch/
pitch_class.rs1use crate::pitch::{Accidental, PitchClassRepr, RawPitchClass};
7use rstmt_traits::PitchMod;
8
9pub trait IntoPitchClass<P, K>
10where
11 P: RawPitchClass<Tag = K>,
12 K: Accidental,
13{
14 fn into_pitch_class(self) -> PitchClass<P, K>;
15
16 private! {}
17}
18
19#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
27#[cfg_attr(
28 feature = "serde",
29 derive(serde::Deserialize, serde::Serialize),
30 serde(rename_all = "lowercase")
31)]
32#[repr(C)]
33pub struct PitchClass<P = super::CNote, K = <P as RawPitchClass>::Tag>
34where
35 P: RawPitchClass<Tag = K>,
36 K: Accidental,
37{
38 pub(crate) class: P,
39 pub(crate) kind: K,
40}
41
42macro_rules! classes {
46 (@impl $name:ident::<Natural>) => {
47 paste::paste! {
48 pub type $name = $crate::pitch::PitchClass<$crate::pitch::[<$name Note>], $crate::pitch::Natural>;
49 }
50 };
51 (@impl $name:ident::<$kind:ident>) => {
52 paste::paste! {
53 pub type [<$name $kind>] = $crate::pitch::PitchClass<$crate::pitch::[<$name $kind Note>], $crate::pitch::$kind>;
54 }
55 };
56 (@impl $name:ident::<$($kind:ident),+ $(,)?>) => {
57 $(classes! { @impl $name::<$kind> })*
58 };
59 ($($name:ident::<$($K:ident),* $(,)?>),* $(,)?) => {
60 $(classes! { @impl $name::<Natural, $($K),*> })*
61 };
62}
63
64classes! {
65 C::<Sharp>,
66 D::<Flat, Sharp>,
67 E::<Flat>,
68 F::<Sharp>,
69 G::<Flat, Sharp>,
70 A::<Flat, Sharp>,
71 B::<Flat>,
72}
73
74impl<P, K> IntoPitchClass<P, K> for isize
75where
76 P: PitchClassRepr<Tag = K>,
77 K: Accidental,
78{
79 seal! {}
80
81 fn into_pitch_class(self) -> PitchClass<P, K> {
82 match self.pmod() {
83 x if x == P::IDX => PitchClass::new(),
84 _ => panic!("cannot convert {self} into pitch class"),
85 }
86 }
87}