1use crate::{Interval, Pitch};
2use core::marker::PhantomData;
3use num_traits::{PrimInt, Zero};
4
5pub type PitchSet = Set<Pitch, u16>;
6
7pub type IntervalSet = Set<Interval, u32>;
8
9impl IntervalSet {
10 pub fn modes(self) -> impl Iterator<Item = Self> {
11 self.enumerate().map(move |(index, _)| {
12 let rotated = self.bits.rotate_right(index as _);
13 Self::new(rotated)
14 })
15 }
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
19pub struct Set<T, U> {
20 pub bits: U,
21 _marker: PhantomData<T>,
22}
23
24impl<T, U: Zero> Default for Set<T, U> {
25 fn default() -> Self {
26 Self::new(U::zero())
27 }
28}
29
30impl<T, U> Set<T, U> {
31 fn new(bits: U) -> Self {
32 Self {
33 bits,
34 _marker: PhantomData,
35 }
36 }
37}
38
39impl<T, U> Set<T, U>
40where
41 U: PrimInt,
42{
43 pub fn all() -> Self
44 where
45 U: PrimInt,
46 {
47 Self::new(U::max_value())
48 }
49
50 pub fn pop_bit(&mut self) -> Option<u8> {
52 if !self.bits.is_zero() {
53 let trailing = self.bits.trailing_zeros();
54 self.bits = self.bits & (self.bits - U::one());
55 Some(trailing as u8)
56 } else {
57 None
58 }
59 }
60}
61
62impl<T, U> Set<T, U>
63where
64 T: Into<u8>,
65 U: PrimInt,
66{
67 pub fn push(&mut self, item: T) {
68 self.bits = self.bits | (U::one() << item.into() as usize);
69 }
70
71 pub fn remove(&mut self, item: T) {
72 self.bits = self.bits | !(U::one() << item.into() as usize);
73 }
74
75 pub fn contains(&self, item: T) -> bool {
76 (self.bits >> item.into() as usize & U::one()).is_one()
77 }
78
79 pub fn split(self, item: T) -> (Self, Self) {
80 let byte = item.into() as usize;
81 (
82 Self::new(self.bits & ((U::one() << byte) - U::one())),
83 Self::new((self.bits >> byte) << byte),
84 )
85 }
86}
87
88impl<T, U> FromIterator<T> for Set<T, U>
89where
90 T: Into<u8>,
91 U: PrimInt,
92{
93 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
94 let mut set = Self::default();
95 set.extend(iter);
96 set
97 }
98}
99
100impl<T, U> Extend<T> for Set<T, U>
101where
102 T: Into<u8>,
103 U: PrimInt,
104{
105 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
106 for item in iter {
107 self.push(item);
108 }
109 }
110}
111
112impl<T, U> Iterator for Set<T, U>
113where
114 T: From<u8>,
115 U: PrimInt,
116{
117 type Item = T;
118
119 fn next(&mut self) -> Option<Self::Item> {
120 self.pop_bit().map(Into::into)
121 }
122}