1use std::{fmt, hash::Hash};
2
3#[derive(serde::Deserialize, serde::Serialize)]
7#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)]
8pub enum Numerator {
9 Whole,
11 Half,
13 #[default]
15 Quarter,
16 N8th,
18 N16th,
20 N32nd,
22 N64th,
24 N128th,
26}
27
28impl Numerator {
29 pub const fn ord(self) -> u8 {
30 match self {
31 Numerator::Whole => 0,
32 Numerator::Half => 1,
33 Numerator::Quarter => 2,
34 Numerator::N8th => 3,
35 Numerator::N16th => 4,
36 Numerator::N32nd => 5,
37 Numerator::N64th => 6,
38 Numerator::N128th => 7,
39 }
40 }
41
42 pub const fn from_ord(ord: u8) -> Option<Numerator> {
43 match ord {
44 0 => Some(Numerator::Whole),
45 1 => Some(Numerator::Half),
46 2 => Some(Numerator::Quarter),
47 3 => Some(Numerator::N8th),
48 4 => Some(Numerator::N16th),
49 5 => Some(Numerator::N32nd),
50 6 => Some(Numerator::N64th),
51 7 => Some(Numerator::N128th),
52 _ => None,
53 }
54 }
55}
56
57#[derive(serde::Deserialize, serde::Serialize)]
62#[serde(from="SerializedDenominator")]
63#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
64pub struct Denominator(u8);
65
66impl Default for Denominator {
67 fn default() -> Self {
68 Self(2)
69 }
70}
71
72#[derive(serde::Deserialize)]
73struct SerializedDenominator(u8);
74
75impl From<SerializedDenominator> for Denominator {
76 fn from(ser: SerializedDenominator) -> Self {
77 Denominator::from_value(ser.0).unwrap_or(Denominator(2))
78 }
79}
80
81impl fmt::Display for Denominator {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 write!(f, "{}", self.0)
84 }
85}
86
87impl Denominator {
88 pub const fn value(self) -> u8 {
89 self.0
90 }
91
92 pub const fn from_value(value: u8) -> Option<Denominator> {
93 if value < 2 {
94 None
95 } else {
96 Some(Denominator(value))
97 }
98 }
99}
100
101#[derive(serde::Deserialize, serde::Serialize)]
106#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
107pub struct Dots(u8);
108
109impl Default for Dots {
110 fn default() -> Self {
111 Self::ZERO
112 }
113}
114
115impl Dots {
116 pub const ZERO: Dots = Dots(0);
117 pub const ONE: Dots = Dots(1);
118 pub const TWO: Dots = Dots(2);
119 pub const THREE: Dots = Dots(3);
120 pub const FOUR: Dots = Dots(4);
121 pub const FIVE: Dots = Dots(5);
122 pub const SIX: Dots = Dots(6);
123 pub const SEVEN: Dots = Dots(7);
124
125 pub const fn value(self) -> u8 {
126 self.0
127 }
128
129 pub const fn from_value(value: u8) -> Option<Dots> {
130 if 7 < value {
131 None
132 } else {
133 Some(Dots(value))
134 }
135 }
136}
137
138#[derive(serde::Deserialize, serde::Serialize)]
166#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Default)]
167pub struct Duration {
168 pub numerator: Numerator,
170 pub denominator: Denominator,
172 pub dots: Dots,
174}
175
176impl Duration {
177 pub const TICK_RESOLUTION: i32 = 240;
179 pub const MAX_TICK_LENGTH: i32 = Duration::TICK_RESOLUTION * 8;
181 pub const MIN_DENOMINATOR: u8 = 2;
183 pub const MAX_DENOMINATOR: u8 = 255;
185 pub const MAX_DOT: u8 = 7;
187 pub const MAX_NUMERATOR: u8 = 7;
189
190 pub fn new(numerator: Numerator, denominator: Denominator, dots: Dots) -> Duration {
198 Self { numerator, denominator, dots }
199 }
200
201 pub const fn tick_length(self) -> u32 {
207 let numerator = self.numerator.ord();
208 let len =
209 if numerator <= 2 {
210 (Duration::TICK_RESOLUTION << (2 - numerator)) as u32
211 } else {
212 (Duration::TICK_RESOLUTION >> (numerator - 2)) as u32
213 };
214
215 if self.dots.value() == 0 && self.denominator.value() == 2 {
216 len
217 } else {
218 ((len + (len - (len >> self.dots.value()))) as i64 * 2 / (self.denominator.value() as i64)) as u32
219 }
220 }
221
222 pub fn with_numerator(self, numerator: Numerator) -> Duration {
224 Self::new(numerator, self.denominator, self.dots)
225 }
226
227 pub fn with_denominator(self, denominator: Denominator) -> Duration {
229 Self::new(self.numerator, denominator, self.dots)
230 }
231
232 pub fn with_dots(self, dots: Dots) -> Duration {
234 Self::new(self.numerator, self.denominator, dots)
235 }
236
237 pub fn min(self, other: Self) -> Self {
239 if self.tick_length() < other.tick_length() { self } else { other }
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use crate::duration::Duration;
246
247 use super::{Numerator, Denominator, Dots};
248
249 #[test]
250 #[should_panic]
251 fn low_denominator() {
252 Duration::new(Numerator::Half, Denominator::from_value(1).unwrap(), Dots::ZERO);
253 }
254
255 #[test]
256 #[should_panic]
257 fn high_dot() {
258 Duration::new(Numerator::N128th, Denominator::from_value(2).unwrap(), Dots::from_value(8).unwrap());
259 }
260
261 #[test]
262 fn getter() {
263 let d = Duration::new(Numerator::Half, Denominator::from_value(2).unwrap(), Dots::from_value(3).unwrap());
264 assert_eq!(d.numerator, Numerator::Half);
265 assert_eq!(d.denominator.value(), 2);
266 assert_eq!(d.dots.value(), 3);
267 }
268
269 #[test]
270 fn tick_length() {
271 assert_eq!(Duration::new(Numerator::Quarter, Denominator::from_value(2).unwrap(), Dots::ZERO).tick_length(), 240);
272 assert_eq!(Duration::new(Numerator::Half, Denominator::from_value(2).unwrap(), Dots::ZERO).tick_length(), 480);
273 assert_eq!(Duration::new(Numerator::Quarter, Denominator::from_value(3).unwrap(), Dots::ZERO).tick_length(), 160);
274 assert_eq!(Duration::new(Numerator::Quarter, Denominator::from_value(2).unwrap(), Dots::from_value(1).unwrap()).tick_length(), 360);
275 }
276}