-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathmask_iter.rs
73 lines (66 loc) · 1.86 KB
/
mask_iter.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Copyright (C) 2020 Andrej Shadura
// SPDX-License-Identifier: MIT
use std::iter::Iterator;
/// Iterate over the bits of a binary value
///
/// `IterableMask` is an iterator producing only the set bits
/// of a binary value it is created from:
/// ```rust
/// IterableMask::from(0x81_u8).collect::<Vec<u8>>()
/// # [0x80, 1]
/// ```
pub struct IterableMask<T> {
value: T,
curr_mask: T
}
macro_rules! implement_iterable_mask {
($t: ty) => {
impl Iterator for IterableMask<$t> {
type Item = $t;
fn next(&mut self) -> Option<$t> {
loop {
let bit = self.curr_mask & self.value;
self.curr_mask >>= 1;
if bit != 0 {
return Some(bit);
}
if self.curr_mask == 0 {
break;
}
}
None
}
}
impl From<$t> for IterableMask<$t> {
fn from(value: $t) -> Self {
IterableMask {
value,
curr_mask: <$t>::from(1u8).rotate_right(1)
}
}
}
};
}
implement_iterable_mask!(u8);
implement_iterable_mask!(u16);
implement_iterable_mask!(u32);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
assert_eq!(
IterableMask::from(0x123ce_u32).collect::<Vec<u32>>(),
[0x10000, 0x2000, 0x200, 0x100, 0x80, 0x40, 8, 4, 2]
);
assert_eq!(
IterableMask::from(0x23c5_u16).collect::<Vec<u16>>(),
[0x2000, 0x200, 0x100, 0x80, 0x40, 4, 1]
);
assert_eq!(
IterableMask::from(0xce_u8).collect::<Vec<u8>>(),
[0x80, 0x40, 8, 4, 2]
);
assert_eq!(IterableMask::from(0_u8).collect::<Vec<u8>>(), []);
}
}