Compare commits

...

2 commits

Author SHA1 Message Date
58624e14db add tests for the join module #79
Some checks failed
cargo devel CI / cargo CI (push) Has been cancelled
2024-05-13 14:57:17 +02:00
b7c83107d5 feat: add a join module to join arrays into larger integers # 79 2024-05-13 14:57:17 +02:00
3 changed files with 100 additions and 0 deletions

View file

@ -0,0 +1,44 @@
//! # Join bits and bytes into numbers
//!
//! Sometimes you have a `[u8]` that is the representation of a larger unsigned integer, such as
//! [u128]. This module helps you join them together.
use anyhow::anyhow;
use libpt_log::trace;
/// Join a [Vec] of [u8]s into an unsigned integer
///
/// Say you have the array `[0b00000110, 0b10110101]` and want to use it as a [u32].
/// This function sets it together to a integer type of your choosing:
/// 1717 (binary: `00000000 00000000 00000110 10110101`).
///
/// If the array is not long enough, the number will be padded with null bytes.
///
/// # Examples
///
/// ```
/// # use libpt_bintols::join::*;
///
/// let x: [u8; 2] = [0b00000110, 0b10110101];
///
/// assert_eq!(array_to_unsigned::<u32>(&x).unwrap(), 1717);
/// ```
pub fn array_to_unsigned<T>(parts: &[u8]) -> anyhow::Result<T>
where
u128: std::convert::From<T>,
T: std::str::FromStr,
<T as std::str::FromStr>::Err: std::fmt::Debug,
{
trace!("amount of parts: {}", parts.len());
if parts.len() > (u128::BITS / 8) as usize {
return Err(anyhow!(
"the list is too long to fit into the specified integer type: {}",
std::any::type_name::<T>()
));
}
let mut ri: u128 = 0;
for (i, e) in parts.iter().rev().enumerate() {
ri += (*e as u128) * 256u128.pow(i as u32);
}
Ok(ri.to_string().parse().unwrap())
}

View file

@ -26,3 +26,4 @@ pub const YOBI: u128 = 2u128.pow(80);
pub mod datalayout; pub mod datalayout;
pub mod display; pub mod display;
pub mod split; pub mod split;
pub mod join;

View file

@ -0,0 +1,55 @@
use libpt_bintols::join::*;
#[test]
fn join_u128() {
let correct = [
16,
255,
256,
0,
u128::MAX,
u64::MAX as u128,
u64::MAX as u128 + 1,
];
let source = [
vec![16],
vec![255],
vec![1, 0],
vec![0],
vec![
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
],
vec![255, 255, 255, 255, 255, 255, 255, 255],
vec![1, 0, 0, 0, 0, 0, 0, 0, 0],
];
for (i, n) in source.iter().enumerate() {
assert_eq!(array_to_unsigned::<u128>(n).unwrap(), correct[i]);
}
}
#[test]
fn join_u64() {
let correct = [
16,
255,
256,
0,
u64::MAX,
u32::MAX as u64,
0b1_00000001,
0b10011011_10110101_11110000_00110011,
];
let source = [
vec![16],
vec![255],
vec![1, 0],
vec![0],
vec![255, 255, 255, 255, 255, 255, 255, 255],
vec![255, 255, 255, 255],
vec![1, 1],
vec![0b10011011, 0b10110101, 0b11110000, 0b00110011],
];
for (i, n) in source.iter().enumerate() {
assert_eq!(array_to_unsigned::<u64>(n).unwrap(), correct[i]);
}
}