bin_iter/
lib.rs

1//! 2 進法のイテレータ。
2
3/// 2 進法のイテレータ。
4///
5/// ```
6/// # use bin_iter::BinIter;
7/// assert!(0_u32.bin_iter().eq([]));
8/// assert!(1_u32.bin_iter().map(u32::from).eq([1]));
9/// assert!(0b_1001011_u64.bin_iter().map(u32::from).eq([1, 1, 0, 1, 0, 0, 1]));
10/// assert!((!0_u128).bin_iter().map(u32::from).eq([1; 128]));
11/// ```
12pub trait BinIter {
13    type Iter: Iterator<Item = bool>;
14    fn bin_iter(&self) -> Self::Iter;
15}
16
17pub struct UIntIter<U>(U);
18
19pub trait Binary {
20    fn pop(&mut self) -> Option<bool>;
21}
22
23macro_rules! impl_binary {
24    ( $($ty:ty)* ) => { $(
25        impl Binary for $ty {
26            fn pop(&mut self) -> Option<bool> {
27                if *self == 0 {
28                    None
29                } else {
30                    let tmp = *self & 1 != 0;
31                    *self >>= 1;
32                    Some(tmp)
33                }
34            }
35        }
36    )* }
37}
38
39impl_binary! { u8 u16 u32 u64 u128 usize }
40
41impl<U: Binary> UIntIter<U> {
42    pub fn new(u: U) -> Self { Self(u) }
43}
44
45impl<U: Binary> Iterator for UIntIter<U> {
46    type Item = bool;
47    fn next(&mut self) -> Option<Self::Item> { self.0.pop() }
48}
49
50macro_rules! impl_bin_iter {
51    ( $($ty:ty)* ) => { $(
52        impl BinIter for $ty {
53            type Iter = UIntIter<$ty>;
54            fn bin_iter(&self) -> Self::Iter { Self::Iter::new(*self) }
55        }
56    )* }
57}
58
59impl_bin_iter! { u8 u16 u32 u64 u128 usize }
60
61#[test]
62fn sanity_check() {
63    assert!(0_u32.bin_iter().eq([]));
64    assert!(1_u32.bin_iter().map(u32::from).eq([1]));
65    assert!(0b_1001011_u64.bin_iter().map(u32::from).eq([1, 1, 0, 1, 0, 0, 1]));
66    assert!((!0_u128).bin_iter().map(u32::from).eq([1; 128]));
67}