rstmt_nrt/types/
factors.rs1use strum::IntoEnumIterator;
6
7#[derive(
10 Clone,
11 Copy,
12 Debug,
13 Eq,
14 Hash,
15 Ord,
16 PartialEq,
17 PartialOrd,
18 strum::AsRefStr,
19 strum::Display,
20 strum::EnumCount,
21 strum::EnumDiscriminants,
22 strum::EnumIs,
23 strum::VariantNames,
24)]
25#[cfg_attr(
26 feature = "serde",
27 derive(serde::Deserialize, serde::Serialize),
28 serde(rename_all = "lowercase"),
29 strum_discriminants(
30 derive(serde::Deserialize, serde::Serialize),
31 serde(rename_all = "lowercase")
32 )
33)]
34#[strum_discriminants(
35 name(Factors),
36 derive(
37 Hash,
38 Ord,
39 PartialOrd,
40 strum::AsRefStr,
41 strum::Display,
42 strum::EnumCount,
43 strum::EnumIter,
44 strum::EnumString,
45 strum::VariantArray,
46 strum::VariantNames
47 ),
48 strum(serialize_all = "lowercase")
49)]
50#[repr(usize)]
51#[strum(serialize_all = "lowercase")]
52pub enum ChordFactor<T = usize> {
53 #[strum(serialize = "r", serialize = "root")]
54 Root(T) = 0,
55 #[strum(serialize = "t", serialize = "third")]
56 Third(T) = 1,
57 #[strum(serialize = "f", serialize = "fifth")]
58 Fifth(T) = 2,
59}
60
61impl Factors {
62 pub const fn root() -> Self {
64 Self::Root
65 }
66 pub const fn third() -> Self {
68 Self::Third
69 }
70 pub const fn fifth() -> Self {
72 Self::Fifth
73 }
74 pub fn factors_as_slice() -> [Self; 3] {
76 use Factors::*;
77 [Root, Third, Fifth]
78 }
79 #[cfg(feature = "alloc")]
80 pub fn others(&self) -> alloc::vec::Vec<Self> {
82 Self::iter().filter(|x| x != self).collect()
83 }
84}
85
86impl<T> ChordFactor<T> {
87 pub const fn new(data: T, factor: Factors) -> Self {
88 match factor {
89 Factors::Root => Self::Root(data),
90 Factors::Third => Self::Third(data),
91 Factors::Fifth => Self::Fifth(data),
92 }
93 }
94 pub const fn factor(&self) -> Factors {
96 match self {
97 Self::Root(_) => Factors::Root,
98 Self::Third(_) => Factors::Third,
99 Self::Fifth(_) => Factors::Fifth,
100 }
101 }
102 pub const fn fifth(data: T) -> Self {
104 Self::Fifth(data)
105 }
106 pub const fn root(data: T) -> Self {
108 Self::Root(data)
109 }
110 pub const fn third(data: T) -> Self {
112 Self::Third(data)
113 }
114 #[inline]
115 pub fn value(self) -> T {
117 match self {
118 Self::Root(inner) => inner,
119 Self::Third(inner) => inner,
120 Self::Fifth(inner) => inner,
121 }
122 }
123 pub const fn get(&self) -> &T {
125 match self {
126 Self::Root(inner) => inner,
127 Self::Third(inner) => inner,
128 Self::Fifth(inner) => inner,
129 }
130 }
131 pub const fn get_mut(&mut self) -> &mut T {
133 match self {
134 Self::Root(inner) => inner,
135 Self::Third(inner) => inner,
136 Self::Fifth(inner) => inner,
137 }
138 }
139}
140
141impl Default for Factors {
142 fn default() -> Self {
143 Factors::Root
144 }
145}
146
147macro_rules! impl_from_factor {
148 (@impl $T:ty) => {
149 impl From<$T> for Factors {
150 fn from(x: $T) -> Self {
151 use strum::EnumCount;
152 match x % Self::COUNT as $T {
153 0 => Factors::Root,
154 1 => Factors::Third,
155 2 => Factors::Fifth,
156 _ => unreachable!("Modular arithmetic error"),
157 }
158 }
159 }
160
161 impl From<Factors> for $T {
162 fn from(x: Factors) -> Self {
163 x as $T
164 }
165 }
166 };
167 ($($T:ty),* $(,)?) => {
168 $(impl_from_factor! { @impl $T })*
169 }
170}
171
172impl_from_factor! { u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize }
173
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178
179 #[test]
180 fn chord_factors() {
181
182 }
184
185 #[test]
186 fn chord_factors_iter() {
187 use Factors::*;
188
189 let factors = Factors::factors_as_slice();
190 assert_eq! { factors, [Root, Third, Fifth] }
191 }
192}