dtb_walker/property/
str.rs

1use 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    /// Converts to str without checking utf-8 validity.
32    ///
33    /// # Safety
34    ///
35    /// see [`core::str::from_utf8_unchecked`].
36    #[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}