Skip to content

Commit b11ca85

Browse files
committed
Implement Iterator with bit manipulations
1 parent adcbff1 commit b11ca85

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

src/lib.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -216,34 +216,43 @@ pub mod _internal {
216216

217217
use ::core::cmp::PartialOrd;
218218
use ::core::fmt;
219-
use ::core::ops::{BitAnd, BitOr, BitXor, Not};
219+
use ::core::ops::{BitAnd, BitOr, BitXor, Not, Sub};
220220

221221
pub trait BitFlagNum:
222222
Default
223223
+ BitOr<Self, Output = Self>
224224
+ BitAnd<Self, Output = Self>
225225
+ BitXor<Self, Output = Self>
226+
+ Sub<Self, Output = Self>
226227
+ Not<Output = Self>
227228
+ PartialOrd<Self>
228229
+ fmt::Debug
229230
+ fmt::Binary
230231
+ Copy
231232
+ Clone
232233
{
233-
#[doc(hidden)]
234+
const ONE: Self;
235+
234236
fn is_power_of_two(self) -> bool;
235-
#[doc(hidden)]
236237
fn count_ones(self) -> u32;
238+
fn wrapping_neg(self) -> Self;
237239
}
238240

239241
for_each_uint! { $ty $hide_docs =>
240242
impl BitFlagNum for $ty {
243+
const ONE: Self = 1;
244+
241245
fn is_power_of_two(self) -> bool {
242246
<$ty>::is_power_of_two(self)
243247
}
248+
244249
fn count_ones(self) -> u32 {
245250
<$ty>::count_ones(self)
246251
}
252+
253+
fn wrapping_neg(self) -> Self {
254+
<$ty>::wrapping_neg(self)
255+
}
247256
}
248257
}
249258

@@ -640,7 +649,6 @@ where
640649
pub fn iter(self) -> Iter<T> {
641650
Iter {
642651
rest: self,
643-
it: T::FLAG_LIST.iter(),
644652
}
645653
}
646654
}
@@ -658,7 +666,6 @@ impl<T: BitFlag> IntoIterator for BitFlags<T> {
658666
#[derive(Clone, Debug)]
659667
pub struct Iter<T: BitFlag> {
660668
rest: BitFlags<T>,
661-
it: core::slice::Iter<'static, T>,
662669
}
663670

664671
impl<T> Iterator for Iter<T>
@@ -668,15 +675,15 @@ where
668675
type Item = T;
669676

670677
fn next(&mut self) -> Option<Self::Item> {
671-
for &flag in &mut self.it {
672-
let yes = self.rest.contains(flag);
678+
if self.rest.is_empty() {
679+
None
680+
} else {
681+
let bits = self.rest.bits();
682+
let flag: T::Numeric = bits & bits.wrapping_neg();
683+
let flag: T = unsafe { core::mem::transmute_copy(&flag) };
673684
self.rest.remove(flag);
674-
if yes {
675-
return Some(flag);
676-
}
685+
Some(flag)
677686
}
678-
679-
None
680687
}
681688

682689
fn size_hint(&self) -> (usize, Option<usize>) {

0 commit comments

Comments
 (0)