datex_core/utils/
buffers.rs

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