fdt-parser 0.5.1

A crate for parsing FDT
Documentation
use core::{ffi::CStr, iter};

use crate::{
    base::Fdt,
    data::{Buffer, Raw},
    FdtError, Token,
};

#[derive(Clone)]
pub struct Property<'a> {
    pub name: &'a str,
    pub(crate) data: Raw<'a>,
}

impl<'a> Property<'a> {
    pub fn raw_value(&self) -> &'a [u8] {
        self.data.value()
    }

    pub fn u32(&self) -> Result<u32, FdtError> {
        self.data.buffer().take_u32()
    }

    pub fn u64(&self) -> Result<u64, FdtError> {
        self.data.buffer().take_u64()
    }

    pub fn str(&self) -> Result<&'a str, FdtError> {
        let res = CStr::from_bytes_until_nul(self.data.value())?.to_str()?;
        Ok(res)
    }

    pub fn str_list(&self) -> impl Iterator<Item = &'a str> + 'a {
        let mut value = self.data.buffer();
        iter::from_fn(move || value.take_str().ok())
    }

    pub fn u32_list(&self) -> impl Iterator<Item = u32> + 'a {
        let mut value = self.data.buffer();
        iter::from_fn(move || value.take_u32().ok())
    }

    pub fn u64_list(&self) -> impl Iterator<Item = u64> + 'a {
        let mut value = self.data.buffer();
        iter::from_fn(move || value.take_u64().ok())
    }
}

impl core::fmt::Debug for Property<'_> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{} = [", self.name)?;
        for v in self.u32_list() {
            write!(f, "{:#x}, ", v)?;
        }
        write!(f, "]")?;
        Ok(())
    }
}

pub(crate) struct PropIter<'a> {
    fdt: Fdt<'a>,
    reader: Buffer<'a>,
    has_err: bool,
}

impl<'a> PropIter<'a> {
    pub fn new(fdt: Fdt<'a>, reader: Buffer<'a>) -> Self {
        Self {
            fdt,
            reader,
            has_err: false,
        }
    }

    fn try_next(&mut self) -> Result<Option<Property<'a>>, FdtError> {
        loop {
            match self.reader.take_token()? {
                Token::Prop => break,
                Token::Nop => {}
                _ => return Ok(None),
            }
        }
        let prop = self.reader.take_prop(&self.fdt)?;
        Ok(Some(prop))
    }
}

impl<'a> Iterator for PropIter<'a> {
    type Item = Result<Property<'a>, FdtError>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.has_err {
            return None;
        }
        match self.try_next() {
            Ok(Some(prop)) => Some(Ok(prop)),
            Ok(None) => None,
            Err(e) => {
                self.has_err = true;
                Some(Err(e))
            }
        }
    }
}