use crate::BitContainer;
use super::{BitIterableContainer, InnerType};
use core::ops::{BitAnd, Shl};
pub trait BitConvert {
type Bits: Iterator<Item = bool>;
const SIZE: usize;
fn into_bits(self) -> Self::Bits;
fn from_bits<I>(iter: I) -> Self
where
I: Iterator<Item = bool>;
}
#[derive(Debug, Clone)]
pub struct BitIter<T> {
value: T,
pos: usize,
total: usize,
}
impl<T> Iterator for BitIter<T>
where
T: From<bool>,
T: Shl<usize, Output = T>,
T: BitAnd<T, Output = T>,
T: Copy,
T: Eq,
{
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
if self.pos == self.total {
return None;
}
let one = T::from(true);
let zero = T::from(false);
let mask = one << self.pos;
let bit = self.value & mask;
self.pos += 1;
Some(bit != zero)
}
}
macro_rules! impl_bitconvert {
($($t:ty),*) => {
$(
impl BitConvert for $t {
type Bits = BitIter<$t>;
const SIZE: usize = core::mem::size_of::<Self>() * 8;
fn into_bits(self) -> Self::Bits {
BitIter {
value: self,
pos: 0,
total: Self::SIZE,
}
}
fn from_bits<I>(iter: I) -> Self
where
I: Iterator<Item = bool>
{
iter.take(Self::SIZE)
.enumerate()
.fold(0, |acc, (i, bit)| acc | (Self::from(bit) << i))
}
}
)*
};
}
impl_bitconvert!(u8, u16, u32, u64);
impl<U: InnerType> BitConvert for BitIterableContainer<U> {
type Bits = U::Bits;
const SIZE: usize = U::SIZE;
#[inline]
fn into_bits(self) -> Self::Bits {
self.into_inner().into_bits()
}
#[inline]
fn from_bits<I>(iter: I) -> Self
where
I: Iterator<Item = bool>,
{
U::from_bits(iter).into()
}
}
impl BitConvert for bool {
type Bits = core::iter::Once<bool>;
const SIZE: usize = 1;
fn into_bits(self) -> Self::Bits {
core::iter::once(self)
}
fn from_bits<I>(mut iter: I) -> Self
where
I: Iterator<Item = bool>,
{
iter.next().is_some_and(|bool| bool)
}
}
impl BitConvert for () {
type Bits = core::iter::Empty<bool>;
const SIZE: usize = 0;
fn into_bits(self) -> Self::Bits {
core::iter::empty()
}
fn from_bits<I>(_iter: I) -> Self
where
I: Iterator<Item = bool>,
{
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::vec;
use std::vec::Vec;
#[test]
fn bit_iter_all_zeros() {
let iter = BitIter {
value: 0b0000_0000u8,
pos: 0,
total: 8,
};
assert_eq!(iter.collect::<Vec<bool>>(), vec![false; 8])
}
#[test]
fn bit_iter_all_ones() {
let iter = BitIter {
value: 0b1111_1111u8,
pos: 0,
total: 8,
};
assert_eq!(iter.collect::<Vec<bool>>(), vec![true; 8])
}
#[test]
fn bit_iter_mixed() {
let iter = BitIter {
value: 0b1010_1100u8,
pos: 0,
total: 8,
};
assert_eq!(
iter.collect::<Vec<bool>>(),
vec![false, false, true, true, false, true, false, true]
)
}
#[test]
fn bit_convert_unit_into_bits() {
assert_eq!(().into_bits().count(), 0)
}
#[test]
fn bit_convert_bool_into_bits() {
assert_eq!(true.into_bits().collect::<Vec<bool>>(), vec![true]);
assert_eq!(false.into_bits().collect::<Vec<bool>>(), vec![false])
}
#[test]
fn bit_convert_bool_from_bits() {
assert!(bool::from_bits([true].into_iter()));
assert!(!bool::from_bits([false].into_iter()));
}
#[test]
fn bit_convert_bool_from_bits_empty_ite() {
assert!(!bool::from_bits([].into_iter()));
}
#[test]
fn bit_convert_uint_into_bits() {
let min: Vec<bool> = u8::MIN.into_bits().collect();
assert_eq!(min, vec![false; 8]);
let max: Vec<bool> = u8::MAX.into_bits().collect();
assert_eq!(max, vec![true; 8]);
let mixed: Vec<bool> = 0b1100_1001u8.into_bits().collect();
let expected = vec![true, false, false, true, false, false, true, true];
assert_eq!(mixed, expected);
}
}