From 0fc99f1997be9323bb75826c478094e74797ddf9 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 30 Jun 2013 20:12:04 +0200 Subject: [PATCH] Add an EnumSetIterator and EnumSet::iter --- src/librustc/util/enum_set.rs | 92 +++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 9 deletions(-) diff --git a/src/librustc/util/enum_set.rs b/src/librustc/util/enum_set.rs index 2bdb6583b2304..7f29ce98b3ec1 100644 --- a/src/librustc/util/enum_set.rs +++ b/src/librustc/util/enum_set.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::iterator::Iterator; #[deriving(Eq, IterBytes)] pub struct EnumSet { @@ -73,6 +74,10 @@ impl EnumSet { } return true; } + + pub fn iter(&self) -> EnumSetIterator { + EnumSetIterator::new(self.bits) + } } impl Sub, EnumSet> for EnumSet { @@ -93,6 +98,39 @@ impl BitAnd, EnumSet> for EnumSet { } } +pub struct EnumSetIterator { + priv index: uint, + priv bits: uint, +} + +impl EnumSetIterator { + fn new(bits: uint) -> EnumSetIterator { + EnumSetIterator { index: 0, bits: bits } + } +} + +impl Iterator for EnumSetIterator { + fn next(&mut self) -> Option { + if (self.bits == 0) { + return None; + } + + while (self.bits & 1) == 0 { + self.index += 1; + self.bits >>= 1; + } + let elem = CLike::from_uint(self.index); + self.index += 1; + self.bits >>= 1; + Some(elem) + } + + fn size_hint(&self) -> (Option, Option) { + let exact = Some(self.bits.population_count()); + (exact, exact) + } +} + #[cfg(test)] mod test { @@ -199,25 +237,58 @@ mod test { } /////////////////////////////////////////////////////////////////////////// - // each + // iterator + + #[test] + fn test_iterator() { + let mut e1: EnumSet = EnumSet::empty(); + + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[], elems) + + e1.add(A); + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[A], elems) + + e1.add(C); + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[A,C], elems) + + e1.add(C); + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[A,C], elems) + + e1.add(B); + let elems: ~[Foo] = e1.iter().collect(); + assert_eq!(~[A,B,C], elems) + } + + fn collect(e: EnumSet) -> ~[Foo] { + let mut elems = ~[]; + e.each(|elem| { + elems.push(elem); + true + }); + elems + } #[test] fn test_each() { let mut e1: EnumSet = EnumSet::empty(); - assert_eq!(~[], iter::FromIter::from_iter::(|f| e1.each(f))) + assert_eq!(~[], collect(e1)) e1.add(A); - assert_eq!(~[A], iter::FromIter::from_iter::(|f| e1.each(f))) + assert_eq!(~[A], collect(e1)) e1.add(C); - assert_eq!(~[A,C], iter::FromIter::from_iter::(|f| e1.each(f))) + assert_eq!(~[A,C], collect(e1)) e1.add(C); - assert_eq!(~[A,C], iter::FromIter::from_iter::(|f| e1.each(f))) + assert_eq!(~[A,C], collect(e1)) e1.add(B); - assert_eq!(~[A,B,C], iter::FromIter::from_iter::(|f| e1.each(f))) + assert_eq!(~[A,B,C], collect(e1)) } /////////////////////////////////////////////////////////////////////////// @@ -234,12 +305,15 @@ mod test { e2.add(C); let e_union = e1 | e2; - assert_eq!(~[A,B,C], iter::FromIter::from_iter::(|f| e_union.each(f))) + let elems: ~[Foo] = e_union.iter().collect(); + assert_eq!(~[A,B,C], elems) let e_intersection = e1 & e2; - assert_eq!(~[C], iter::FromIter::from_iter::(|f| e_intersection.each(f))) + let elems: ~[Foo] = e_intersection.iter().collect(); + assert_eq!(~[C], elems) let e_subtract = e1 - e2; - assert_eq!(~[A], iter::FromIter::from_iter::(|f| e_subtract.each(f))) + let elems: ~[Foo] = e_subtract.iter().collect(); + assert_eq!(~[A], elems) } }