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.
19 use core::iter::FromIterator;
20 use core::ops::{Sub, BitOr, BitAnd, BitXor};
22 // FIXME(contentions): implement union family of methods? (general design may be wrong here)
24 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
25 /// A specialized set implementation to use enum types.
26 pub struct EnumSet<E> {
27 // We must maintain the invariant that no bits are set
28 // for which no variant exists
32 impl<E> Copy for EnumSet<E> {}
34 impl<E:CLike+fmt::Show> fmt::Show for EnumSet<E> {
35 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
36 try!(write!(fmt, "{{"));
38 for e in self.iter() {
40 try!(write!(fmt, ", "));
42 try!(write!(fmt, "{}", e));
49 /// An interface for casting C-like enum to uint and back.
50 /// A typically implementation is as below.
58 /// impl CLike for Foo {
59 /// fn to_uint(&self) -> uint {
63 /// fn from_uint(v: uint) -> Foo {
64 /// unsafe { mem::transmute(v) }
69 /// Converts a C-like enum to a `uint`.
70 fn to_uint(&self) -> uint;
71 /// Converts a `uint` to a C-like enum.
72 fn from_uint(uint) -> Self;
75 fn bit<E:CLike>(e: &E) -> uint {
77 let value = e.to_uint();
78 assert!(value < uint::BITS,
79 "EnumSet only supports up to {} variants.", uint::BITS - 1);
83 impl<E:CLike> EnumSet<E> {
84 /// Returns an empty `EnumSet`.
85 #[unstable = "matches collection reform specification, waiting for dust to settle"]
86 pub fn new() -> EnumSet<E> {
90 /// Returns the number of elements in the given `EnumSet`.
91 #[unstable = "matches collection reform specification, waiting for dust to settle"]
92 pub fn len(&self) -> uint {
93 self.bits.count_ones()
96 /// Returns true if the `EnumSet` is empty.
97 #[unstable = "matches collection reform specification, waiting for dust to settle"]
98 pub fn is_empty(&self) -> bool {
102 pub fn clear(&mut self) {
106 /// Returns `false` if the `EnumSet` contains any enum of the given `EnumSet`.
107 #[unstable = "matches collection reform specification, waiting for dust to settle"]
108 pub fn is_disjoint(&self, other: &EnumSet<E>) -> bool {
109 (self.bits & other.bits) == 0
112 /// Returns `true` if a given `EnumSet` is included in this `EnumSet`.
113 #[unstable = "matches collection reform specification, waiting for dust to settle"]
114 pub fn is_superset(&self, other: &EnumSet<E>) -> bool {
115 (self.bits & other.bits) == other.bits
118 /// Returns `true` if this `EnumSet` is included in the given `EnumSet`.
119 #[unstable = "matches collection reform specification, waiting for dust to settle"]
120 pub fn is_subset(&self, other: &EnumSet<E>) -> bool {
121 other.is_superset(self)
124 /// Returns the union of both `EnumSets`.
125 pub fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
126 EnumSet {bits: self.bits | e.bits}
129 /// Returns the intersection of both `EnumSets`.
130 pub fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
131 EnumSet {bits: self.bits & e.bits}
134 /// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
135 #[unstable = "matches collection reform specification, waiting for dust to settle"]
136 pub fn insert(&mut self, e: E) -> bool {
137 let result = !self.contains(&e);
138 self.bits |= bit(&e);
142 /// Removes an enum from the EnumSet
143 #[unstable = "matches collection reform specification, waiting for dust to settle"]
144 pub fn remove(&mut self, e: &E) -> bool {
145 let result = self.contains(e);
146 self.bits &= !bit(e);
150 /// Returns `true` if an `EnumSet` contains a given enum.
151 #[unstable = "matches collection reform specification, waiting for dust to settle"]
152 pub fn contains(&self, e: &E) -> bool {
153 (self.bits & bit(e)) != 0
156 /// Returns an iterator over an `EnumSet`.
157 #[unstable = "matches collection reform specification, waiting for dust to settle"]
158 pub fn iter(&self) -> Iter<E> {
163 impl<E:CLike> Sub for EnumSet<E> {
164 type Output = EnumSet<E>;
166 fn sub(self, e: EnumSet<E>) -> EnumSet<E> {
167 EnumSet {bits: self.bits & !e.bits}
171 impl<E:CLike> BitOr for EnumSet<E> {
172 type Output = EnumSet<E>;
174 fn bitor(self, e: EnumSet<E>) -> EnumSet<E> {
175 EnumSet {bits: self.bits | e.bits}
179 impl<E:CLike> BitAnd for EnumSet<E> {
180 type Output = EnumSet<E>;
182 fn bitand(self, e: EnumSet<E>) -> EnumSet<E> {
183 EnumSet {bits: self.bits & e.bits}
187 impl<E:CLike> BitXor for EnumSet<E> {
188 type Output = EnumSet<E>;
190 fn bitxor(self, e: EnumSet<E>) -> EnumSet<E> {
191 EnumSet {bits: self.bits ^ e.bits}
195 /// An iterator over an EnumSet
201 // FIXME(#19839) Remove in favor of `#[derive(Clone)]`
202 impl<E> Clone for Iter<E> {
203 fn clone(&self) -> Iter<E> {
211 impl<E:CLike> Iter<E> {
212 fn new(bits: uint) -> Iter<E> {
213 Iter { index: 0, bits: bits }
217 impl<E:CLike> Iterator for Iter<E> {
220 fn next(&mut self) -> Option<E> {
225 while (self.bits & 1) == 0 {
229 let elem = CLike::from_uint(self.index);
235 fn size_hint(&self) -> (uint, Option<uint>) {
236 let exact = self.bits.count_ones();
241 impl<E:CLike> FromIterator<E> for EnumSet<E> {
242 fn from_iter<I:Iterator<Item=E>>(iterator: I) -> EnumSet<E> {
243 let mut ret = EnumSet::new();
244 ret.extend(iterator);
249 impl<E:CLike> Extend<E> for EnumSet<E> {
250 fn extend<I: Iterator<Item=E>>(&mut self, mut iterator: I) {
251 for element in iterator {
252 self.insert(element);
263 use super::{EnumSet, CLike};
265 #[derive(Copy, PartialEq, Show)]
272 fn to_uint(&self) -> uint {
276 fn from_uint(v: uint) -> Foo {
277 unsafe { mem::transmute(v) }
283 let e: EnumSet<Foo> = EnumSet::new();
284 assert!(e.is_empty());
289 let mut e = EnumSet::new();
290 assert_eq!("{}", e.to_string());
292 assert_eq!("{A}", e.to_string());
294 assert_eq!("{A, C}", e.to_string());
299 let mut e = EnumSet::new();
300 assert_eq!(e.len(), 0);
304 assert_eq!(e.len(), 3);
306 assert_eq!(e.len(), 2);
308 assert_eq!(e.len(), 0);
311 ///////////////////////////////////////////////////////////////////////////
315 fn test_two_empties_do_not_intersect() {
316 let e1: EnumSet<Foo> = EnumSet::new();
317 let e2: EnumSet<Foo> = EnumSet::new();
318 assert!(e1.is_disjoint(&e2));
322 fn test_empty_does_not_intersect_with_full() {
323 let e1: EnumSet<Foo> = EnumSet::new();
325 let mut e2: EnumSet<Foo> = EnumSet::new();
330 assert!(e1.is_disjoint(&e2));
334 fn test_disjoint_intersects() {
335 let mut e1: EnumSet<Foo> = EnumSet::new();
338 let mut e2: EnumSet<Foo> = EnumSet::new();
341 assert!(e1.is_disjoint(&e2));
345 fn test_overlapping_intersects() {
346 let mut e1: EnumSet<Foo> = EnumSet::new();
349 let mut e2: EnumSet<Foo> = EnumSet::new();
353 assert!(!e1.is_disjoint(&e2));
356 ///////////////////////////////////////////////////////////////////////////
357 // contains and contains_elem
361 let mut e1: EnumSet<Foo> = EnumSet::new();
364 let mut e2: EnumSet<Foo> = EnumSet::new();
368 let mut e3: EnumSet<Foo> = EnumSet::new();
371 assert!(e1.is_subset(&e2));
372 assert!(e2.is_superset(&e1));
373 assert!(!e3.is_superset(&e2));
374 assert!(!e2.is_superset(&e3))
379 let mut e1: EnumSet<Foo> = EnumSet::new();
381 assert!(e1.contains(&A));
382 assert!(!e1.contains(&B));
383 assert!(!e1.contains(&C));
387 assert!(e1.contains(&A));
388 assert!(e1.contains(&B));
389 assert!(!e1.contains(&C));
392 ///////////////////////////////////////////////////////////////////////////
397 let mut e1: EnumSet<Foo> = EnumSet::new();
399 let elems: ::vec::Vec<Foo> = e1.iter().collect();
400 assert!(elems.is_empty());
403 let elems: ::vec::Vec<_> = e1.iter().collect();
404 assert_eq!(vec![A], elems);
407 let elems: ::vec::Vec<_> = e1.iter().collect();
408 assert_eq!(vec![A,C], elems);
411 let elems: ::vec::Vec<_> = e1.iter().collect();
412 assert_eq!(vec![A,C], elems);
415 let elems: ::vec::Vec<_> = e1.iter().collect();
416 assert_eq!(vec![A,B,C], elems);
419 ///////////////////////////////////////////////////////////////////////////
423 fn test_operators() {
424 let mut e1: EnumSet<Foo> = EnumSet::new();
428 let mut e2: EnumSet<Foo> = EnumSet::new();
432 let e_union = e1 | e2;
433 let elems: ::vec::Vec<_> = e_union.iter().collect();
434 assert_eq!(vec![A,B,C], elems);
436 let e_intersection = e1 & e2;
437 let elems: ::vec::Vec<_> = e_intersection.iter().collect();
438 assert_eq!(vec![C], elems);
440 // Another way to express intersection
441 let e_intersection = e1 - (e1 - e2);
442 let elems: ::vec::Vec<_> = e_intersection.iter().collect();
443 assert_eq!(vec![C], elems);
445 let e_subtract = e1 - e2;
446 let elems: ::vec::Vec<_> = e_subtract.iter().collect();
447 assert_eq!(vec![A], elems);
449 // Bitwise XOR of two sets, aka symmetric difference
450 let e_symmetric_diff = e1 ^ e2;
451 let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
452 assert_eq!(vec![A,B], elems);
454 // Another way to express symmetric difference
455 let e_symmetric_diff = (e1 - e2) | (e2 - e1);
456 let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
457 assert_eq!(vec![A,B], elems);
459 // Yet another way to express symmetric difference
460 let e_symmetric_diff = (e1 | e2) - (e1 & e2);
461 let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
462 assert_eq!(vec![A,B], elems);
472 V00, V01, V02, V03, V04, V05, V06, V07, V08, V09,
473 V10, V11, V12, V13, V14, V15, V16, V17, V18, V19,
474 V20, V21, V22, V23, V24, V25, V26, V27, V28, V29,
475 V30, V31, V32, V33, V34, V35, V36, V37, V38, V39,
476 V40, V41, V42, V43, V44, V45, V46, V47, V48, V49,
477 V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
478 V60, V61, V62, V63, V64, V65, V66, V67, V68, V69,
482 fn to_uint(&self) -> uint {
486 fn from_uint(v: uint) -> Bar {
487 unsafe { mem::transmute(v) }
490 let mut set = EnumSet::new();
491 set.insert(Bar::V64);