#![no_std]
use core::cmp::PartialEq;
use core::iter::Iterator;
use core::num::Wrapping;
use core::ops::{RangeInclusive, Shl, Shr, Sub, Not, BitAnd, BitOr};
pub trait Twiddle {
fn mask(range: RangeInclusive<usize>) -> Self;
fn bit(self, bit: usize) -> bool;
fn bits(self, range: RangeInclusive<usize>) -> Self;
fn set_bit(self, bit: usize, value: bool) -> Self;
fn replace(self, range: RangeInclusive<usize>, bits: Self) -> Self;
fn split<I>(self, lengths: I) -> Split<Self, <I as IntoIterator>::IntoIter>
where I: IntoIterator<Item=usize>, Self: Sized;
}
impl<T> Twiddle for T where
T: Int,
Wrapping<T>: Sub<Output=Wrapping<T>>
{
fn mask(range: RangeInclusive<usize>) -> T {
let (start, end) = (*range.start(), *range.end());
debug_assert!(start < T::bit_width());
debug_assert!(end <= start);
let top = Wrapping(T::one().cshl(1 + start - end));
let one = Wrapping(T::one());
(top - one).0 << end
}
fn bit(self, bit: usize) -> bool {
((self >> bit) & T::one()) != T::zero()
}
fn bits(self, range: RangeInclusive<usize>) -> T {
(self & T::mask(range.clone())) >> *range.end()
}
fn set_bit(self, bit: usize, value: bool) -> T {
let mask = T::mask(bit..=bit);
(self & !mask) | (if value { T::one() } else { T::zero() } << bit)
}
fn replace(self, range: RangeInclusive<usize>, bits: T) -> T {
let mask = T::mask(range.clone());
(self & !mask) | ((bits << *range.end()) & mask)
}
fn split<I>(self, lengths: I) -> Split<T, <I as IntoIterator>::IntoIter>
where I: IntoIterator<Item=usize> {
Split {
number: self,
lengths: lengths.into_iter(),
bits_left: T::bit_width() as isize
}
}
}
pub struct Split<T, I> {
number: T,
lengths: I,
bits_left: isize
}
impl<T, I> Iterator for Split<T, I> where
T: Twiddle + Int,
I: Iterator<Item=usize>
{
type Item = T;
fn next(&mut self) -> Option<T> {
if self.bits_left <= 0 { return None }
match self.lengths.next() {
None => None,
Some(0) => Some(T::zero()),
Some(n) => {
let start = T::bit_width() - 1;
let end = if n > start { 0 } else { start + 1 - n };
let bits = self.number.bits(start..=end);
self.number = self.number << n;
self.bits_left -= n as isize;
Some(bits)
}
}
}
}
pub trait Int:
Shl<usize, Output=Self> +
Shr<usize, Output=Self> +
Not<Output=Self> +
BitAnd<Output=Self> +
BitOr<Output=Self> +
PartialEq<Self> +
Clone + Copy
{
fn bit_width() -> usize;
fn zero() -> Self;
fn one() -> Self;
fn cshl(self, n: usize) -> Self;
}
macro_rules! impl_int {
($($t:ty : $w:expr, $z:expr, $o:expr);*) => ($(
impl Int for $t {
#[inline]
fn bit_width() -> usize { $w }
#[inline]
fn zero() -> Self { $z }
#[inline]
fn one() -> Self { $o }
#[inline]
fn cshl(self, n: usize) -> Self {
self.checked_shl(n as u32).unwrap_or(0)
}
}
)*)
}
impl_int! {
u8: 8, 0, 1;
u16: 16, 0, 1;
u32: 32, 0, 1;
u64: 64, 0, 1
}
#[cfg(test)]
mod tests {
use Twiddle;
#[test]
fn mask_middle() {
assert_eq!(u8::mask(4..=2), 0b0001_1100);
}
#[test]
fn mask_top() {
assert_eq!(u8::mask(7..=3), 0b1111_1000);
}
#[test]
fn mask_bottom() {
assert_eq!(u8::mask(2..=0), 0b0000_0111);
}
#[test]
fn mask_full() {
assert_eq!(u8::mask(7..=0), 0b1111_1111);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "assertion failed")]
fn mask_reversed() {
u8::mask(2..=4);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "assertion failed")]
fn mask_overflow() {
u8::mask(99..=2);
}
#[test]
fn bit() {
let byte: u8 = 0b0010_1001;
let mut bits = [false; 8];
for i in 0..8 {
bits[i] = byte.bit(7-i);
}
assert_eq!(bits, [false, false, true, false, true, false, false, true]);
}
#[test]
fn bits_middle() {
assert_eq!(0b0010_1110_1001_0011u16.bits(10..= 3), 0b0000_0000_1101_0010);
}
#[test]
fn bits_top() {
assert_eq!(0b1110_0011_0011_1111u16.bits(15..=12), 0b0000_0000_0000_1110);
}
#[test]
fn bits_bottom() {
assert_eq!(0b0111_1011_1000_0110u16.bits( 6..= 0), 0b0000_0000_0000_0110);
}
#[test]
fn bits_full() {
assert_eq!(0b1100_1010_0111_1000u16.bits(15..= 0), 0b1100_1010_0111_1000);
}
#[test]
fn unset_false_bit() {
assert_eq!(0b1100_1010_0111_1000u16.set_bit(13, false), 0b1100_1010_0111_1000);
}
#[test]
fn unset_true_bit() {
assert_eq!(0b1100_1010_0111_1000u16.set_bit(14, false), 0b1000_1010_0111_1000);
}
#[test]
fn set_false_bit() {
assert_eq!(0b1100_1010_0111_1000u16.set_bit(1, true), 0b1100_1010_0111_1010);
}
#[test]
fn set_true_bit() {
assert_eq!(0b1100_1010_0111_1000u16.set_bit(3, true), 0b1100_1010_0111_1000);
}
#[test]
fn replace_middle() {
assert_eq!(
0b0111_0010_1100_1101u16.replace(11..= 5, 0b011_0011),
0b0111_0110_0110_1101
);
}
#[test]
fn replace_top() {
assert_eq!(
0b0011_1100_0101_0110u16.replace(15..=10, 0b11_0101),
0b1101_0100_0101_0110
);
}
#[test]
fn replace_bottom() {
assert_eq!(
0b1111_1001_0100_1100u16.replace( 7..= 0, 0b1110_1110),
0b1111_1001_1110_1110
);
}
#[test]
fn replace_full() {
assert_eq!(
0b1001_1001_1110_0001u16.replace(15..= 0, 0b1010_0101_0010_0111),
0b1010_0101_0010_0111
);
}
#[test]
fn replace_overlong() {
assert_eq!(
0b0000_0000_0000_0000u16.replace( 7..= 4, 0b1111_1111_1111),
0b0000_0000_1111_0000
);
}
#[test]
fn split() {
let n: u32 = 0b111_000000_1111111_0000_1111_000000_11;
let lengths = [3, 6, 7, 4, 4, 6, 5, 9];
let mut sets = [0; 7];
for (i, set) in n.split(lengths.iter().cloned()).enumerate() {
sets[i] = set;
}
assert_eq!(sets, [0b111, 0b0, 0b1111111, 0b0, 0b1111, 0b0, 0b11000]);
}
}