intpack/pack.rs
1// Byte numbering: Index 0 in input slice is the most significant byte(s) in the output value
2
3// Note on casting unsigned numbers with as: Casting to smaller integer will truncate, casting to larger will zero-extend
4
5// Functions for every unsigned type to pack multiple of them into a bigger type
6
7use std::convert::TryInto;
8
9// This simply panics on fail. It shouldn't ever fail
10macro_rules! to_arr {
11 ($slice:expr) => {
12 $slice.try_into().unwrap()
13 };
14}
15
16// Base packing functions to pack to next biggest
17
18/// Packs 2 u8 values into a u16. Index 0 in input slice is the most significant byte(s) in the output value
19pub fn u8_to_u16(b: &[u8; 2]) -> u16 {
20 ((b[0] as u16) << 8)
21 | (b[1] as u16)
22}
23
24/// Packs 2 u16 values into a u32. Index 0 in input slice is the most significant byte(s) in the output value
25pub fn u16_to_u32(b: &[u16; 2]) -> u32 {
26 ((b[0] as u32) << 16)
27 | (b[1] as u32)
28}
29
30/// Packs 2 u32 values into a u64. Index 0 in input slice is the most significant byte(s) in the output value
31pub fn u32_to_u64(b: &[u32; 2]) -> u64 {
32 ((b[0] as u64) << 16)
33 | (b[1] as u64)
34}
35
36/// Packs 2 u64 values into a u128. Index 0 in input slice is the most significant byte(s) in the output value
37pub fn u64_to_u128(b: &[u64; 2]) -> u128 {
38 ((b[0] as u128) << 64)
39 | (b[1] as u128)
40}
41
42// And then extended packing functions, pack into everything bigger
43
44/// Packs 4 u8 values into a u32. Index 0 in input slice is the most significant byte(s) in the output value
45pub fn u8_to_u32(b: &[u8; 4]) -> u32 {
46 u16_to_u32(&[u8_to_u16(to_arr!(&b[0..=1])), u8_to_u16(to_arr!(&b[2..=3]))])
47}
48
49/// Packs 8 u8 values into a u64. Index 0 in input slice is the most significant byte(s) in the output value
50pub fn u8_to_u64(b: &[u8; 8]) -> u64 {
51 u32_to_u64(&[u8_to_u32(to_arr!(&b[0..=3])), u8_to_u32(to_arr!(&b[4..=8]))])
52}
53
54/// Packs 16 u8 values into a u128. Index 0 in input slice is the most significant byte(s) in the output value
55pub fn u8_to_u128(b: &[u8; 16]) -> u128 {
56 u64_to_u128(&[u8_to_u64(to_arr!(&b[0..=7])), u8_to_u64(to_arr!(&b[8..=15]))])
57}
58
59/// Packs 4 u16 values into a u64. Index 0 in input slice is the most significant byte(s) in the output value
60pub fn u16_to_u64(b: &[u16; 4]) -> u64 {
61 u32_to_u64(&[u16_to_u32(to_arr!(&b[0..=1])), u16_to_u32(to_arr!(&b[2..=3]))])
62}
63
64/// Packs 4 u16 values into a u128. Index 0 in input slice is the most significant byte(s) in the output value
65pub fn u16_to_u128(b: &[u16; 8]) -> u128 {
66 u64_to_u128(&[u16_to_u64(to_arr!(&b[0..=3])), u16_to_u64(to_arr!(&b[4..=8]))])
67}
68
69/// Packs 4 u32 values into a u128. Index 0 in input slice is the most significant byte(s) in the output value
70pub fn u32_to_u128(b: &[u32; 4]) -> u128 {
71 u64_to_u128(&[u32_to_u64(to_arr!(&b[0..=1])), u32_to_u64(to_arr!(&b[2..=3]))])
72}