bms_rs/bms/command/
time.rs1use num::Integer;
4use std::num::NonZeroU64;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct Track(pub u64);
10
11impl std::fmt::Display for Track {
12 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13 write!(f, "Track: {:03}", self.0)
14 }
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub struct ObjTime {
21 track: Track,
23 numerator: u64,
25 denominator: NonZeroU64,
27}
28
29impl ObjTime {
30 #[must_use]
32 pub fn new(track: u64, numerator: u64, denominator: NonZeroU64) -> Self {
33 let (track, numerator) = if numerator > denominator.get() {
35 (
36 track + (numerator / denominator.get()),
37 numerator % denominator.get(),
38 )
39 } else {
40 (track, numerator)
41 };
42 let gcd = numerator.gcd(&denominator.get());
45 Self {
46 track: Track(track),
47 numerator: numerator / gcd,
48 denominator: NonZeroU64::new(denominator.get() / gcd)
49 .expect("GCD should never make denominator zero"),
50 }
51 }
52
53 #[must_use]
55 pub const fn track(&self) -> Track {
56 self.track
57 }
58
59 #[must_use]
61 pub const fn numerator(&self) -> u64 {
62 self.numerator
63 }
64
65 #[must_use]
67 pub const fn denominator(&self) -> NonZeroU64 {
68 self.denominator
69 }
70
71 #[must_use]
73 pub const fn denominator_u64(&self) -> u64 {
74 self.denominator.get()
75 }
76}
77
78impl PartialOrd for ObjTime {
79 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
80 Some(self.cmp(other))
81 }
82}
83
84impl Ord for ObjTime {
85 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
86 let self_time_in_track = self.numerator() * other.denominator().get();
87 let other_time_in_track = other.numerator() * self.denominator().get();
88 self.track()
89 .cmp(&other.track())
90 .then(self_time_in_track.cmp(&other_time_in_track))
91 }
92}
93
94impl std::fmt::Display for ObjTime {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 write!(
97 f,
98 "ObjTime: {}, {} / {}",
99 self.track(),
100 self.numerator(),
101 self.denominator().get()
102 )
103 }
104}