devicetree/
utils.rs

1use core::{
2    mem::discriminant,
3    ffi::CStr
4};
5use alloc::{
6    vec::Vec,
7    string::String
8};
9
10/// Pop the first n-bytes from input, and return it
11/// 
12/// Returns None and does not modify the slice if the given length is out of bounds.
13pub(crate) fn pop_slice<'a>(input: &mut &'a [u8], len: usize) -> Option<&'a [u8]> {
14    input.take(..len)
15}
16
17/// Read from a slice as a u32 in big endian
18/// 
19/// Note: After read, the input will point to unread position
20pub(crate) fn take_be_u32(input: &mut &[u8]) -> Option<u32> {
21    Some(u32::from_be_bytes(pop_slice(input, 4)?.try_into().unwrap()))
22}
23
24/// Read from a slice as a u64 in big endian
25/// 
26/// Note: After read, the input will point to unread position
27pub(crate) fn take_be_u64(input: &mut &[u8]) -> Option<u64> {
28    Some(u64::from_be_bytes(pop_slice(input, 8)?.try_into().unwrap()))
29}
30
31/// Read first 4 bytes from a slice as a u32 in big endian
32pub(crate) fn read_first_be_u32(input: &[u8]) -> Option<u32> {
33    Some(u32::from_be_bytes(input.get(..4)?.try_into().unwrap()))
34}
35
36/// Read first 8 bytes from a slice as a u64 in big endian
37pub(crate) fn read_first_be_u64(input: &[u8]) -> Option<u64> {
38    Some(u64::from_be_bytes(input.get(..8)?.try_into().unwrap()))
39}
40
41pub(crate) fn take_utf8_until_nul_aligned<'a>(input: &mut &'a [u8], align: usize) -> Option<&'a str> {
42    let c_str = CStr::from_bytes_until_nul(input).unwrap();
43
44    let str = c_str.to_str().unwrap();
45
46    let len = c_str.to_bytes_with_nul().len();
47
48    if align != 0 {
49        pop_slice(input, len + (align - (len % align)) % align)?;
50    } else {
51        pop_slice(input, len)?;
52    }
53
54    Some(str)
55}
56
57pub(crate) fn take_utf8_until_nul<'a>(input: &mut &'a [u8]) -> Option<&'a str> {
58    let c_str = CStr::from_bytes_until_nul(input).unwrap();
59
60    let str = c_str.to_str().unwrap();
61
62    let len = c_str.to_bytes_with_nul().len();
63
64    pop_slice(input, len)?;
65
66    Some(str)
67}
68
69pub(crate) fn take_aligned<'a>(input: &mut &'a [u8], len: usize, align: usize) -> Option<&'a [u8]> {
70    pop_slice(input, len + (align - (len % align)) % align)?.get(..len)
71}
72
73/// A function that compares two enums by their variant
74/// 
75/// Returns true if both enums are same variant
76pub(crate) fn variant_eq<T>(a: &T, b: &T) -> bool {
77	discriminant(a) == discriminant(b)
78}
79
80/// A function that print vector of strings in the form '<String1>', '<String2>'
81pub(crate) fn vec_strings_fmt(v: &Vec<String>) -> String {
82	let v_fmt: Vec<String> = v.iter().map(|i| format!("'{}'", i)).collect();
83
84	v_fmt.join(", ")
85}