#![no_std]
#![doc(html_root_url = "https://docs.rs/bit-iter/1.3.1")]
use core::iter::{ExactSizeIterator, FusedIterator};
#[cfg(test)]
mod tests;
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct BitIter<T>(T);
macro_rules! iter_impl {
($($t:ty)*) => {$(
#[doc(hidden)]
impl BitIter<$t> {
#[inline]
fn rightmost_one_pos(&self) -> usize {
self.0.trailing_zeros() as usize
}
#[inline]
fn leftmost_one_pos(&self) -> usize {
(<$t>::BITS - 1 - self.0.leading_zeros()) as usize
}
#[inline]
fn count_ones(&self) -> usize {
self.0.count_ones() as usize
}
#[inline]
fn clear_rightmost_one(&mut self) {
self.0 &= self.0.wrapping_sub(1);
}
}
impl From<$t> for BitIter<$t> {
#[inline]
fn from(value: $t) -> Self {
Self(value)
}
}
impl Iterator for BitIter<$t> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.0 != 0 {
let trailing = self.rightmost_one_pos();
self.clear_rightmost_one();
Some(trailing)
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let sz = self.count_ones();
(sz, Some(sz))
}
#[inline]
fn count(self) -> usize {
self.count_ones()
}
#[inline]
fn last(self) -> Option<Self::Item> {
if self.0 != 0 {
Some(self.leftmost_one_pos())
} else {
None
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let mut i = 0;
while self.0 != 0 && i < n {
self.clear_rightmost_one();
i += 1;
}
self.next()
}
#[inline]
fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B
{
let mut accum = init;
while self.0 != 0 {
accum = f(accum, self.rightmost_one_pos());
self.clear_rightmost_one();
}
accum
}
#[inline]
fn max(self) -> Option<Self::Item> {
self.last()
}
#[inline]
fn min(self) -> Option<Self::Item> {
if self.0 != 0 {
Some(self.rightmost_one_pos())
} else {
None
}
}
fn is_sorted(self) -> bool {
true
}
}
impl FusedIterator for BitIter<$t> {}
impl DoubleEndedIterator for BitIter<$t> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
if self.0 != 0 {
let highest = self.leftmost_one_pos();
self.0 ^= 1 as $t << highest;
Some(highest)
} else {
None
}
}
}
impl ExactSizeIterator for BitIter<$t> {
#[inline]
fn len(&self) -> usize {
self.count_ones()
}
}
)*}
}
iter_impl! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }