diff --git a/members/libpt-bintols/src/lib.rs b/members/libpt-bintols/src/lib.rs index ca13f78..54a907f 100644 --- a/members/libpt-bintols/src/lib.rs +++ b/members/libpt-bintols/src/lib.rs @@ -25,3 +25,4 @@ pub const YOBI: u128 = 2u128.pow(80); // use libpt_core; pub mod datalayout; pub mod display; +pub mod split_numbers; diff --git a/members/libpt-bintols/src/split_numbers.rs b/members/libpt-bintols/src/split_numbers.rs new file mode 100644 index 0000000..7b3bda2 --- /dev/null +++ b/members/libpt-bintols/src/split_numbers.rs @@ -0,0 +1,38 @@ +//! # Split numbers into bits and bytes +//! +//! 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 +/// be splitted to `vec![0b00000110, 0b10110101]`. +/// +/// The 0 bytes of the numbers will be discarded (unless the number is 0, then the Vec contains a +/// single Null byte.) and the remaining parts of the numbers are inserted into a Vec as [u8]. +/// +/// # Examples +/// +/// ``` +/// # use libpt_bintols::split_numbers::*; +/// +/// let x: u32 = 1717; +/// +/// assert_eq!(unsigned_to_vec(x), vec![0b00000110, 0b10110101]); +/// ``` +pub fn unsigned_to_vec(num: T) -> Vec +where + u128: std::convert::From, +{ + let mut num: u128 = num.into(); + if num == 0 { + return vec![0]; + } + let mut buf: Vec = Vec::new(); + while num > 0 { + buf.push(num as u8); + num >>= 8; + } + buf.reverse(); + buf +} diff --git a/members/libpt-bintols/tests/split_numbers.rs b/members/libpt-bintols/tests/split_numbers.rs new file mode 100644 index 0000000..3f461a3 --- /dev/null +++ b/members/libpt-bintols/tests/split_numbers.rs @@ -0,0 +1,55 @@ +use libpt_bintols::split_numbers::*; + +#[test] +fn split_u128() { + let source = [ + 16, + 255, + 256, + 0, + u128::MAX, + u64::MAX as u128, + u64::MAX as u128 + 1, + ]; + let correct = [ + 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!(unsigned_to_vec(*n), correct[i]); + } +} + +#[test] +fn split_u64() { + let source = [ + 16, + 255, + 256, + 0, + u64::MAX, + u32::MAX as u64, + 0b1_00000001, + 0b10011011_10110101_11110000_00110011, + ]; + let correct = [ + 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!(unsigned_to_vec(*n), correct[i]); + } +}