datex_core/utils/
buffers.rs

1use byteorder::{LittleEndian, ReadBytesExt};
2use core::fmt::Write;
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 mut slice = &buffer[*index..*index + 1];
17    *index += 1;
18    slice.read_i8().unwrap()
19}
20
21pub fn read_u16(buffer: &[u8], index: &mut usize) -> u16 {
22    let mut slice = &buffer[*index..*index + 2];
23    *index += 2;
24    slice.read_u16::<LittleEndian>().unwrap()
25}
26pub fn read_i16(buffer: &[u8], index: &mut usize) -> i16 {
27    let mut slice = &buffer[*index..*index + 2];
28    *index += 2;
29    slice.read_i16::<LittleEndian>().unwrap()
30}
31
32pub fn read_i32(buffer: &[u8], index: &mut usize) -> i32 {
33    let mut slice = &buffer[*index..*index + 4];
34    *index += 4;
35    slice.read_i32::<LittleEndian>().unwrap()
36}
37pub fn read_u32(buffer: &[u8], index: &mut usize) -> u32 {
38    let mut slice = &buffer[*index..*index + 4];
39    *index += 4;
40    slice.read_u32::<LittleEndian>().unwrap()
41}
42
43pub fn read_u64(buffer: &[u8], index: &mut usize) -> u64 {
44    let mut slice = &buffer[*index..*index + 8];
45    *index += 8;
46    slice.read_u64::<LittleEndian>().unwrap()
47}
48pub fn read_i64(buffer: &[u8], index: &mut usize) -> i64 {
49    let mut slice = &buffer[*index..*index + 8];
50    *index += 8;
51    slice.read_i64::<LittleEndian>().unwrap()
52}
53
54pub fn read_f64(buffer: &[u8], index: &mut usize) -> f64 {
55    let mut slice = &buffer[*index..*index + 8];
56    *index += 8;
57    slice.read_f64::<LittleEndian>().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        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                write!(s, "x{zero_count:01X}").expect("could not parse buffer");
286            } else {
287                i = initial_i;
288                write!(s, "{byte:02X}").expect("could not parse buffer");
289            }
290        }
291        // normal
292        else {
293            write!(s, "{byte:02X}").expect("could not parse buffer");
294        }
295
296        // seperator?
297        if !seperator.is_empty() && i < n {
298            s += seperator;
299        }
300    }
301
302    s
303}
304
305pub fn hex_to_buffer(hex: String) -> Vec<u8> {
306    let mut buffer = Vec::<u8>::new();
307
308    for chunk in &hex.chars().chunks(2) {
309        buffer.push(
310            u8::from_str_radix(&String::from_iter(chunk), 16)
311                .expect("invalid hex buffer"),
312        );
313    }
314
315    buffer
316}
317
318pub fn hex_to_buffer_advanced(hex: String, seperator: &str) -> Vec<u8> {
319    let mut buffer = Vec::<u8>::new();
320
321    let raw_hex = hex.replace(seperator, "");
322
323    for chunk in &raw_hex.chars().chunks(2) {
324        let part = &String::from_iter(chunk);
325        if part.starts_with("x") {
326            let count = u8::from_str_radix(part.split_at(1).1, 16)
327                .expect("invalid x shortcut");
328            for _i in 0..count {
329                buffer.push(0);
330            }
331        } else {
332            buffer.push(
333                u8::from_str_radix(part, 16).expect("invalid hex buffer"),
334            );
335        }
336    }
337
338    buffer
339}
340
341#[cfg(test)]
342mod tests {
343    use super::{
344        buffer_to_hex, buffer_to_hex_advanced, hex_to_buffer,
345        hex_to_buffer_advanced,
346    };
347
348    /**
349     * test byte array to hex string conversion, including seperator characters and fixed length padding
350     */
351    #[test]
352    pub fn buffer_to_hex_tests() {
353        assert_eq!(buffer_to_hex_advanced(vec![], "_", 0, true), "");
354        assert_eq!(
355            buffer_to_hex_advanced(vec![0x00, 0x00, 0x00], "", 0, true),
356            "x3"
357        );
358        assert_eq!(
359            buffer_to_hex_advanced(
360                vec![
361                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362                    0x00, 0x00, 0x00, 0x00, 0x00
363                ],
364                "",
365                0,
366                true
367            ),
368            "xF"
369        );
370        assert_eq!(
371            buffer_to_hex_advanced(
372                vec![
373                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa
375                ],
376                "",
377                0,
378                true
379            ),
380            "00xFAA"
381        );
382        assert_eq!(buffer_to_hex(vec![0xaa, 0xbb, 0xcc, 0x00]), "AABBCC00");
383        assert_eq!(
384            buffer_to_hex_advanced(vec![0xaa, 0xbb, 0xcc, 0x00], "-", 0, false),
385            "AA-BB-CC-00"
386        );
387        assert_eq!(
388            buffer_to_hex_advanced(
389                vec![0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x01],
390                "_",
391                0,
392                false
393            ),
394            "AA_BB_CC_00_00_00_00_01"
395        );
396        assert_eq!(
397            buffer_to_hex_advanced(
398                vec![0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x01],
399                "_",
400                0,
401                true
402            ),
403            "AA_BB_CC_x4_01"
404        );
405
406        assert_eq!(
407            buffer_to_hex_advanced(vec![0xaa, 0xbb], "-", 4, true),
408            "AA-BB-x2"
409        );
410        assert_eq!(
411            buffer_to_hex_advanced(vec![0xaa, 0xbb, 0xcc], "-", 6, false),
412            "AA-BB-CC-00-00-00"
413        );
414        assert_eq!(
415            buffer_to_hex_advanced(vec![0xaa, 0xbb, 0xcc, 0xdd], "-", 2, false),
416            "AA-BB"
417        );
418    }
419
420    /**
421     * test hex string to byte array conversion, and conversion back to hex string
422     */
423    #[test]
424    pub fn hex_to_buffer_tests() {
425        assert_eq!(hex_to_buffer(buffer_to_hex(vec![0x1])), vec![0x1]);
426        assert_eq!(
427            hex_to_buffer(buffer_to_hex(vec![0xaa, 0xbb, 0xcc, 0x00])),
428            vec![0xaa, 0xbb, 0xcc, 0x00]
429        );
430
431        assert_eq!(buffer_to_hex(hex_to_buffer("".to_string())), "");
432        assert_eq!(
433            buffer_to_hex(hex_to_buffer("AABB1122".to_string())),
434            "AABB1122"
435        );
436        assert_eq!(
437            buffer_to_hex(hex_to_buffer_advanced(
438                "AA-BB-11-22".to_string(),
439                "-"
440            )),
441            "AABB1122"
442        );
443        assert_eq!(
444            buffer_to_hex_advanced(
445                hex_to_buffer_advanced("AA-BB-11-22".to_string(), "-"),
446                "-",
447                0,
448                false
449            ),
450            "AA-BB-11-22"
451        );
452
453        assert_eq!(
454            hex_to_buffer_advanced("AA-BB-11-22".to_string(), "-"),
455            vec![0xAA, 0xBB, 0x11, 0x22]
456        );
457        assert_eq!(
458            hex_to_buffer_advanced("AABB1122".to_string(), ""),
459            vec![0xAA, 0xBB, 0x11, 0x22]
460        );
461    }
462}