rstmt_core/intervals/
qualities.rs1pub trait Quality {
15 private!();
16
17 fn phantom() -> PhantomData<Self> {
18 PhantomData::<Self>
19 }
20
21 fn kind() -> IntervalQuality {
22 match Self::name() {
23 "Augmented" => IntervalQuality::augmented(),
24 "Diminished" => IntervalQuality::diminished(),
25 "Major" => IntervalQuality::major(),
26 "Minor" => IntervalQuality::minor(),
27 "Perfect" => IntervalQuality::perfect(),
28 _ => unreachable!(),
29 }
30 }
31
32 fn name() -> &'static str {
33 core::any::type_name::<Self>()
34 }
35
36 fn is_augmented() -> bool {
37 false
38 }
39
40 fn is_diminished() -> bool {
41 false
42 }
43
44 fn is_perfect() -> bool {
45 false
46 }
47
48 fn is_major() -> bool {
49 false
50 }
51
52 fn is_minor() -> bool {
53 false
54 }
55}
56
57macro_rules! quality {
58 (@impl $name:ident::$call:ident) => {
59 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
60 #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize),)]
61 pub enum $name {}
62
63 impl Quality for $name {
64 seal!();
65
66 fn kind() -> IntervalQuality {
67 IntervalQuality::$call()
68 }
69
70 fn name() -> &'static str {
71 stringify!($call)
72 }
73
74 paste::paste! {
75 fn [<is_ $call>]() -> bool {
76 true
77 }
78 }
79 }
80
81 unsafe impl Send for $name {}
82
83 unsafe impl Sync for $name {}
84 };
85 ($($name:ident::$call:ident),* $(,)?) => {
86 $(
87 quality!(@impl $name::$call);
88 )*
89 };
90}
91
92quality!(
93 Augmented::augmented,
94 Diminished::diminished,
95 Major::major,
96 Minor::minor,
97 Perfect::perfect
98);
99
100use core::marker::PhantomData;
101
102#[derive(
105 Clone,
106 Copy,
107 Debug,
108 Eq,
109 Hash,
110 Ord,
111 PartialEq,
112 PartialOrd,
113 strum::AsRefStr,
114 strum::Display,
115 strum::EnumCount,
116 strum::EnumIs,
117 strum::EnumIter,
118 strum::EnumString,
119 strum::VariantNames,
120)]
121#[cfg_attr(
122 feature = "serde",
123 derive(serde::Deserialize, serde::Serialize),
124 serde(rename_all = "lowercase")
125)]
126#[non_exhaustive]
127#[strum(serialize_all = "lowercase")]
128pub enum IntervalQuality {
129 Augmented(PhantomData<Augmented>),
130 Diminished(PhantomData<Diminished>),
131 Major(PhantomData<Major>),
132 Minor(PhantomData<Minor>),
133 Perfect(PhantomData<Perfect>),
134}
135
136impl IntervalQuality {
137 pub fn new<Q: Quality>() -> Self {
138 Q::kind()
139 }
140 pub fn augmented() -> Self {
141 IntervalQuality::Augmented(PhantomData)
142 }
143
144 pub fn diminished() -> Self {
145 IntervalQuality::Diminished(PhantomData)
146 }
147
148 pub fn major() -> Self {
149 IntervalQuality::Major(PhantomData)
150 }
151
152 pub fn minor() -> Self {
153 IntervalQuality::Minor(PhantomData)
154 }
155
156 pub fn perfect() -> Self {
157 IntervalQuality::Perfect(PhantomData)
158 }
159
160 pub fn from_str(value: &str) -> Option<Self> {
161 match value {
162 "Augmented" | "augmented" => Some(IntervalQuality::augmented()),
163 "Diminished" | "diminished" => Some(IntervalQuality::diminished()),
164 "Major" | "major" => Some(IntervalQuality::major()),
165 "Minor" | "minor" => Some(IntervalQuality::minor()),
166 "Perfect" | "perfect" => Some(IntervalQuality::perfect()),
167 _ => None,
168 }
169 }
170}