From 2e38597a7cc8705414a27bd393a4302670b02108 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Mon, 13 May 2024 14:56:37 +0200 Subject: [PATCH 1/4] feat: add a join module to join arrays into larger integers #79 --- members/libpt-bintols/src/join.rs | 44 +++++++++++++++++++++++++++++++ members/libpt-bintols/src/lib.rs | 1 + 2 files changed, 45 insertions(+) create mode 100644 members/libpt-bintols/src/join.rs diff --git a/members/libpt-bintols/src/join.rs b/members/libpt-bintols/src/join.rs new file mode 100644 index 0000000..35efcd7 --- /dev/null +++ b/members/libpt-bintols/src/join.rs @@ -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::(&x).unwrap(), 1717); +/// ``` +pub fn array_to_unsigned(parts: &[u8]) -> anyhow::Result +where + u128: std::convert::From, + T: 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::() + )); + } + 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()) +} diff --git a/members/libpt-bintols/src/lib.rs b/members/libpt-bintols/src/lib.rs index 30dec09..1680664 100644 --- a/members/libpt-bintols/src/lib.rs +++ b/members/libpt-bintols/src/lib.rs @@ -26,3 +26,4 @@ pub const YOBI: u128 = 2u128.pow(80); pub mod datalayout; pub mod display; pub mod split; +pub mod join; From 3ef1ffc33722c68646afd5261715347ced089a00 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Mon, 13 May 2024 14:56:47 +0200 Subject: [PATCH 2/4] test: add tests for the join module #79 --- members/libpt-bintols/tests/join.rs | 55 +++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 members/libpt-bintols/tests/join.rs diff --git a/members/libpt-bintols/tests/join.rs b/members/libpt-bintols/tests/join.rs new file mode 100644 index 0000000..35a76c7 --- /dev/null +++ b/members/libpt-bintols/tests/join.rs @@ -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::(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::(n).unwrap(), correct[i]); + } +} From 53e545832c3ab1c2219a1a135aa816e59475816a Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Mon, 13 May 2024 12:59:44 +0000 Subject: [PATCH 3/4] automatic cargo CI changes --- members/libpt-bintols/src/lib.rs | 2 +- members/libpt-bintols/src/split.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/members/libpt-bintols/src/lib.rs b/members/libpt-bintols/src/lib.rs index 1680664..e69706c 100644 --- a/members/libpt-bintols/src/lib.rs +++ b/members/libpt-bintols/src/lib.rs @@ -25,5 +25,5 @@ pub const YOBI: u128 = 2u128.pow(80); // use libpt_core; pub mod datalayout; pub mod display; -pub mod split; pub mod join; +pub mod split; diff --git a/members/libpt-bintols/src/split.rs b/members/libpt-bintols/src/split.rs index c996ef7..3fb3a7d 100644 --- a/members/libpt-bintols/src/split.rs +++ b/members/libpt-bintols/src/split.rs @@ -3,7 +3,6 @@ //! Sometimes, you need a large integer in the form of many bytes, so split into [u8]. //! Rust provides - /// Split unsigned integers into a [Vec] of [u8]s /// /// Say you have the [u32] 1717 (binary: `00000000 00000000 00000110 10110101 `). This number would @@ -23,7 +22,7 @@ /// ``` pub fn unsigned_to_vec(num: T) -> Vec where - u128: std::convert::From + u128: std::convert::From, { let mut num: u128 = num.into(); if num == 0 { From 7928423d6e2c4c6bbc5ac2320d80d0dc87a05c3d Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Mon, 13 May 2024 15:13:35 +0200 Subject: [PATCH 4/4] refactor(bintols-join): return err if the result cannot be converted to T #80 #79 --- members/libpt-bintols/src/join.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/members/libpt-bintols/src/join.rs b/members/libpt-bintols/src/join.rs index 35efcd7..96c8e6e 100644 --- a/members/libpt-bintols/src/join.rs +++ b/members/libpt-bintols/src/join.rs @@ -27,7 +27,13 @@ pub fn array_to_unsigned(parts: &[u8]) -> anyhow::Result where u128: std::convert::From, T: std::str::FromStr, + T: std::convert::TryFrom, ::Err: std::fmt::Debug, + ::Err: std::error::Error, + >::Error: std::error::Error, + >::Error: std::marker::Send, + >::Error: std::marker::Sync, + >::Error: 'static, { trace!("amount of parts: {}", parts.len()); if parts.len() > (u128::BITS / 8) as usize { @@ -40,5 +46,5 @@ where for (i, e) in parts.iter().rev().enumerate() { ri += (*e as u128) * 256u128.pow(i as u32); } - Ok(ri.to_string().parse().unwrap()) + T::try_from(ri).map_err(anyhow::Error::from) }