1use core::{ffi::CStr, iter};
2
3use crate::{
4 base::Fdt,
5 data::{Buffer, Raw},
6 FdtError, Token,
7};
8
9#[derive(Clone)]
10pub struct Property<'a> {
11 pub name: &'a str,
12 pub(crate) data: Raw<'a>,
13}
14
15impl<'a> Property<'a> {
16 pub fn raw_value(&self) -> &'a [u8] {
17 self.data.value()
18 }
19
20 pub fn u32(&self) -> Result<u32, FdtError> {
21 self.data.buffer().take_u32()
22 }
23
24 pub fn u64(&self) -> Result<u64, FdtError> {
25 self.data.buffer().take_u64()
26 }
27
28 pub fn str(&self) -> Result<&'a str, FdtError> {
29 let res = CStr::from_bytes_until_nul(self.data.value())?.to_str()?;
30 Ok(res)
31 }
32
33 pub fn str_list(&self) -> impl Iterator<Item = &'a str> + 'a {
34 let mut value = self.data.buffer();
35 iter::from_fn(move || value.take_str().ok())
36 }
37
38 pub fn u32_list(&self) -> impl Iterator<Item = u32> + 'a {
39 let mut value = self.data.buffer();
40 iter::from_fn(move || value.take_u32().ok())
41 }
42
43 pub fn u64_list(&self) -> impl Iterator<Item = u64> + 'a {
44 let mut value = self.data.buffer();
45 iter::from_fn(move || value.take_u64().ok())
46 }
47}
48
49impl core::fmt::Debug for Property<'_> {
50 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51 write!(f, "{} = [", self.name)?;
52 for v in self.u32_list() {
53 write!(f, "{:#x}, ", v)?;
54 }
55 write!(f, "]")?;
56 Ok(())
57 }
58}
59
60pub(crate) struct PropIter<'a> {
61 fdt: Fdt<'a>,
62 reader: Buffer<'a>,
63 has_err: bool,
64}
65
66impl<'a> PropIter<'a> {
67 pub fn new(fdt: Fdt<'a>, reader: Buffer<'a>) -> Self {
68 Self {
69 fdt,
70 reader,
71 has_err: false,
72 }
73 }
74
75 fn try_next(&mut self) -> Result<Option<Property<'a>>, FdtError> {
76 loop {
77 match self.reader.take_token()? {
78 Token::Prop => break,
79 Token::Nop => {}
80 _ => return Ok(None),
81 }
82 }
83 let prop = self.reader.take_prop(&self.fdt)?;
84 Ok(Some(prop))
85 }
86}
87
88impl<'a> Iterator for PropIter<'a> {
89 type Item = Result<Property<'a>, FdtError>;
90
91 fn next(&mut self) -> Option<Self::Item> {
92 if self.has_err {
93 return None;
94 }
95 match self.try_next() {
96 Ok(Some(prop)) => Some(Ok(prop)),
97 Ok(None) => None,
98 Err(e) => {
99 self.has_err = true;
100 Some(Err(e))
101 }
102 }
103 }
104}