fn bits(num: u64, from: u8, amount: u8) -> u64 {
assert!(amount <= 64);
let length = from - amount;
let mask = ((1 << amount) - 1) << length;
(mask & num) >> length
}
pub struct BitIterator {
object: u64,
iter_length: u8,
current_pos: u8,
}
impl BitIterator {
#[must_use]
#[allow(clippy::cast_possible_truncation)]
pub fn new(object: u64, iter_length: u8) -> BitIterator {
let current_pos = std::mem::size_of::<u64>() as u8 * 8;
assert!(iter_length <= current_pos);
BitIterator {
object,
iter_length,
current_pos,
}
}
pub fn change_iter_length(&mut self, iter_length: u8) -> &mut BitIterator {
assert!(iter_length <= self.current_pos);
self.iter_length = iter_length;
self
}
pub fn next_bits<T: std::convert::TryFrom<u64>>(&mut self, amount: u8) -> Option<T> {
self.change_iter_length(amount);
self.next().and_then(|next| T::try_from(next).ok())
}
}
impl Iterator for BitIterator {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
let new_pos = self.current_pos.checked_sub(self.iter_length)?;
let item = bits(self.object, self.current_pos, self.iter_length) as Self::Item;
self.current_pos = new_pos;
Some(item)
}
}