midi_toolkit/
num.rs

1use std::{
2    fmt::Display,
3    ops::{AddAssign, DivAssign, MulAssign, SubAssign},
4};
5
6use num_traits::Num;
7use std::fmt::Debug;
8
9pub trait MIDINumInto<T: MIDINum> {
10    /// Casts the midi time type to another supported type.
11    ///
12    /// By default, supports: i32, i64, u32, u64, f32, f64
13    /// ## Example
14    /// ```
15    ///use midi_toolkit::num::{MIDINumInto};
16    ///
17    ///let dt_i32: i32 = 10;
18    ///let dt_u64: u64 = 10;
19    ///
20    ///let dt_f32: f32 = dt_i32.midi_num_into();
21    ///let dt_f64: f64 = dt_i32.midi_num_into();
22    ///let dt_u32: u32 = dt_u64.midi_num_into();
23    ///let dt_i64: i64 = dt_u64.midi_num_into();
24    ///
25    ///assert_eq!(dt_f32, 10f32);
26    ///assert_eq!(dt_f64, 10f64);
27    ///assert_eq!(dt_u32, 10u32);
28    ///assert_eq!(dt_i64, 10i64);
29    /// ```
30    fn midi_num_into(&self) -> T;
31}
32
33pub trait MIDINumFrom<T: MIDINum> {
34    /// Casts the midi time type to another supported type.
35    ///
36    /// By default, supports: i32, i64, u32, u64, f32, f64
37    /// ## Example
38    /// ```
39    ///use midi_toolkit::num::{MIDINumInto};
40    ///
41    ///let dt_i32: i32 = 10;
42    ///let dt_u64: u64 = 10;
43    ///
44    ///let dt_f32: f32 = dt_i32.midi_num_into();
45    ///let dt_f64: f64 = dt_i32.midi_num_into();
46    ///let dt_u32: u32 = dt_u64.midi_num_into();
47    ///let dt_i64: i64 = dt_u64.midi_num_into();
48    ///
49    ///assert_eq!(dt_f32, 10f32);
50    ///assert_eq!(dt_f64, 10f64);
51    ///assert_eq!(dt_u32, 10u32);
52    ///assert_eq!(dt_i64, 10i64);
53    /// ```
54    fn midi_num_from(val: T) -> Self;
55}
56
57pub trait MIDINum:
58    Num
59    + PartialOrd
60    + PartialEq
61    + AddAssign
62    + SubAssign
63    + DivAssign
64    + MulAssign
65    + Copy
66    + Sized
67    + Debug
68    + Display
69    + Send
70    + Sync
71    + MIDINumFrom<i32>
72    + MIDINumFrom<f32>
73    + MIDINumFrom<f64>
74    + MIDINumFrom<i64>
75    + MIDINumFrom<u32>
76    + MIDINumFrom<u64>
77    + MIDINumInto<i32>
78    + MIDINumInto<f32>
79    + MIDINumInto<f64>
80    + MIDINumInto<i64>
81    + MIDINumInto<u32>
82    + MIDINumInto<u64>
83{
84    fn saturating_add(self, other: Self) -> Self;
85    fn saturating_sub(self, other: Self) -> Self;
86}
87
88macro_rules! impl_delta_from_to {
89    ($from:ident, $to:ident) => {
90        impl MIDINumInto<$to> for $from {
91            fn midi_num_into(&self) -> $to {
92                *self as $to
93            }
94        }
95
96        impl MIDINumFrom<$to> for $from {
97            fn midi_num_from(val: $to) -> Self {
98                val as $from
99            }
100        }
101    };
102}
103
104macro_rules! impl_delta_from {
105    ($from:ident) => {
106        impl_delta_from_to!($from, i32);
107        impl_delta_from_to!($from, u32);
108        impl_delta_from_to!($from, i64);
109        impl_delta_from_to!($from, u64);
110        impl_delta_from_to!($from, f32);
111        impl_delta_from_to!($from, f64);
112    };
113}
114
115impl_delta_from!(i32);
116impl_delta_from!(u32);
117impl_delta_from!(i64);
118impl_delta_from!(u64);
119impl_delta_from!(f32);
120impl_delta_from!(f64);
121
122macro_rules! impl_midi_num_for_int {
123    ($int:ident) => {
124        impl MIDINum for $int {
125            fn saturating_add(self, other: Self) -> Self {
126                self.saturating_add(other)
127            }
128
129            fn saturating_sub(self, other: Self) -> Self {
130                self.saturating_sub(other)
131            }
132        }
133    };
134}
135
136macro_rules! impl_midi_num_for_float {
137    ($int:ident) => {
138        impl MIDINum for $int {
139            fn saturating_add(self, other: Self) -> Self {
140                self + other
141            }
142
143            fn saturating_sub(self, other: Self) -> Self {
144                self - other
145            }
146        }
147    };
148}
149
150impl_midi_num_for_int!(i32);
151impl_midi_num_for_int!(u32);
152impl_midi_num_for_int!(i64);
153impl_midi_num_for_int!(u64);
154impl_midi_num_for_float!(f32);
155impl_midi_num_for_float!(f64);
156
157#[cfg(test)]
158mod tests {
159    use crate::num::{MIDINumFrom, MIDINumInto};
160    #[test]
161    fn casts_delta_into() {
162        let dt_i32: i32 = 10;
163        let dt_u64: u64 = 10;
164
165        let dt_f32: f32 = dt_i32.midi_num_into();
166        let dt_f64: f64 = dt_i32.midi_num_into();
167        let dt_u32: u32 = dt_u64.midi_num_into();
168        let dt_i64: i64 = dt_u64.midi_num_into();
169
170        assert_eq!(dt_f32, 10f32);
171        assert_eq!(dt_f64, 10f64);
172        assert_eq!(dt_u32, 10u32);
173        assert_eq!(dt_i64, 10i64);
174    }
175
176    #[test]
177    fn casts_delta_from() {
178        let dt_i32: i32 = 10;
179        let dt_u64: u64 = 10;
180
181        let dt_f32 = f32::midi_num_from(dt_i32);
182        let dt_f64 = f64::midi_num_from(dt_i32);
183        let dt_u32 = u32::midi_num_from(dt_u64);
184        let dt_i64 = i64::midi_num_from(dt_u64);
185
186        assert_eq!(dt_f32, 10f32);
187        assert_eq!(dt_f64, 10f64);
188        assert_eq!(dt_u32, 10u32);
189        assert_eq!(dt_i64, 10i64);
190    }
191}