1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! A structure for holding a set of enum variants
13 //! This module defines a container which uses an efficient bit mask
14 //! representation to hold C-like enum variants.
16 #[deriving(Clone, Eq, IterBytes, ToStr, Encodable, Decodable)]
17 /// A specialized Set implementation to use enum types.
18 pub struct EnumSet<E> {
19 // We must maintain the invariant that no bits are set
20 // for which no variant exists
24 /// An interface for casting C-like enum to uint and back.
26 /// Converts C-like enum to uint.
27 fn to_uint(&self) -> uint;
28 /// Converts uint to C-like enum.
29 fn from_uint(uint) -> Self;
32 fn bit<E:CLike>(e: E) -> uint {
36 impl<E:CLike> EnumSet<E> {
37 /// Returns an empty EnumSet.
38 pub fn empty() -> EnumSet<E> {
42 /// Returns true if an EnumSet is empty.
43 pub fn is_empty(&self) -> bool {
47 /// Returns true if an EnumSet contains any enum of a given EnumSet
48 pub fn intersects(&self, e: EnumSet<E>) -> bool {
49 (self.bits & e.bits) != 0
52 /// Returns an intersection of both EnumSets.
53 pub fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
54 EnumSet {bits: self.bits & e.bits}
57 /// Returns true if a given EnumSet is included in an EnumSet.
58 pub fn contains(&self, e: EnumSet<E>) -> bool {
59 (self.bits & e.bits) == e.bits
62 /// Returns a union of both EnumSets.
63 pub fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
64 EnumSet {bits: self.bits | e.bits}
67 /// Add an enum to an EnumSet
68 pub fn add(&mut self, e: E) {
72 /// Returns true if an EnumSet contains a given enum
73 pub fn contains_elem(&self, e: E) -> bool {
74 (self.bits & bit(e)) != 0
77 /// Returns an iterator over an EnumSet
78 pub fn iter(&self) -> EnumSetIterator<E> {
79 EnumSetIterator::new(self.bits)
83 impl<E:CLike> Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
84 fn sub(&self, e: &EnumSet<E>) -> EnumSet<E> {
85 EnumSet {bits: self.bits & !e.bits}
89 impl<E:CLike> BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
90 fn bitor(&self, e: &EnumSet<E>) -> EnumSet<E> {
91 EnumSet {bits: self.bits | e.bits}
95 impl<E:CLike> BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
96 fn bitand(&self, e: &EnumSet<E>) -> EnumSet<E> {
97 EnumSet {bits: self.bits & e.bits}
101 /// An iterator over an EnumSet
102 pub struct EnumSetIterator<E> {
107 impl<E:CLike> EnumSetIterator<E> {
108 fn new(bits: uint) -> EnumSetIterator<E> {
109 EnumSetIterator { index: 0, bits: bits }
113 impl<E:CLike> Iterator<E> for EnumSetIterator<E> {
114 fn next(&mut self) -> Option<E> {
115 if (self.bits == 0) {
119 while (self.bits & 1) == 0 {
123 let elem = CLike::from_uint(self.index);
129 fn size_hint(&self) -> (uint, Option<uint>) {
130 let exact = self.bits.population_count();
149 fn to_uint(&self) -> uint {
153 fn from_uint(v: uint) -> Foo {
154 unsafe { cast::transmute(v) }
160 let e: EnumSet<Foo> = EnumSet::empty();
161 assert!(e.is_empty());
164 ///////////////////////////////////////////////////////////////////////////
168 fn test_two_empties_do_not_intersect() {
169 let e1: EnumSet<Foo> = EnumSet::empty();
170 let e2: EnumSet<Foo> = EnumSet::empty();
171 assert!(!e1.intersects(e2));
175 fn test_empty_does_not_intersect_with_full() {
176 let e1: EnumSet<Foo> = EnumSet::empty();
178 let mut e2: EnumSet<Foo> = EnumSet::empty();
183 assert!(!e1.intersects(e2));
187 fn test_disjoint_intersects() {
188 let mut e1: EnumSet<Foo> = EnumSet::empty();
191 let mut e2: EnumSet<Foo> = EnumSet::empty();
194 assert!(!e1.intersects(e2));
198 fn test_overlapping_intersects() {
199 let mut e1: EnumSet<Foo> = EnumSet::empty();
202 let mut e2: EnumSet<Foo> = EnumSet::empty();
206 assert!(e1.intersects(e2));
209 ///////////////////////////////////////////////////////////////////////////
210 // contains and contains_elem
214 let mut e1: EnumSet<Foo> = EnumSet::empty();
217 let mut e2: EnumSet<Foo> = EnumSet::empty();
221 assert!(!e1.contains(e2));
222 assert!(e2.contains(e1));
226 fn test_contains_elem() {
227 let mut e1: EnumSet<Foo> = EnumSet::empty();
229 assert!(e1.contains_elem(A));
230 assert!(!e1.contains_elem(B));
231 assert!(!e1.contains_elem(C));
235 assert!(e1.contains_elem(A));
236 assert!(e1.contains_elem(B));
237 assert!(!e1.contains_elem(C));
240 ///////////////////////////////////////////////////////////////////////////
245 let mut e1: EnumSet<Foo> = EnumSet::empty();
247 let elems: ~[Foo] = e1.iter().collect();
248 assert_eq!(~[], elems)
251 let elems: ~[Foo] = e1.iter().collect();
252 assert_eq!(~[A], elems)
255 let elems: ~[Foo] = e1.iter().collect();
256 assert_eq!(~[A,C], elems)
259 let elems: ~[Foo] = e1.iter().collect();
260 assert_eq!(~[A,C], elems)
263 let elems: ~[Foo] = e1.iter().collect();
264 assert_eq!(~[A,B,C], elems)
267 ///////////////////////////////////////////////////////////////////////////
271 fn test_operators() {
272 let mut e1: EnumSet<Foo> = EnumSet::empty();
276 let mut e2: EnumSet<Foo> = EnumSet::empty();
280 let e_union = e1 | e2;
281 let elems: ~[Foo] = e_union.iter().collect();
282 assert_eq!(~[A,B,C], elems)
284 let e_intersection = e1 & e2;
285 let elems: ~[Foo] = e_intersection.iter().collect();
286 assert_eq!(~[C], elems)
288 let e_subtract = e1 - e2;
289 let elems: ~[Foo] = e_subtract.iter().collect();
290 assert_eq!(~[A], elems)