dtb_walker/property/
str.rs1use super::{Error, Result as Res};
2use crate::StructureBlock;
3use core::{fmt, slice, str};
4
5#[derive(Clone)]
6pub struct Str<'a>(pub(super) &'a [u8]);
7
8impl<'a> Str<'a> {
9 #[inline]
10 pub(super) fn new(value: &'a [StructureBlock], len: usize) -> Res<Self> {
11 let buf = unsafe { slice::from_raw_parts(value.as_ptr().cast(), len) };
12 if let Some(b'\0') = buf.last().copied() {
13 Ok(Self(&buf[..buf.len() - 1]))
14 } else {
15 Err(Error)
16 }
17 }
18}
19
20impl Str<'_> {
21 #[inline]
22 pub fn as_bytes(&self) -> &[u8] {
23 self.0
24 }
25
26 #[inline]
27 pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
28 str::from_utf8(self.0)
29 }
30
31 #[inline]
37 pub unsafe fn as_str_unchecked(&self) -> &str {
38 str::from_utf8_unchecked(self.0)
39 }
40}
41
42impl fmt::Display for Str<'_> {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 '"'.fmt(f)?;
45 unsafe { self.as_str_unchecked() }.fmt(f)?;
46 '"'.fmt(f)
47 }
48}
49
50#[derive(Clone)]
51pub struct StrList<'a>(&'a [u8]);
52
53impl<'a> StrList<'a> {
54 #[inline]
55 pub(super) fn new(value: &'a [StructureBlock], len: usize) -> Res<Self> {
56 let buf = unsafe { slice::from_raw_parts(value.as_ptr().cast(), len) };
57 if let Some(b'\0') = buf.last().copied() {
58 Ok(Self(buf))
59 } else {
60 Err(Error)
61 }
62 }
63}
64
65impl<'a> Iterator for StrList<'a> {
66 type Item = Str<'a>;
67
68 fn next(&mut self) -> Option<Self::Item> {
69 if self.0.is_empty() {
70 return None;
71 }
72 let (head, tail) = self
73 .0
74 .split_at(self.0.iter().position(|c| *c == b'\0').unwrap());
75 self.0 = &tail[1..];
76 Some(Str(head))
77 }
78}
79
80impl fmt::Display for StrList<'_> {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 let mut iter = self.clone();
83 '['.fmt(f)?;
84 if let Some(first) = iter.next() {
85 first.fmt(f)?;
86 for s in iter {
87 ", ".fmt(f)?;
88 s.fmt(f)?;
89 }
90 }
91 ']'.fmt(f)
92 }
93}