tokio_dbus/object_path/
iter.rs

1use std::mem::take;
2use std::str::from_utf8_unchecked;
3
4/// An iterator over an [`ObjectPath`].
5///
6/// [`ObjectPath`]: crate::ObjectPath
7#[must_use = "iterators are lazy and do nothing unless consumed"]
8pub struct Iter<'a> {
9    data: &'a [u8],
10}
11
12impl<'a> Iter<'a> {
13    pub(super) fn new(data: &'a [u8]) -> Self {
14        // NB: trim leading '/'.
15        Self { data: &data[1..] }
16    }
17}
18
19impl<'a> Iterator for Iter<'a> {
20    type Item = &'a str;
21
22    fn next(&mut self) -> Option<Self::Item> {
23        if self.data.is_empty() {
24            return None;
25        }
26
27        let data = match self.data.iter().position(|b| *b == b'/') {
28            Some(n) => {
29                let (head, tail) = self.data.split_at(n);
30                self.data = &tail[1..];
31                head
32            }
33            None => take(&mut self.data),
34        };
35
36        Some(unsafe { from_utf8_unchecked(data) })
37    }
38}
39
40impl<'a> DoubleEndedIterator for Iter<'a> {
41    #[inline]
42    fn next_back(&mut self) -> Option<Self::Item> {
43        if self.data.is_empty() {
44            return None;
45        }
46
47        let data = match self.data.iter().rposition(|b| *b == b'/') {
48            Some(n) => {
49                let (head, tail) = self.data.split_at(n);
50                self.data = head;
51                &tail[1..]
52            }
53            None => take(&mut self.data),
54        };
55
56        Some(unsafe { from_utf8_unchecked(data) })
57    }
58}