enum_set2/
lib.rs

1#![deny(missing_docs)]
2//! A set for enum variants
3//!
4//! It is implemented as a wrapper over the `bit-set` crate,
5//! which provides a set for integers values. We use the `EnumLike` trait
6//! from the `enum_like` crate which allows for a conversion between enum
7//! variant and integer value.
8//!
9//! Since an `EnumSet` is a wrapper over a `BitSet`, and a `BitSet` is
10//! a wrapper over a `BitVec`, looking at the assembly generated by this crate
11//! should be interesting.
12extern crate enum_like;
13extern crate bit_set;
14
15use enum_like::EnumLike;
16use bit_set::BitSet;
17use std::marker::PhantomData;
18use std::iter::FromIterator;
19use std::fmt;
20
21/// A `BitSet` indexed by an `EnumLike` type.
22#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
23pub struct EnumSet<E: EnumLike> {
24    inner: BitSet,
25    _phantom: PhantomData<E>,
26}
27
28impl<E: EnumLike> EnumSet<E> {
29    /// Returns the inner `BitSet`.
30    pub fn into_bit_set(self) -> BitSet {
31        self.inner
32    }
33
34    /// Returns a reference to the inner `BitSet`.
35    pub fn get_ref(&self) -> &BitSet {
36        &self.inner
37    }
38
39    /// Constructs an `EnumSet` from a `BitSet`.
40    pub fn from_bit_set(inner: BitSet) -> Self {
41        Self {
42            inner,
43            _phantom: PhantomData,
44        }
45    }
46
47    /// Creates a new `EnumSet`.
48    pub fn new() -> Self {
49        Self {
50            //inner: BitSet::with_capacity(E::NUM_VARIANTS),
51            inner: BitSet::new(),
52            _phantom: PhantomData,
53        }
54    }
55
56    /// Attemps to minimalize the memory usage of the inner `BitSet`.
57    pub fn shrink_to_fit(&mut self) {
58        self.inner.shrink_to_fit()
59    }
60
61    /// Iterator over each element in the set.
62    pub fn iter(&self) -> WrapIter<E, bit_set::Iter<'_, u32>> {
63        WrapIter::<E, _>::new(self.inner.iter())
64    }
65
66    /*
67    // Alternative not using WrapIter
68    /// Iterator over each element in the set
69    pub fn iter<'a>(&'a self) -> impl Iterator<Item=E> + 'a {
70        self.inner.iter().map(|x| E::from_discr(x))
71    }
72    */
73
74    /// Iterator over each element in `set || other`.
75    pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, E> {
76        WrapIter::<E, _>::new(self.inner.union(&other.inner))
77    }
78
79    /// Iterator over each element in `set && other`.
80    pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, E> {
81        WrapIter::<E, _>::new(self.inner.intersection(&other.inner))
82    }
83
84    /// Iterator over each element in `set - other`.
85    pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, E> {
86        WrapIter::<E, _>::new(self.inner.difference(&other.inner))
87    }
88
89    /// Iterator over each element in `set ^ other`.
90    pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, E> {
91        WrapIter::<E, _>::new(self.inner.symmetric_difference(&other.inner))
92    }
93
94    /// Computes the union with the other set, in-place.
95    pub fn union_with(&mut self, other: &Self) {
96        self.inner.union_with(&other.inner)
97    }
98
99    /// Computes the intersection with the other set, in-place.
100    pub fn intersect_with(&mut self, other: &Self) {
101        self.inner.intersect_with(&other.inner)
102    }
103
104    /// Computes the difference with the other set, in-place.
105    pub fn difference_with(&mut self, other: &Self) {
106        self.inner.difference_with(&other.inner)
107    }
108
109    /// Computes the symmetric difference with the other set, in-place.
110    pub fn symmetric_difference_with(&mut self, other: &Self) {
111        self.inner.symmetric_difference_with(&other.inner)
112    }
113
114    /// Returns the number of elements in the set.
115    pub fn len(&self) -> usize {
116        self.inner.len()
117    }
118
119    /// Returns `true` if there are no elements in the set.
120    pub fn is_empty(&self) -> bool {
121        self.inner.is_empty()
122    }
123
124    /// Clears all elements in the set.
125    pub fn clear(&mut self) {
126        self.inner.clear()
127    }
128
129    /// Returns `true` if the set contains this value.
130    pub fn contains(&self, value: E) -> bool {
131        let d = value.to_discr();
132        self.inner.contains(d)
133    }
134
135    /// Returns `true` if the set has no elements in common with `other`.
136    pub fn is_disjoint(&self, other: &Self) -> bool {
137        self.inner.is_disjoint(&other.inner)
138    }
139
140    /// Returns `true` if the set has no elements in common with `other`.
141    pub fn is_subset(&self, other: &Self) -> bool {
142        self.inner.is_subset(&other.inner)
143    }
144
145    /// Returns `true` if the set has no elements in common with `other`.
146    pub fn is_superset(&self, other: &Self) -> bool {
147        self.inner.is_superset(&other.inner)
148    }
149
150    /// Returns `true` if the value was not already present in the set
151    pub fn insert(&mut self, value: E) -> bool {
152        let d = value.to_discr();
153        self.inner.insert(d)
154    }
155
156    /// Returns `true` if the value was already present in the set
157    pub fn remove(&mut self, value: E) -> bool {
158        let d = value.to_discr();
159        self.inner.remove(d)
160    }
161}
162
163impl<E: EnumLike> Default for EnumSet<E> {
164    fn default() -> Self {
165        Self::new()
166    }
167}
168
169impl<E: EnumLike> FromIterator<E> for EnumSet<E> {
170    fn from_iter<I: IntoIterator<Item = E>>(iter: I) -> Self {
171        let mut ret = Self::default();
172        ret.extend(iter);
173        ret
174    }
175}
176
177impl<E: EnumLike> Extend<E> for EnumSet<E> {
178    fn extend<I: IntoIterator<Item = E>>(&mut self, iter: I) {
179        for i in iter {
180            self.insert(i);
181        }
182    }
183}
184
185impl<E: EnumLike + fmt::Debug> fmt::Debug for EnumSet<E> {
186    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187        f.debug_set().entries(self.iter()).finish()
188    }
189}
190
191// Iterators
192
193/// Wraps an iterator from the `bit-set` crate, mapping the output from
194/// `usize` to `E: EnumLike`.
195#[derive(Debug)]
196pub struct WrapIter<E: EnumLike, I: Iterator<Item=usize>> {
197    inner: I,
198    _phantom: PhantomData<E>,
199}
200
201/// Iterator over the `&EnumSet`
202pub type Iter<'a, E> = WrapIter<E, bit_set::Iter<'a, u32>>;
203/// Iterator over the `&EnumSet`
204pub type Union<'a, E> = WrapIter<E, bit_set::Union<'a, u32>>;
205/// Iterator over the `&EnumSet`
206pub type Intersection<'a, E> = WrapIter<E, bit_set::Intersection<'a, u32>>;
207/// Iterator over the `&EnumSet`
208pub type Difference<'a, E> = WrapIter<E, bit_set::Difference<'a, u32>>;
209/// Iterator over the `&EnumSet`
210pub type SymmetricDifference<'a, E> = WrapIter<E, bit_set::SymmetricDifference<'a, u32>>;
211
212impl<E: EnumLike, I: Iterator<Item=usize>> WrapIter<E, I> {
213    fn new(inner: I) -> Self {
214        Self { inner, _phantom: PhantomData }
215    }
216}
217
218impl<E: EnumLike, I: Iterator<Item=usize>> Iterator for WrapIter<E, I> {
219    type Item = E;
220    fn next(&mut self) -> Option<E> {
221        self.inner.next().map(|x| E::from_discr(x))
222    }
223    fn size_hint(&self) -> (usize, Option<usize>) {
224        self.inner.size_hint()
225    }
226}
227
228impl<'a, E: EnumLike> IntoIterator for &'a EnumSet<E> {
229    type Item = E;
230    type IntoIter = WrapIter<E, bit_set::Iter<'a, u32>>;
231
232    fn into_iter(self) -> Self::IntoIter {
233        self.iter()
234    }
235}
236
237
238/*
239/// Make all the other methods of `BitVec` available without having to
240/// rewrite them.
241/// Now that I think about it, this may be a bad idea.
242impl<E: EnumLike> Deref for EnumSet<E> {
243    type Target = BitSet;
244    fn deref(&self) -> &Self::Target {
245        &self.inner
246    }
247}
248
249impl<E: EnumLike> DerefMut for EnumSet<E> {
250    fn deref_mut(&mut self) -> &mut Self::Target {
251        &mut self.inner
252    }
253}
254*/
255
256#[cfg(test)]
257mod tests {
258    use super::*;
259
260    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
261    enum ABC {
262        A,
263        B,
264        C,
265    }
266
267    unsafe impl EnumLike for ABC {
268        const NUM_VARIANTS: usize = 3;
269        fn to_discr(self) -> usize {
270            //self as usize
271            // ^this may not work if the enum has variants with values, like A = 100:
272            // so instead, we do the long form:
273            match self {
274                ABC::A => 0,
275                ABC::B => 1,
276                ABC::C => 2,
277            }
278        }
279        fn from_discr(x: usize) -> Self {
280            match x {
281                0 => ABC::A,
282                1 => ABC::B,
283                2 => ABC::C,
284                _ => panic!("Enum ABC has no variant {}", x),
285            }
286        }
287    }
288
289    #[test]
290    fn create() {
291        let mut e = EnumSet::new();
292        assert_eq!(e.contains(ABC::A), false);
293        assert_eq!(e.insert(ABC::A), true);
294        assert_eq!(e.insert(ABC::A), false);
295        assert_eq!(e.contains(ABC::A), true);
296        assert_eq!(e.remove(ABC::A), true);
297        assert_eq!(e.remove(ABC::A), false);
298        assert_eq!(e.contains(ABC::A), false);
299    }
300
301    // As for now, this crate is assumed to work because of its simplicity.
302}