1use core::mem::size_of;
2use core::str::from_utf8;
3
4use crate::prelude::*;
5
6use crate::base::DevTree;
7use crate::error::DevTreeError;
8use crate::spec::Phandle;
9
10use crate::error::Result;
11
12#[cfg(doc)]
13use crate::base::DevTreeProp;
14
15pub trait PropReader<'dt> {
16 type NodeType;
17
18 #[doc(hidden)]
20 fn propbuf(&self) -> &'dt [u8];
21
22 #[doc(hidden)]
24 fn nameoff(&self) -> usize;
25
26 #[doc(hidden)]
27 fn fdt(&self) -> &DevTree<'dt>;
28
29 #[inline]
31 fn name(&self) -> Result<&'dt str> {
32 let str_offset = self.fdt().off_dt_strings() + self.nameoff();
33 let name = self.fdt().buf().read_bstring0(str_offset)?;
34 Ok(from_utf8(name)?)
35 }
36
37 #[inline]
39 #[must_use]
40 fn length(&self) -> usize {
41 self.propbuf().len()
42 }
43
44 fn node(&self) -> Self::NodeType;
46
47 #[inline]
53 fn u32(&self, index: usize) -> Result<u32> {
54 unsafe {
57 self.propbuf()
58 .unsafe_read_be_u32(index * size_of::<u32>())
59 .or(Err(DevTreeError::InvalidOffset))
60 }
61 }
62
63 #[inline]
69 fn u64(&self, index: usize) -> Result<u64> {
70 self.propbuf()
71 .read_be_u64(index * size_of::<u64>())
72 .or(Err(DevTreeError::InvalidOffset))
73 }
74
75 #[inline]
78 fn phandle(&self, index: usize) -> Result<Phandle> {
79 unsafe {
82 self.propbuf()
83 .unsafe_read_be_u32(index * size_of::<Phandle>())
84 .or(Err(DevTreeError::InvalidOffset))
85 }
86 }
87
88 #[inline]
93 fn str(&self) -> Result<&'dt str> {
94 self.iter_str().next()?.ok_or(DevTreeError::ParseError)
95 }
96
97 #[inline]
102 fn iter_str(&self) -> StringPropIter<'dt> {
103 StringPropIter::new(self.propbuf())
104 }
105 #[inline]
111 fn raw(&self) -> &'dt [u8] {
112 self.propbuf()
113 }
114}
115
116use fallible_iterator::FallibleIterator;
117
118#[derive(Debug, Clone)]
119pub struct StringPropIter<'dt> {
120 offset: usize,
121 propbuf: &'dt [u8],
122}
123
124impl<'dt> StringPropIter<'dt> {
125 fn new(propbuf: &'dt [u8]) -> Self {
126 Self { propbuf, offset: 0 }
127 }
128}
129
130impl<'dt> FallibleIterator for StringPropIter<'dt> {
131 type Error = DevTreeError;
132 type Item = &'dt str;
133
134 fn next(&mut self) -> Result<Option<Self::Item>> {
135 if self.offset == self.propbuf.len() {
136 return Ok(None);
137 }
138 if self.offset > self.propbuf.len() {
139 return Err(DevTreeError::InvalidOffset);
140 }
141
142 let u8_slice = self.propbuf.read_bstring0(self.offset)?;
143 self.offset += u8_slice.len() + 1;
145 Ok(Some(from_utf8(u8_slice)?))
146 }
147}