use crate::Vec;
use anyhow::{Result, ensure};
#[macro_export]
macro_rules! to_bits_le {
($($x:expr),*) => ({
let mut buffer = $crate::vec![];
$($x.write_bits_le(&mut buffer);)*
buffer
});
($($x:expr),*; $size:expr) => ({
let mut buffer = $crate::Vec::with_capacity($size);
$($x.write_bits_le(&mut buffer);)*
buffer
});
}
pub trait ToBits: Sized {
fn write_bits_le(&self, vec: &mut Vec<bool>);
fn write_bits_be(&self, vec: &mut Vec<bool>);
fn to_bits_le(&self) -> Vec<bool> {
let mut bits = Vec::new();
self.write_bits_le(&mut bits);
bits
}
fn to_bits_be(&self) -> Vec<bool> {
let mut bits = Vec::new();
self.write_bits_be(&mut bits);
bits
}
fn num_bits() -> Option<usize> {
None
}
}
pub trait FromBits: Sized {
fn from_bits_le(bits: &[bool]) -> Result<Self>;
fn from_bits_be(bits: &[bool]) -> Result<Self>;
}
macro_rules! to_bits_tuple {
(($t0:ident, $i0:tt), $(($ty:ident, $idx:tt)),+) => {
impl<$t0: ToBits, $($ty: ToBits),+> ToBits for ($t0, $($ty),+) {
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
(&self).write_bits_le(vec);
}
#[inline]
fn write_bits_be(&self, vec: &mut Vec<bool>) {
(&self).write_bits_be(vec);
}
}
impl<'a, $t0: ToBits, $($ty: ToBits),+> ToBits for &'a ($t0, $($ty),+) {
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
self.$i0.write_bits_le(vec);
$(self.$idx.write_bits_le(vec);)+
}
#[inline]
fn write_bits_be(&self, vec: &mut Vec<bool>) {
self.$i0.write_bits_be(vec);
$(self.$idx.write_bits_be(vec);)+
}
}
}
}
to_bits_tuple!((C0, 0), (C1, 1));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9));
to_bits_tuple!((C0, 0), (C1, 1), (C2, 2), (C3, 3), (C4, 4), (C5, 5), (C6, 6), (C7, 7), (C8, 8), (C9, 9), (C10, 10));
impl ToBits for bool {
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
vec.push(*self);
}
#[inline]
fn write_bits_be(&self, vec: &mut Vec<bool>) {
vec.push(*self);
}
}
macro_rules! impl_bits_for_integer {
($int:ty) => {
impl ToBits for $int {
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
let mut value = *self;
for _ in 0..<$int>::BITS {
vec.push(value & 1 == 1);
value = value.wrapping_shr(1u32);
}
}
#[inline]
fn write_bits_be(&self, vec: &mut Vec<bool>) {
let reversed = self.reverse_bits();
reversed.write_bits_le(vec);
}
fn num_bits() -> Option<usize> {
Some(<$int>::BITS as usize)
}
}
impl FromBits for $int {
#[inline]
fn from_bits_le(bits: &[bool]) -> Result<Self> {
for bit in bits.iter().skip(<$int>::BITS as usize) {
ensure!(!bit, "upper bits are not zero");
}
Ok(bits.iter().take(<$int>::BITS as usize).rev().fold(0, |value, bit| match bit {
true => (value.wrapping_shl(1)) ^ 1,
false => (value.wrapping_shl(1)) ^ 0,
}))
}
#[inline]
fn from_bits_be(bits: &[bool]) -> Result<Self> {
for bit in bits.iter().take(bits.len().saturating_sub(<$int>::BITS as usize)) {
ensure!(!bit, "upper bits are not zero");
}
Ok(bits.iter().skip(bits.len().saturating_sub(<$int>::BITS as usize)).fold(0, |value, bit| match bit {
true => (value.wrapping_shl(1)) ^ 1,
false => (value.wrapping_shl(1)) ^ 0,
}))
}
}
};
}
impl_bits_for_integer!(u8);
impl_bits_for_integer!(u16);
impl_bits_for_integer!(u32);
impl_bits_for_integer!(u64);
impl_bits_for_integer!(u128);
impl_bits_for_integer!(i8);
impl_bits_for_integer!(i16);
impl_bits_for_integer!(i32);
impl_bits_for_integer!(i64);
impl_bits_for_integer!(i128);
impl ToBits for String {
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
self.as_bytes().write_bits_le(vec);
}
#[inline]
fn write_bits_be(&self, vec: &mut Vec<bool>) {
self.as_bytes().write_bits_be(vec);
}
}
impl<C: ToBits> ToBits for Vec<C> {
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
self.as_slice().write_bits_le(vec);
}
#[inline]
fn write_bits_be(&self, vec: &mut Vec<bool>) {
self.as_slice().write_bits_be(vec);
}
}
impl<C: ToBits, const N: usize> ToBits for [C; N] {
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
self.as_slice().write_bits_le(vec)
}
#[inline]
fn write_bits_be(&self, vec: &mut Vec<bool>) {
self.as_slice().write_bits_be(vec)
}
}
impl<C: ToBits> ToBits for &[C] {
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
if let Some(num_bits) = C::num_bits() {
vec.reserve(num_bits * self.len());
}
for elem in self.iter() {
elem.write_bits_le(vec);
}
}
#[inline]
fn write_bits_be(&self, vec: &mut Vec<bool>) {
if let Some(num_bits) = C::num_bits() {
vec.reserve(num_bits * self.len());
}
for elem in self.iter() {
elem.write_bits_be(vec);
}
}
}
impl FromBits for Vec<u8> {
#[inline]
fn from_bits_le(bits: &[bool]) -> Result<Self> {
bits.chunks(8).map(u8::from_bits_le).collect::<Result<Vec<_>>>()
}
#[inline]
fn from_bits_be(bits: &[bool]) -> Result<Self> {
bits.chunks(8).map(u8::from_bits_be).collect::<Result<Vec<_>>>()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{TestRng, Uniform};
use anyhow::Result;
use rand::{Rng, distributions::Alphanumeric};
const ITERATIONS: u64 = 10000;
fn random_string(len: u16, rng: &mut TestRng) -> String {
rng.sample_iter(&Alphanumeric).take(len as usize).map(char::from).collect()
}
#[test]
fn test_to_bits_le_macro() {
let rng = &mut TestRng::default();
macro_rules! check {
($given:expr) => {{
let given = $given;
let mut expected = Vec::new();
given.iter().for_each(|elem| elem.write_bits_le(&mut expected));
let candidate = to_bits_le!(given);
assert_eq!(candidate, expected);
}};
}
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<u8>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<u16>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<u32>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<u64>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<u128>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<i8>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<i16>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<i32>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<i64>>());
check!((0..100).map(|_| Uniform::rand(rng)).collect::<Vec<i128>>());
check!((0..100).map(|_| random_string(rng.gen(), rng)).collect::<Vec<String>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<u8>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<u16>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<u32>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<u64>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<u128>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<i8>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<i16>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<i32>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<i64>>()).collect::<Vec<_>>());
check!((0..100).map(|_| (0..128).map(|_| Uniform::rand(rng)).collect::<Vec<i128>>()).collect::<Vec<_>>());
check!(
(0..100)
.map(|_| (0..128).map(|_| random_string(rng.gen(), rng)).collect::<Vec<String>>())
.collect::<Vec<_>>()
);
}
#[test]
fn test_to_bits_le_macro_with_capacity() {
let mut expected = Vec::new();
1u8.write_bits_le(&mut expected);
2u16.write_bits_le(&mut expected);
3u32.write_bits_le(&mut expected);
4u64.write_bits_le(&mut expected);
5u128.write_bits_le(&mut expected);
6i8.write_bits_le(&mut expected);
7i16.write_bits_le(&mut expected);
8i32.write_bits_le(&mut expected);
9i64.write_bits_le(&mut expected);
10i128.write_bits_le(&mut expected);
let capacity = expected.len();
let candidate = to_bits_le![1u8, 2u16, 3u32, 4u64, 5u128, 6i8, 7i16, 8i32, 9i64, 10i128; capacity];
assert_eq!(candidate, expected);
}
#[test]
fn test_integers() -> Result<()> {
macro_rules! check_integer {
($integer:tt, $rng:expr) => {{
for _ in 0..ITERATIONS {
let expected: $integer = Uniform::rand($rng);
let bits_le = expected.to_bits_le();
assert_eq!(expected, $integer::from_bits_le(&bits_le)?);
let bits_be = expected.to_bits_be();
assert_eq!(expected, $integer::from_bits_be(&bits_be)?);
}
}};
}
let mut rng = TestRng::default();
check_integer!(u8, &mut rng);
check_integer!(u16, &mut rng);
check_integer!(u32, &mut rng);
check_integer!(u64, &mut rng);
check_integer!(u128, &mut rng);
check_integer!(i8, &mut rng);
check_integer!(i16, &mut rng);
check_integer!(i32, &mut rng);
check_integer!(i64, &mut rng);
check_integer!(i128, &mut rng);
Ok(())
}
}