#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![deny(dead_code)]
#![deny(unused_imports)]
#![deny(missing_docs)]
use std::ops::{BitAnd, Shr, Shl, BitOrAssign};
use num::{Integer};
use std::convert::TryFrom;
pub fn repack<T1, T2>(src: &[T1], bits_in: usize, bits_out: usize, bits_limit: usize) -> Result<Vec<T2>, &'static str>
where
T1: BitAnd<Output = T1> + Integer + Clone + Shr<Output = T1> + TryFrom<usize>,
T2: Integer + Clone + TryFrom<T1> + BitOrAssign + TryFrom<usize> + Shl<Output = T2>,
{
if bits_in < 1 || bits_out < 1 || bits_limit < 1 {
return Err("bits_in < 1 || bits_out < 1 || bits_limit < 1");
}
let src_bit_size = std::mem::size_of_val(&T1::zero()) * 8;
if bits_in > src_bit_size {
return Err("bits_in > T1::size");
}
let dst_bit_size = std::mem::size_of_val(&T2::zero()) * 8;
if bits_out > dst_bit_size {
return Err("bits_out > T2::size");
}
if bits_limit % bits_out != 0 {
return Err("bits_limit % bits_out != 0")
}
let mut dst = vec![T2::zero(); bits_limit / bits_out];
for i in 0..bits_limit {
let src_i = i / bits_in;
let src_b = i % bits_in;
let dst_i = i / bits_out;
let dst_b = i % bits_out;
let rsh = match T1::try_from(bits_in - src_b - 1) {
Ok(v) => v,
Err(_) => return Err("can't convert usize to T1"),
};
let lsh = match T2::try_from(bits_out - dst_b - 1) {
Ok(v) => v,
Err(_) => return Err("can't convert usize to T2"),
};
let src_byte = if src_i < src.len() {
src[src_i].clone()
} else {
T1::zero()
};
let src_bit = match T2::try_from((src_byte >> rsh) & T1::one()) {
Ok(v) => v,
Err(_) => return Err("can't convert T1 to T2"),
};
dst[dst_i] |= src_bit << lsh;
}
Ok(dst)
}
#[test]
fn test1() {
let src = [0b_00101001_00010000_u16, 0b_00101001_00010000_u16];
let dst = [0b_00101001_u8, 0b_00010000_u8, 0b_00101001u8, 0b_00010000_u8];
let r: Vec<u8> = repack(&src, 16, 8, 32).unwrap();
assert_eq!(dst, r.as_slice());
}
#[test]
fn test2() {
let src = [0xFF, 0xFF];
let dst = [0u8, 0, 0, 0xFF, 0, 0, 0, 0xFF];
let r: Vec<u8> = repack(&src, 32, 8, 64).unwrap();
assert_eq!(dst, r.as_slice());
}
#[test]
#[should_panic(expected = "bits_limit % bits_out != 0")]
fn test3() {
let src = [0xFF, 0xFF];
let dst = [0u8, 0, 0, 0xFF, 0, 0, 0, 0xFF];
let r: Vec<u8> = repack(&src, 32, 7, 64).unwrap();
assert_eq!(dst, r.as_slice());
}
#[test]
#[should_panic(expected = "bits_in > T1::size")]
fn test4() {
let src = [0xFF, 0xFF];
let _: Vec<u8> = repack(&src, 256, 7, 64).unwrap();
}
#[test]
#[should_panic(expected = "bits_out > T2::size")]
fn test5() {
let src = [0xFF, 0xFF];
let _: Vec<u8> = repack(&src, 32, 16, 64).unwrap();
}
#[test]
#[should_panic(expected = "bits_in < 1 || bits_out < 1 || bits_limit < 1")]
fn test6() {
let src = [0xFF, 0xFF];
let _: Vec<u8> = repack(&src, 0, 16, 64).unwrap();
}
#[test]
#[should_panic(expected = "bits_in < 1 || bits_out < 1 || bits_limit < 1")]
fn test7() {
let src = [0xFF, 0xFF];
let _: Vec<u8> = repack(&src, 32, 0, 64).unwrap();
}
#[test]
#[should_panic(expected = "bits_in < 1 || bits_out < 1 || bits_limit < 1")]
fn test8() {
let src = [0xFF, 0xFF];
let _: Vec<u8> = repack(&src, 32, 16, 0).unwrap();
}
#[test]
fn test9() {
let src = [0b_00101001_u8, 0b_00010000_u8, 0b_00101001u8, 0b_00010000_u8];
let dst = [0b_00101001_00010000_u16, 0b_00101001_00010000_u16];
let r: Vec<u16> = repack(&src, 8, 16, 32).unwrap();
assert_eq!(dst, r.as_slice());
}
#[test]
fn test10() {
let src = [5u16, 5]; let dst = [11u8, 4]; let r: Vec<u8> = repack(&src, 3, 4, 8).unwrap();
assert_eq!(dst, r.as_slice());
}