moa_fdt 0.1.4

FDT (Flattened Device Tree) 零拷贝解析器
Documentation
// Based on fdt 0.1.5 (MPL-2.0) by repnop, with modifications:
// - Removed BigEndianU32/BigEndianU64 newtypes, use u32/u64 directly
// - Simplified CStr

/// Null-terminated C 字符串引用
pub(crate) struct CStr<'a>(&'a [u8]);

impl<'a> CStr<'a> {
    #[inline(always)]
    pub(crate) fn new(data: &'a [u8]) -> Option<Self> {
        let end = data.iter().position(|&b| b == 0)?;
        Some(Self(&data[..end]))
    }

    #[inline(always)]
    pub(crate) fn len(&self) -> usize {
        self.0.len()
    }

    #[inline(always)]
    pub(crate) fn as_str(&self) -> Option<&'a str> {
        core::str::from_utf8(self.0).ok()
    }
}

/// 大端字节流游标
#[derive(Debug, Clone, Copy)]
pub(crate) struct FdtData<'a> {
    bytes: &'a [u8],
}

impl<'a> FdtData<'a> {
    #[inline(always)]
    pub(crate) fn new(bytes: &'a [u8]) -> Self {
        Self { bytes }
    }

    #[inline(always)]
    pub(crate) fn u32(&mut self) -> Option<u32> {
        let val = u32::from_be_bytes(self.bytes.get(..4)?.try_into().ok()?);
        self.skip(4);
        Some(val)
    }

    #[inline(always)]
    pub(crate) fn u64(&mut self) -> Option<u64> {
        let val = u64::from_be_bytes(self.bytes.get(..8)?.try_into().ok()?);
        self.skip(8);
        Some(val)
    }

    #[inline(always)]
    pub(crate) fn skip(&mut self, n: usize) {
        self.bytes = self.bytes.get(n..).unwrap_or_default();
    }

    #[inline(always)]
    pub(crate) fn remaining(&self) -> &'a [u8] {
        self.bytes
    }

    #[inline(always)]
    pub(crate) fn peek_u32(&self) -> Option<u32> {
        Some(u32::from_be_bytes(self.bytes.get(..4)?.try_into().ok()?))
    }

    #[inline(always)]
    pub(crate) fn is_empty(&self) -> bool {
        self.bytes.is_empty()
    }

    #[inline(always)]
    pub(crate) fn skip_nops(&mut self) {
        while self.peek_u32() == Some(crate::node::FDT_NOP) {
            self.skip(4);
        }
    }
}

#[inline(always)]
pub(crate) fn skip_4_aligned(stream: &mut FdtData<'_>, len: usize) {
    stream.skip((len + 3) & !0x3);
}