use core::mem::size_of;
use core::str::from_utf8;
use crate::prelude::*;
use crate::base::DevTree;
use crate::error::DevTreeError;
use crate::spec::Phandle;
use crate::error::Result;
#[cfg(doc)]
use crate::base::DevTreeProp;
pub trait PropReader<'dt> {
type NodeType;
#[doc(hidden)]
fn propbuf(&self) -> &'dt [u8];
#[doc(hidden)]
fn nameoff(&self) -> usize;
#[doc(hidden)]
fn fdt(&self) -> &DevTree<'dt>;
#[inline]
fn name(&self) -> Result<&'dt str> {
let str_offset = self.fdt().off_dt_strings() + self.nameoff();
let name = self.fdt().buf().read_bstring0(str_offset)?;
Ok(from_utf8(name)?)
}
#[inline]
#[must_use]
fn length(&self) -> usize {
self.propbuf().len()
}
fn node(&self) -> Self::NodeType;
#[inline]
fn u32(&self, index: usize) -> Result<u32> {
unsafe {
self.propbuf()
.unsafe_read_be_u32(index * size_of::<u32>())
.or(Err(DevTreeError::InvalidOffset))
}
}
#[inline]
fn u64(&self, index: usize) -> Result<u64> {
self.propbuf()
.read_be_u64(index * size_of::<u64>())
.or(Err(DevTreeError::InvalidOffset))
}
#[inline]
fn phandle(&self, index: usize) -> Result<Phandle> {
unsafe {
self.propbuf()
.unsafe_read_be_u32(index * size_of::<Phandle>())
.or(Err(DevTreeError::InvalidOffset))
}
}
#[inline]
fn str(&self) -> Result<&'dt str> {
self.iter_str().next()?.ok_or(DevTreeError::ParseError)
}
#[inline]
fn iter_str(&self) -> StringPropIter<'dt> {
StringPropIter::new(self.propbuf())
}
#[inline]
fn raw(&self) -> &'dt [u8] {
self.propbuf()
}
}
use fallible_iterator::FallibleIterator;
#[derive(Debug, Clone)]
pub struct StringPropIter<'dt> {
offset: usize,
propbuf: &'dt [u8],
}
impl<'dt> StringPropIter<'dt> {
fn new(propbuf: &'dt [u8]) -> Self {
Self { propbuf, offset: 0 }
}
}
impl<'dt> FallibleIterator for StringPropIter<'dt> {
type Error = DevTreeError;
type Item = &'dt str;
fn next(&mut self) -> Result<Option<Self::Item>> {
if self.offset == self.propbuf.len() {
return Ok(None);
}
if self.offset > self.propbuf.len() {
return Err(DevTreeError::InvalidOffset);
}
let u8_slice = self.propbuf.read_bstring0(self.offset)?;
self.offset += u8_slice.len() + 1;
Ok(Some(from_utf8(u8_slice)?))
}
}