anothertls/utils/
bytes.rs

1/*
2 * Copyright (c) 2023, Tobias Müller <git@tsmr.eu>
3 *
4 */
5
6use ibig::{ibig, IBig};
7
8pub fn to_ibig_le(bytes: &[u8]) -> IBig {
9    let mut res = ibig!(0);
10    for (i, byte) in bytes.iter().enumerate() {
11        res += IBig::from(*byte) << (i * 8);
12    }
13    res
14}
15pub fn to_ibig_be(bytes: &[u8]) -> IBig {
16    let mut res = ibig!(0);
17    for (i, byte) in bytes.iter().enumerate() {
18        res += IBig::from(*byte) << (((bytes.len() - 1) * 8) - i * 8);
19    }
20    res
21}
22#[derive(PartialEq)]
23pub enum ByteOrder {
24    Little,
25    Big
26}
27pub fn ibig_to_vec(num: IBig, order: ByteOrder) -> Vec<u8> {
28    let b = <ibig::UBig as std::convert::TryFrom<IBig>>::try_from(num).unwrap();
29    if order == ByteOrder::Big {
30        b.to_be_bytes()
31    } else {
32        b.to_le_bytes()
33    }
34}
35pub fn ibig_to_32bytes(num: IBig, order: ByteOrder) -> [u8; 32] {
36    let b = ibig_to_vec(num, order);
37    let mut c = [0; 32];
38    for (i, d) in b.iter().enumerate() {
39        if i >= 32 {
40            break;
41        }
42        c[i] = *d;
43    }
44    c
45}
46pub fn u128_to_bytes_be(num: u128) -> [u8; 16] {
47    let mut res = [0u8; 16];
48    for (i, r) in res.iter_mut().enumerate() {
49        *r = (num >> ((15 * 8) - i * 8)) as u8;
50    }
51    res
52}
53
54pub fn str_to_u8(s: &str) -> u8 {
55    match &s[..1] {
56        "1" => 1,
57        "2" => 2,
58        "3" => 3,
59        "4" => 4,
60        "5" => 5,
61        "6" => 6,
62        "7" => 7,
63        "8" => 8,
64        "9" => 9,
65        _ => 0
66    }
67
68}
69pub fn str_to_u16(s: &str) -> u16 {
70    ((str_to_u8(&s[..1]) as u16)*10) + str_to_u8(&s[1..2]) as u16
71}
72// pub fn to_u32(buf: &[u8]) -> u32 {
73//     if buf.is_empty() {
74//         return 0;
75//     }
76//     let mut res = buf[0] as u32;
77//     if buf.len() > 1 {
78//         res += (res << 8) | buf[1] as u32;
79//     }
80//     if buf.len() > 2 {
81//         res += (res << 8) | buf[2] as u32;
82//     }
83//     if buf.len() > 3 {
84//         res += (res << 8) | buf[3] as u32;
85//     }
86//     res
87// }
88pub fn to_u16(buf: &[u8]) -> u16 {
89    if buf.is_empty() {
90        return 0;
91    }
92    if buf.len() < 2 {
93        return buf[0] as u16;
94    }
95    ((buf[0] as u16) << 8) | buf[1] as u16
96}
97pub fn to_u128_be_fill(bytes: &[u8]) -> u128 {
98    let mut new = [0; 16];
99    let bytes: &[u8] = match bytes.len() {
100        a if a < 16 => {
101            for (i, b) in bytes.iter().enumerate() {
102                new[(16 - bytes.len()) + i] = *b;
103            }
104            &new
105        },
106        a if a > 16 => &bytes[..16],
107        _ => bytes
108    };
109    to_u128_be(bytes)
110}
111pub fn to_u128_be(bytes: &[u8]) -> u128 {
112    // if bytes.len() < 128/8 filling 0 at the END
113    let mut res: u128 = 0;
114    let bytes: &[u8] = match bytes.len() {
115        a if a > 16 => &bytes[..16],
116        _ => bytes
117    };
118    for (i, byte) in bytes.iter().enumerate() {
119        res += (*byte as u128) << ((15 * 8) - i * 8);
120    }
121    res
122}
123pub fn to_u128_le(bytes: &[u8]) -> u128 {
124    // if bytes.len() < 128/8 filling 0 at the END
125    let mut res: u128 = 0;
126    let bytes: &[u8] = match bytes.len() {
127        a if a > 16 => &bytes[..16],
128        _ => bytes
129    };
130    for (i, byte) in bytes.iter().enumerate() {
131        res += (*byte as u128) << (i * 8);
132    }
133    res
134}
135pub fn to_u64_le(bytes: &[u8]) -> u64 {
136    let mut res: u64 = 0;
137    for (i, byte) in bytes[..8].iter().enumerate() {
138        res += (*byte as u64) << ((7 * 8) - i * 8);
139    }
140    res
141}
142pub fn u64_to_bytes_le(num: u64) -> [u8; 8] {
143    let mut res = [0u8; 8];
144    for (i, r) in res.iter_mut().enumerate() {
145        *r = (num >> (i * 8)) as u8;
146    }
147    res
148}
149
150#[allow(dead_code)]
151pub fn to_hex(b: &[u8]) -> String {
152    b.iter()
153        .map(|b| format!("{b:02x}"))
154        .collect::<Vec<String>>()
155        .join("")
156}
157
158#[allow(dead_code)]
159/// Panics, use only for tests
160pub fn from_hex(s: &str) -> Vec<u8> {
161    if s.len() % 2 == 0 {
162        let a: Option<Vec<u8>> = (0..s.len())
163            .step_by(2)
164            .map(|i| {
165                s.get(i..i + 2)
166                    .and_then(|sub| u8::from_str_radix(sub, 16).ok())
167            })
168            .collect();
169        a.unwrap()
170    } else {
171        panic!("This should not happen!")
172    }
173}