euphony_core/time/
compound.rs

1use crate::time::{beat::Beat, measure::Measure, time_signature::TimeSignature};
2use core::ops::{Add, AddAssign, Mul, Sub, SubAssign};
3
4#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
5pub struct CompoundDuration {
6    pub measure: Measure,
7    pub beat: Beat,
8}
9
10macro_rules! compound_conversion {
11    ($ty:ident, $field:ident, $other_ty:ident, $other_field:ident) => {
12        impl From<$ty> for CompoundDuration {
13            fn from($field: $ty) -> Self {
14                Self {
15                    $other_field: Default::default(),
16                    $field,
17                }
18            }
19        }
20
21        impl Add<$ty> for CompoundDuration {
22            type Output = CompoundDuration;
23
24            fn add(self, $field: $ty) -> Self::Output {
25                CompoundDuration {
26                    $field: self.$field + $field,
27                    $other_field: self.$other_field,
28                }
29            }
30        }
31
32        impl AddAssign<$ty> for CompoundDuration {
33            fn add_assign(&mut self, $field: $ty) {
34                self.$field += $field;
35            }
36        }
37
38        impl Sub<$ty> for CompoundDuration {
39            type Output = CompoundDuration;
40
41            fn sub(self, $field: $ty) -> Self::Output {
42                CompoundDuration {
43                    $field: self.$field - $field,
44                    $other_field: self.$other_field,
45                }
46            }
47        }
48
49        impl SubAssign<$ty> for CompoundDuration {
50            fn sub_assign(&mut self, $field: $ty) {
51                self.$field -= $field;
52            }
53        }
54
55        impl Add<$ty> for $other_ty {
56            type Output = CompoundDuration;
57
58            fn add(self, value: $ty) -> Self::Output {
59                let compound: CompoundDuration = self.into();
60                compound + value
61            }
62        }
63
64        impl Sub<$ty> for $other_ty {
65            type Output = CompoundDuration;
66
67            fn sub(self, value: $ty) -> Self::Output {
68                let compound: CompoundDuration = self.into();
69                compound - value
70            }
71        }
72    };
73}
74
75compound_conversion!(Beat, beat, Measure, measure);
76compound_conversion!(Measure, measure, Beat, beat);
77
78impl Mul<TimeSignature> for CompoundDuration {
79    type Output = Beat;
80
81    fn mul(self, time_signature: TimeSignature) -> Self::Output {
82        self.beat * time_signature + self.measure * time_signature
83    }
84}