1use std::{fmt::{self, Display}, str::FromStr};
2
3use super::duration::Duration;
4
5pub const MIN_NUMERATOR: u8 = 1;
7pub const MAX_NUMERATOR: u8 = 99;
9
10#[derive(serde::Deserialize, serde::Serialize)]
14#[derive(Debug, Copy, Clone, PartialEq, Eq)]
15pub struct Numerator(u8);
16
17impl Display for Numerator {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 write!(f, "{}", self.0)
20 }
21}
22
23#[derive(Debug)]
25pub enum NumeratorError {
26 InvalidValue(u8),
28 CannotParse(String),
30}
31
32impl Numerator {
33 pub fn from_value(value: u8) -> Result<Numerator, NumeratorError> {
34 if !(MIN_NUMERATOR..=MAX_NUMERATOR).contains(&value) {
35 Err(NumeratorError::InvalidValue(value))
36 } else {
37 Ok(Numerator(value))
38 }
39 }
40
41 pub fn value(self) -> u8 {
42 self.0
43 }
44}
45
46impl FromStr for Numerator {
47 type Err = NumeratorError;
48
49 fn from_str(s: &str) -> Result<Self, Self::Err> {
50 match u8::from_str(s) {
51 Ok(value) => Self::from_value(value),
52 Err(_) => Err(NumeratorError::CannotParse(s.to_owned())),
53 }
54 }
55}
56
57#[derive(Clone, Copy, Debug, PartialEq, Eq)]
62#[derive(serde::Deserialize, serde::Serialize)]
63pub enum Denominator {
64 D2,
66 D4,
68 D8,
70 D16,
72 D32,
74 D64,
76}
77
78pub const DENOMINATORS: [Denominator; 6] = [
80 Denominator::D2, Denominator::D4, Denominator::D8,
81 Denominator::D16, Denominator::D32, Denominator::D64,
82];
83
84pub enum DenominatorError {
86 InvalidValue(u8),
88}
89
90impl Denominator {
91 pub fn from_value(value: u8) -> Result<Denominator, DenominatorError> {
92 match value {
93 2 => Ok(Denominator::D2),
94 4 => Ok(Denominator::D4),
95 8 => Ok(Denominator::D8),
96 16 => Ok(Denominator::D16),
97 32 => Ok(Denominator::D32),
98 64 => Ok(Denominator::D64),
99 _ => Err(DenominatorError::InvalidValue(value)),
100 }
101 }
102
103 pub fn value(self) -> u8 {
104 match self {
105 Denominator::D2 => 2,
106 Denominator::D4 => 4,
107 Denominator::D8 => 8,
108 Denominator::D16 => 16,
109 Denominator::D32 => 32,
110 Denominator::D64 => 64,
111 }
112 }
113}
114
115impl fmt::Display for Denominator {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 write!(f, "{}", self.value())
118 }
119}
120
121#[derive(serde::Deserialize, serde::Serialize)]
123#[derive(Debug, Copy, Clone, PartialEq)]
124pub enum RhythmError {
125 NumeratorError(u8),
127 DenominatorError(u8)
129}
130
131#[derive(serde::Deserialize, serde::Serialize)]
144#[derive(Debug, Copy, Clone, PartialEq, Eq)]
145pub struct Rhythm {
146 pub numerator: Numerator,
148 pub denominator: Denominator,
150}
151
152impl Rhythm {
153 pub fn new(numerator: u8, denominator: u8) -> Rhythm {
172 match Self::value_of(numerator, denominator) {
173 Err(_pe) => panic!("Logic error."),
174 Ok(r) => r
175 }
176 }
177
178 pub fn numerator(self) -> Numerator {
180 self.numerator
181 }
182
183 pub fn denominator(self) -> Denominator {
185 self.denominator
186 }
187
188 pub fn value_of(numerator: u8, denominator: u8) -> Result<Rhythm, RhythmError> {
200 let numerator = Numerator::from_value(numerator);
201 let numerator = match numerator {
202 Err(NumeratorError::InvalidValue(v)) => return Err(RhythmError::NumeratorError(v)),
203 Err(_) => panic!("Logic error."),
204 Ok(n) => n,
205 };
206
207 let denominator = Denominator::from_value(denominator);
208 let denominator = match denominator {
209 Err(DenominatorError::InvalidValue(v)) => return Err(RhythmError::DenominatorError(v)),
210 Ok(d) => d,
211 };
212
213 Ok(Self {numerator, denominator})
214 }
215
216 pub fn tick_len(self) -> u32 {
222 ((self.numerator.0 as i32) * Duration::TICK_RESOLUTION * 4 / (self.denominator.value() as i32)) as u32
223 }
224}
225
226impl Default for Rhythm {
227 fn default() -> Self {
228 Self::new(4, 4)
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use serde_json::Value;
235 use serde_json::json;
236
237 use super::Rhythm;
238 use super::RhythmError;
239
240 #[test]
241 #[should_panic]
242 fn new_with_invalid_denominator() {
243 Rhythm::new(1, 3);
244 }
245
246 #[test]
247 #[should_panic]
248 fn new_with_invalid_numerator() {
249 Rhythm::new(100, 4);
250 }
251
252 #[test]
253 fn value_of_with_invalid_denominator() {
254 assert_eq!(Rhythm::value_of(1, 3).err().unwrap(), RhythmError::DenominatorError(3))
255 }
256
257 #[test]
258 fn value_of_with_invalid_numerator() {
259 assert_eq!(Rhythm::value_of(100, 2).err().unwrap(), RhythmError::NumeratorError(100))
260 }
261
262 #[test]
263 fn value_of() {
264 assert_eq!(Rhythm::value_of(2, 4).ok().unwrap(), Rhythm::new(2, 4))
265 }
266
267 #[test]
268 fn tick_len() {
269 assert_eq!(Rhythm::value_of(4, 4).ok().unwrap().tick_len(), 240 * 4);
270 assert_eq!(Rhythm::value_of(2, 4).ok().unwrap().tick_len(), 240 * 2);
271 assert_eq!(Rhythm::value_of(2, 2).ok().unwrap().tick_len(), 480 * 2);
272 assert_eq!(Rhythm::value_of(6, 8).ok().unwrap().tick_len(), 120 * 6);
273 }
274
275 #[test]
276 fn can_serialize_to_json() {
277 let json_str = serde_json::to_string(&Rhythm::new(3, 4)).unwrap();
278 let json: Value = serde_json::from_str(&json_str).unwrap();
279 assert_eq!(
280 json,
281 json!({
282 "numerator": 3,
283 "denominator": "D4"
284 })
285 );
286 }
287
288 #[test]
289 fn can_deserialize_from_json() {
290 let rhythm: Rhythm = serde_json::from_str(r#"
291 {
292 "numerator": 3,
293 "denominator": "D4"
294 }
295 "#).unwrap();
296 assert_eq!(rhythm, Rhythm::new(3, 4));
297 }
298}