Skip to main content

datex_core/utils/
buffers.rs

1use crate::prelude::*;
2use core::{convert::TryInto, fmt::Write, iter::FromIterator};
3use itertools::Itertools;
4
5/*
6read functions for primitive data types on a u8 array, also increments the index
7 */
8
9pub fn read_u8(buffer: &[u8], index: &mut usize) -> u8 {
10    let val = buffer[*index];
11    *index += 1;
12    val
13}
14
15pub fn read_i8(buffer: &[u8], index: &mut usize) -> i8 {
16    let slice = &buffer[*index..*index + 1];
17    *index += 1;
18    i8::from_le_bytes(slice.try_into().unwrap())
19}
20
21pub fn read_u16(buffer: &[u8], index: &mut usize) -> u16 {
22    let slice = &buffer[*index..*index + 2];
23    *index += 2;
24    u16::from_be_bytes(slice.try_into().unwrap())
25}
26pub fn read_i16(buffer: &[u8], index: &mut usize) -> i16 {
27    let slice = &buffer[*index..*index + 2];
28    *index += 2;
29    i16::from_be_bytes(slice.try_into().unwrap())
30}
31
32pub fn read_i32(buffer: &[u8], index: &mut usize) -> i32 {
33    let slice = &buffer[*index..*index + 4];
34    *index += 4;
35    i32::from_be_bytes(slice.try_into().unwrap())
36}
37pub fn read_u32(buffer: &[u8], index: &mut usize) -> u32 {
38    let slice = &buffer[*index..*index + 4];
39    *index += 4;
40    u32::from_be_bytes(slice.try_into().unwrap())
41}
42
43pub fn read_u64(buffer: &[u8], index: &mut usize) -> u64 {
44    let slice = &buffer[*index..*index + 8];
45    *index += 8;
46    u64::from_be_bytes(slice.try_into().unwrap())
47}
48pub fn read_i64(buffer: &[u8], index: &mut usize) -> i64 {
49    let slice = &buffer[*index..*index + 8];
50    *index += 8;
51    i64::from_be_bytes(slice.try_into().unwrap())
52}
53
54pub fn read_f64(buffer: &[u8], index: &mut usize) -> f64 {
55    let slice = &buffer[*index..*index + 8];
56    *index += 8;
57    f64::from_be_bytes(slice.try_into().unwrap())
58}
59
60pub fn read_string_utf8(
61    buffer: &[u8],
62    index: &mut usize,
63    size: usize,
64) -> String {
65    // end is min(index+size, buffer len)
66    let end = if *index + size > buffer.len() {
67        buffer.len()
68    } else {
69        *index + size
70    };
71    let slice = &buffer[*index..end];
72    *index = end;
73    String::from_utf8(slice.to_vec())
74        .unwrap_or("⎣INVALID UTF8 STRING⎤".to_string())
75}
76
77pub fn read_vec_slice(
78    buffer: &[u8],
79    index: &mut usize,
80    size: usize,
81) -> Vec<u8> {
82    let slice = &buffer[*index..*index + size];
83    *index += size;
84    slice.to_vec()
85}
86
87pub fn read_slice<'a, const SIZE: usize>(
88    buffer: &'a [u8],
89    index: &mut usize,
90) -> &'a [u8; SIZE] {
91    let slice = &buffer[*index..*index + SIZE];
92    *index += SIZE;
93    slice.try_into().unwrap()
94}
95
96/*
97write functions: set value at specific index in byte vector, vector length must be big enough
98append functions: appends the value at the end of the byte vector, automatically increases size
99 */
100
101pub fn write_u8(buffer: &mut [u8], index: &mut usize, val: u8) {
102    buffer[*index] = val;
103    *index += 1;
104}
105pub fn append_u8(buffer: &mut Vec<u8>, val: u8) {
106    buffer.extend_from_slice(&[val]);
107}
108pub fn write_i8(buffer: &mut [u8], index: &mut usize, val: i8) {
109    let bytes = val.to_le_bytes();
110    for b in bytes {
111        buffer[*index] = b;
112        *index += 1;
113    }
114}
115pub fn append_i8(buffer: &mut Vec<u8>, val: i8) {
116    buffer.extend_from_slice(&val.to_le_bytes());
117}
118
119pub fn write_u16(buffer: &mut [u8], index: &mut usize, val: u16) {
120    let bytes = val.to_le_bytes();
121    for b in bytes {
122        buffer[*index] = b;
123        *index += 1;
124    }
125}
126pub fn write_u32(buffer: &mut [u8], index: &mut usize, val: u32) {
127    let bytes = val.to_le_bytes();
128    for b in bytes {
129        buffer[*index] = b;
130        *index += 1;
131    }
132}
133
134pub fn set_bit(buffer: &mut [u8], byte_index: usize, bit_position: u8) {
135    buffer[byte_index] |= 1 << bit_position;
136}
137
138pub fn clear_bit(buffer: &mut [u8], byte_index: usize, bit_position: u8) {
139    if byte_index < buffer.len() && bit_position < 8 {
140        buffer[byte_index] &= !(1 << bit_position);
141    }
142}
143
144pub fn toggle_bit(buffer: &mut [u8], byte_index: usize, bit_position: u8) {
145    if byte_index < buffer.len() && bit_position < 8 {
146        buffer[byte_index] ^= 1 << bit_position;
147    }
148}
149
150// TODO #161
151// pub fn write_int<T: PrimInt>(buffer: &mut Vec<u8>, mut index: usize, val: T) {
152//     let bytes = val.to_u128().unwrap().to_le_bytes();
153//     for b in bytes {
154//         buffer[index] = b;
155//         index += 1;
156//     }
157// }
158
159pub fn append_u16(buffer: &mut Vec<u8>, val: u16) {
160    buffer.extend_from_slice(&val.to_le_bytes());
161}
162pub fn write_i16(buffer: &mut [u8], index: &mut usize, val: i16) {
163    let bytes = val.to_le_bytes();
164    for b in bytes {
165        buffer[*index] = b;
166        *index += 1;
167    }
168}
169pub fn append_i16(buffer: &mut Vec<u8>, val: i16) {
170    buffer.extend_from_slice(&val.to_le_bytes());
171}
172
173pub fn append_u32(buffer: &mut Vec<u8>, val: u32) {
174    buffer.extend_from_slice(&val.to_le_bytes());
175}
176pub fn write_i32(buffer: &mut [u8], index: &mut usize, val: i32) {
177    let bytes = val.to_le_bytes();
178    for b in bytes {
179        buffer[*index] = b;
180        *index += 1;
181    }
182}
183pub fn append_i32(buffer: &mut Vec<u8>, val: i32) {
184    buffer.extend_from_slice(&val.to_le_bytes());
185}
186
187pub fn write_u64(buffer: &mut [u8], index: &mut usize, val: u64) {
188    let bytes = val.to_le_bytes();
189    for b in bytes {
190        buffer[*index] = b;
191        *index += 1;
192    }
193}
194pub fn append_u64(buffer: &mut Vec<u8>, val: u64) {
195    buffer.extend_from_slice(&val.to_le_bytes());
196}
197pub fn write_i64(buffer: &mut [u8], index: &mut usize, val: i64) {
198    let bytes = val.to_le_bytes();
199    for b in bytes {
200        buffer[*index] = b;
201        *index += 1;
202    }
203}
204pub fn append_i64(buffer: &mut Vec<u8>, val: i64) {
205    buffer.extend_from_slice(&val.to_le_bytes());
206}
207pub fn append_i128(buffer: &mut Vec<u8>, val: i128) {
208    buffer.extend_from_slice(&val.to_le_bytes());
209}
210pub fn append_u128(buffer: &mut Vec<u8>, val: u128) {
211    buffer.extend_from_slice(&val.to_le_bytes());
212}
213
214pub fn write_f64(buffer: &mut [u8], index: &mut usize, val: f64) {
215    let bytes = val.to_le_bytes();
216    for b in bytes {
217        buffer[*index] = b;
218        *index += 1;
219    }
220}
221pub fn append_f64(buffer: &mut Vec<u8>, val: f64) {
222    buffer.extend_from_slice(&val.to_le_bytes());
223}
224
225pub fn append_f32(buffer: &mut Vec<u8>, val: f32) {
226    buffer.extend_from_slice(&val.to_le_bytes());
227}
228
229pub fn append_string_utf8(buffer: &mut Vec<u8>, val: &str) {
230    buffer.extend_from_slice(val.as_bytes());
231}
232
233// hex - buffer conversions
234
235pub fn buffer_to_hex(buffer: Vec<u8>) -> String {
236    let n = buffer.len();
237
238    let mut s = String::with_capacity(2 * n);
239    for byte in buffer {
240        core::write!(s, "{byte:02X}").expect("could not parse buffer")
241    }
242    s
243}
244
245/**
246 * seperator: char sequence inserted between each byte
247 * pad_size_bytes: if 0, it is ignored
248 * x_shorthand: collapse multiple 0 bytes to "xC", with C being the number of zero bytes
249 */
250pub fn buffer_to_hex_advanced(
251    buffer: Vec<u8>,
252    seperator: &str,
253    pad_size_bytes: usize,
254    x_shorthand: bool,
255) -> String {
256    let n = if pad_size_bytes == 0 {
257        buffer.len()
258    } else {
259        pad_size_bytes
260    };
261
262    let buf_len = buffer.len();
263
264    let mut s = String::with_capacity(2 * n);
265    let mut i = 0;
266    while i < n {
267        // next byte
268        let byte = if i < buf_len { buffer[i] } else { 0 };
269        i += 1;
270        // multiple (>=2) zero bytes - x shorthand
271        if x_shorthand
272            && byte == 0
273            && i < n
274            && if i < buf_len { buffer[i] } else { 0 } == 0
275        {
276            let mut zero_count: u8 = 2;
277            let initial_i = i;
278            while i + 1 < n && buffer[i + 1] == 0 {
279                i += 1;
280                zero_count += 1;
281            }
282            // 0 count, max 15
283            if zero_count <= 0xf {
284                i += 1;
285                core::write!(s, "x{zero_count:01X}")
286                    .expect("could not parse buffer");
287            } else {
288                i = initial_i;
289                core::write!(s, "{byte:02X}").expect("could not parse buffer");
290            }
291        }
292        // normal
293        else {
294            core::write!(s, "{byte:02X}").expect("could not parse buffer");
295        }
296
297        // seperator?
298        if !seperator.is_empty() && i < n {
299            s += seperator;
300        }
301    }
302
303    s
304}
305
306pub fn hex_to_buffer(hex: String) -> Vec<u8> {
307    let mut buffer = Vec::<u8>::new();
308
309    for chunk in &hex.chars().chunks(2) {
310        buffer.push(
311            u8::from_str_radix(&String::from_iter(chunk), 16)
312                .expect("invalid hex buffer"),
313        );
314    }
315
316    buffer
317}
318
319pub fn hex_to_buffer_advanced(hex: String, seperator: &str) -> Vec<u8> {
320    let mut buffer = Vec::<u8>::new();
321
322    let raw_hex = hex.replace(seperator, "");
323
324    for chunk in &raw_hex.chars().chunks(2) {
325        let part = &String::from_iter(chunk);
326        if part.starts_with("x") {
327            let count = u8::from_str_radix(part.split_at(1).1, 16)
328                .expect("invalid x shortcut");
329            for _i in 0..count {
330                buffer.push(0);
331            }
332        } else {
333            buffer.push(
334                u8::from_str_radix(part, 16).expect("invalid hex buffer"),
335            );
336        }
337    }
338
339    buffer
340}
341
342#[cfg(test)]
343mod tests {
344    use super::{
345        buffer_to_hex, buffer_to_hex_advanced, hex_to_buffer,
346        hex_to_buffer_advanced,
347    };
348    use crate::prelude::*;
349
350    /**
351     * test byte array to hex string conversion, including seperator characters and fixed length padding
352     */
353    #[test]
354    pub fn buffer_to_hex_tests() {
355        assert_eq!(buffer_to_hex_advanced(vec![], "_", 0, true), "");
356        assert_eq!(
357            buffer_to_hex_advanced(vec![0x00, 0x00, 0x00], "", 0, true),
358            "x3"
359        );
360        assert_eq!(
361            buffer_to_hex_advanced(
362                vec![
363                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364                    0x00, 0x00, 0x00, 0x00, 0x00
365                ],
366                "",
367                0,
368                true
369            ),
370            "xF"
371        );
372        assert_eq!(
373            buffer_to_hex_advanced(
374                vec![
375                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa
377                ],
378                "",
379                0,
380                true
381            ),
382            "00xFAA"
383        );
384        assert_eq!(buffer_to_hex(vec![0xaa, 0xbb, 0xcc, 0x00]), "AABBCC00");
385        assert_eq!(
386            buffer_to_hex_advanced(vec![0xaa, 0xbb, 0xcc, 0x00], "-", 0, false),
387            "AA-BB-CC-00"
388        );
389        assert_eq!(
390            buffer_to_hex_advanced(
391                vec![0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x01],
392                "_",
393                0,
394                false
395            ),
396            "AA_BB_CC_00_00_00_00_01"
397        );
398        assert_eq!(
399            buffer_to_hex_advanced(
400                vec![0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x01],
401                "_",
402                0,
403                true
404            ),
405            "AA_BB_CC_x4_01"
406        );
407
408        assert_eq!(
409            buffer_to_hex_advanced(vec![0xaa, 0xbb], "-", 4, true),
410            "AA-BB-x2"
411        );
412        assert_eq!(
413            buffer_to_hex_advanced(vec![0xaa, 0xbb, 0xcc], "-", 6, false),
414            "AA-BB-CC-00-00-00"
415        );
416        assert_eq!(
417            buffer_to_hex_advanced(vec![0xaa, 0xbb, 0xcc, 0xdd], "-", 2, false),
418            "AA-BB"
419        );
420    }
421
422    /**
423     * test hex string to byte array conversion, and conversion back to hex string
424     */
425    #[test]
426    pub fn hex_to_buffer_tests() {
427        assert_eq!(hex_to_buffer(buffer_to_hex(vec![0x1])), vec![0x1]);
428        assert_eq!(
429            hex_to_buffer(buffer_to_hex(vec![0xaa, 0xbb, 0xcc, 0x00])),
430            vec![0xaa, 0xbb, 0xcc, 0x00]
431        );
432
433        assert_eq!(buffer_to_hex(hex_to_buffer("".to_string())), "");
434        assert_eq!(
435            buffer_to_hex(hex_to_buffer("AABB1122".to_string())),
436            "AABB1122"
437        );
438        assert_eq!(
439            buffer_to_hex(hex_to_buffer_advanced(
440                "AA-BB-11-22".to_string(),
441                "-"
442            )),
443            "AABB1122"
444        );
445        assert_eq!(
446            buffer_to_hex_advanced(
447                hex_to_buffer_advanced("AA-BB-11-22".to_string(), "-"),
448                "-",
449                0,
450                false
451            ),
452            "AA-BB-11-22"
453        );
454
455        assert_eq!(
456            hex_to_buffer_advanced("AA-BB-11-22".to_string(), "-"),
457            vec![0xAA, 0xBB, 0x11, 0x22]
458        );
459        assert_eq!(
460            hex_to_buffer_advanced("AABB1122".to_string(), ""),
461            vec![0xAA, 0xBB, 0x11, 0x22]
462        );
463    }
464}