music_note/midi/
midi_set.rs

1use super::MidiNote;
2use crate::set::Set;
3
4#[derive(Clone, Debug, Default, PartialEq, Eq)]
5pub struct MidiSet {
6    low: Set<MidiNote, u64>,
7    high: Set<MidiNote, u64>,
8}
9
10impl MidiSet {
11    pub fn contains(&mut self, midi: MidiNote) -> bool {
12        with_midi(self.low, self.high, midi, |set, midi| set.contains(midi))
13    }
14
15    pub fn push(&mut self, midi: MidiNote) {
16        self.inner(midi, |set, midi| set.push(midi))
17    }
18
19    pub fn remove(&mut self, midi: MidiNote) {
20        self.inner(midi, |set, midi| set.remove(midi))
21    }
22
23    fn inner<F, T>(&mut self, midi: MidiNote, f: F) -> T
24    where
25        F: FnOnce(&mut Set<MidiNote, u64>, MidiNote) -> T,
26    {
27        with_midi(&mut self.low, &mut self.high, midi, f)
28    }
29}
30
31fn with_midi<T, U, F>(low: T, high: T, midi: MidiNote, f: F) -> U
32where
33    F: FnOnce(T, MidiNote) -> U,
34{
35    if midi <= MidiNote::from_byte(63) {
36        f(low, midi)
37    } else {
38        let byte = midi.into_byte() - 63;
39        f(high, MidiNote::from(byte))
40    }
41}
42
43impl FromIterator<MidiNote> for MidiSet {
44    fn from_iter<T: IntoIterator<Item = MidiNote>>(iter: T) -> Self {
45        let mut set = Self::default();
46        set.extend(iter);
47        set
48    }
49}
50
51impl Extend<MidiNote> for MidiSet {
52    fn extend<T: IntoIterator<Item = MidiNote>>(&mut self, iter: T) {
53        for midi in iter {
54            self.push(midi);
55        }
56    }
57}
58
59impl Iterator for MidiSet {
60    type Item = MidiNote;
61
62    fn next(&mut self) -> Option<Self::Item> {
63        self.low.next().or_else(|| {
64            self.high
65                .next()
66                .map(|midi| MidiNote::from(midi.into_byte() + 63))
67        })
68    }
69}