bva 0.4.1

bva is a rust crate for manipulating and doing arithmetics on bit vectors of fixed but arbitrary size.
Documentation
use std::fmt::Debug;

use crate::auto::Bv;
use crate::dynamic::Bvd;
use crate::fixed::Bvf;
use crate::tests::{bvf_bvf_inner_unroll, bvf_inner_unroll, random_bv, random_test_bv};
use crate::utils::{IArray, Integer, StaticCast};
use crate::{BitVector, ConvertionError};

use num_bigint::BigInt;

fn from_inner<B, C>(capacity: usize)
where
    B: BitVector,
    C: From<B> + for<'a> From<&'a B> + PartialEq<BigInt> + PartialEq<B> + Debug,
{
    for size in 1..capacity {
        let (bv, bi) = random_test_bv::<B>(size);
        let cv1 = C::from(&bv);
        let cv2 = C::from(bv);
        assert_eq!(cv1, bi);
        assert_eq!(cv2, bi);
    }
}

fn try_from_inner<B, C>(capacity: usize)
where
    B: BitVector,
    C: TryFrom<B, Error: Debug> + for<'a> TryFrom<&'a B, Error: Debug> + PartialEq<BigInt> + Debug,
{
    for size in 1..capacity {
        let (bv, bi) = random_test_bv::<B>(size);
        let cv1 = C::try_from(&bv).unwrap();
        let cv2 = C::try_from(bv).unwrap();
        assert_eq!(cv1, bi);
        assert_eq!(cv2, bi);
    }
}

fn try_from_uint_inner<B, C>(capacity: usize)
where
    B: BitVector
        + TryFrom<C, Error: Debug>
        + for<'a> TryFrom<&'a C, Error: Debug>
        + PartialEq<BigInt>,
    C: Integer + TryFrom<B, Error: Debug> + for<'a> TryFrom<&'a B, Error: Debug>,
{
    for size in 1..capacity {
        let (bv1, bi) = random_test_bv::<B>(size);
        let c1 = C::try_from(&bv1).unwrap();
        let bv2 = B::try_from(&c1).unwrap();
        assert_eq!(bv2, bi);
        let c2 = C::try_from(bv1).unwrap();
        let bv3 = B::try_from(c2).unwrap();
        assert_eq!(bv3, bi);
    }
}

fn try_from_bvf_uint_inner<I: Integer, const N: usize>()
where
    I: StaticCast<usize>,
{
    try_from_uint_inner::<Bvf<I, N>, u8>(usize::min(Bvf::<I, N>::capacity(), u8::BITS as usize));
    try_from_uint_inner::<Bvf<I, N>, u16>(usize::min(Bvf::<I, N>::capacity(), u16::BITS as usize));
    try_from_uint_inner::<Bvf<I, N>, u32>(usize::min(Bvf::<I, N>::capacity(), u32::BITS as usize));
    try_from_uint_inner::<Bvf<I, N>, u64>(usize::min(Bvf::<I, N>::capacity(), u64::BITS as usize));
    try_from_uint_inner::<Bvf<I, N>, u128>(usize::min(
        Bvf::<I, N>::capacity(),
        u128::BITS as usize,
    ));
    if Bvf::<I, N>::capacity() < u16::BITS as usize {
        assert_eq!(
            Bvf::<I, N>::try_from(u16::MAX),
            Err(ConvertionError::NotEnoughCapacity)
        );
    } else if Bvf::<I, N>::capacity() > u16::BITS as usize {
        assert_eq!(
            u16::try_from(Bvf::<I, N>::ones(u16::BITS as usize + 1)),
            Err(ConvertionError::NotEnoughCapacity)
        );
    }
    if Bvf::<I, N>::capacity() < u32::BITS as usize {
        assert_eq!(
            Bvf::<I, N>::try_from(u32::MAX),
            Err(ConvertionError::NotEnoughCapacity)
        );
    } else if Bvf::<I, N>::capacity() > u32::BITS as usize {
        assert_eq!(
            u32::try_from(Bvf::<I, N>::ones(u32::BITS as usize + 1)),
            Err(ConvertionError::NotEnoughCapacity)
        );
    }
    if Bvf::<I, N>::capacity() < u64::BITS as usize {
        assert_eq!(
            Bvf::<I, N>::try_from(u64::MAX),
            Err(ConvertionError::NotEnoughCapacity)
        );
    } else if Bvf::<I, N>::capacity() > u64::BITS as usize {
        assert_eq!(
            u64::try_from(Bvf::<I, N>::ones(u64::BITS as usize + 1)),
            Err(ConvertionError::NotEnoughCapacity)
        );
    }
    if Bvf::<I, N>::capacity() < usize::BITS as usize {
        assert_eq!(
            Bvf::<I, N>::try_from(usize::MAX),
            Err(ConvertionError::NotEnoughCapacity)
        );
    } else if Bvf::<I, N>::capacity() > usize::BITS as usize {
        assert_eq!(
            usize::try_from(Bvf::<I, N>::ones(usize::BITS as usize + 1)),
            Err(ConvertionError::NotEnoughCapacity)
        );
    }
    if Bvf::<I, N>::capacity() < u128::BITS as usize {
        assert_eq!(
            Bvf::<I, N>::try_from(u128::MAX),
            Err(ConvertionError::NotEnoughCapacity)
        );
    } else if Bvf::<I, N>::capacity() > u128::BITS as usize {
        assert_eq!(
            u128::try_from(Bvf::<I, N>::ones(u128::BITS as usize + 1)),
            Err(ConvertionError::NotEnoughCapacity)
        );
    }
}

#[test]
fn from_bvf_uint() {
    bvf_inner_unroll!(try_from_bvf_uint_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

fn try_from_bvf_bvf_inner<I1, I2, const N1: usize, const N2: usize>()
where
    I1: Integer + StaticCast<I2>,
    I2: Integer + StaticCast<I1>,
{
    for size in 1..usize::min(Bvf::<I1, N1>::capacity(), Bvf::<I2, N2>::capacity()) {
        let (bv, bi) = random_test_bv::<Bvf<I1, N1>>(size);
        let cv1 = Bvf::<I2, N2>::try_from(&bv).unwrap();
        assert_eq!(cv1, bi);
    }
    if Bvf::<I1, N1>::capacity() > Bvf::<I2, N2>::capacity() {
        assert_eq!(
            Bvf::<I2, N2>::try_from(&Bvf::<I1, N1>::ones(Bvf::<I1, N1>::capacity())),
            Err(ConvertionError::NotEnoughCapacity)
        )
    }
}

#[test]
fn from_bvf_bvf() {
    bvf_bvf_inner_unroll!(try_from_bvf_bvf_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

fn try_from_bvf_bvd_inner<I: Integer, const N: usize>()
where
    u64: StaticCast<I>,
{
    try_from_inner::<Bvf<I, N>, Bvd>(Bvf::<I, N>::capacity());
    assert_eq!(
        Bvf::<I, N>::try_from(Bvd::ones(Bvf::<I, N>::capacity() + 1)),
        Err(ConvertionError::NotEnoughCapacity)
    );
}

#[test]
fn from_bvf_bvd() {
    bvf_inner_unroll!(try_from_bvf_bvd_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

fn try_from_bvf_bv_inner<I: Integer, const N: usize>()
where
    u64: StaticCast<I>,
{
    try_from_inner::<Bvf<I, N>, Bv>(Bvf::<I, N>::capacity());
    assert_eq!(
        Bvf::<I, N>::try_from(Bv::ones(Bvf::<I, N>::capacity() + 1)),
        Err(ConvertionError::NotEnoughCapacity)
    );
}

#[test]
fn from_bvf_bv() {
    bvf_inner_unroll!(try_from_bvf_bv_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn from_bvd_uint() {
    try_from_uint_inner::<Bvd, u8>(u8::BITS as usize);
    try_from_uint_inner::<Bvd, u16>(u16::BITS as usize);
    try_from_uint_inner::<Bvd, u32>(u32::BITS as usize);
    try_from_uint_inner::<Bvd, u64>(u64::BITS as usize);
    try_from_uint_inner::<Bvd, u128>(u128::BITS as usize);
    assert_eq!(
        u8::try_from(Bvd::ones(9)),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        u16::try_from(Bvd::ones(17)),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        u32::try_from(Bvd::ones(33)),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        u64::try_from(Bvd::ones(65)),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        u128::try_from(Bvd::ones(129)),
        Err(ConvertionError::NotEnoughCapacity)
    );
}

fn try_from_bvd_bvf_inner<I: Integer, const N: usize>()
where
    u64: StaticCast<I>,
{
    try_from_inner::<Bvd, Bvf<I, N>>(Bvf::<I, N>::capacity());
}

#[test]
fn from_bvd_bvf() {
    bvf_inner_unroll!(try_from_bvd_bvf_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

fn try_from_bv_bvf_inner<I: Integer, const N: usize>()
where
    u64: StaticCast<I>,
{
    try_from_inner::<Bv, Bvf<I, N>>(Bvf::<I, N>::capacity());
}

#[test]
fn from_bvd_bv() {
    from_inner::<Bvd, Bv>(512);
}

#[test]
fn from_bv_uint() {
    try_from_uint_inner::<Bv, u8>(u8::BITS as usize);
    try_from_uint_inner::<Bv, u16>(u16::BITS as usize);
    try_from_uint_inner::<Bv, u32>(u32::BITS as usize);
    try_from_uint_inner::<Bv, u64>(u64::BITS as usize);
    try_from_uint_inner::<Bv, u128>(u128::BITS as usize);
    assert_eq!(
        u8::try_from(Bv::ones(9)),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        u16::try_from(Bv::ones(17)),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        u32::try_from(Bv::ones(33)),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        u64::try_from(Bv::ones(65)),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        u128::try_from(Bv::ones(129)),
        Err(ConvertionError::NotEnoughCapacity)
    );
}

#[test]
fn from_bv_bvf() {
    bvf_inner_unroll!(try_from_bv_bvf_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
}

#[test]
fn from_bv_bvd() {
    from_inner::<Bv, Bvd>(512);
}

fn from_array_inner<B, I>(max_capacity: usize)
where
    <B as IArray>::I: StaticCast<I>,
    B: BitVector + for<'a> TryFrom<&'a [I], Error: Debug>,
    I: Integer,
{
    for length in 0..(max_capacity / I::BITS * I::BITS) {
        let bv1 = random_bv::<B>(length);
        let array: Vec<I> = (0..bv1.int_len::<I>())
            .map(|i| bv1.get_int(i).unwrap())
            .collect();
        let bv2 = B::try_from(&array[..]).unwrap();
        assert_eq!(bv1, bv2);
    }
}

fn from_bvf_array_inner<I: Integer, const N: usize>() {
    from_array_inner::<Bvf<I, N>, u8>(Bvf::<I, N>::capacity());
    from_array_inner::<Bvf<I, N>, u16>(Bvf::<I, N>::capacity());
    from_array_inner::<Bvf<I, N>, u32>(Bvf::<I, N>::capacity());
    from_array_inner::<Bvf<I, N>, u64>(Bvf::<I, N>::capacity());
    from_array_inner::<Bvf<I, N>, u128>(Bvf::<I, N>::capacity());
}

#[test]
fn from_bvf_array() {
    bvf_inner_unroll!(from_bvf_array_inner, {u8, u16, u32, u64, u128}, {1, 2, 3, 4, 5});
    assert_eq!(
        Bvf::<u8, 3>::try_from(&[1u16; 2][..]),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        Bvf::<u16, 3>::try_from(&[1u32; 2][..]),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        Bvf::<u32, 3>::try_from(&[1u64; 2][..]),
        Err(ConvertionError::NotEnoughCapacity)
    );
    assert_eq!(
        Bvf::<u64, 3>::try_from(&[1u128; 2][..]),
        Err(ConvertionError::NotEnoughCapacity)
    );
}

#[test]
fn from_bvd_array() {
    from_array_inner::<Bvd, u8>(256);
    from_array_inner::<Bvd, u16>(256);
    from_array_inner::<Bvd, u32>(256);
    from_array_inner::<Bvd, u64>(256);
    from_array_inner::<Bvd, u128>(256);
}

#[test]
fn from_bv_array() {
    from_array_inner::<Bv, u8>(256);
    from_array_inner::<Bv, u16>(256);
    from_array_inner::<Bv, u32>(256);
    from_array_inner::<Bv, u64>(256);
    from_array_inner::<Bv, u128>(256);
}