typed_path/common/utf8/
iter.rs

1use core::fmt;
2use core::iter::FusedIterator;
3use core::marker::PhantomData;
4
5use crate::{Utf8Component, Utf8Components, Utf8Encoding, Utf8Path};
6
7/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`], as [`str`] slices.
8///
9/// This `struct` is created by the [`iter`] method on [`Utf8Path`].
10/// See its documentation for more.
11///
12/// [`iter`]: Utf8Path::iter
13#[derive(Clone)]
14pub struct Utf8Iter<'a, T>
15where
16    T: Utf8Encoding,
17{
18    _encoding: PhantomData<T>,
19    inner: <T as Utf8Encoding>::Components<'a>,
20}
21
22impl<'a, T> Utf8Iter<'a, T>
23where
24    T: Utf8Encoding + 'a,
25{
26    pub(crate) fn new(inner: <T as Utf8Encoding>::Components<'a>) -> Self {
27        Self {
28            _encoding: PhantomData,
29            inner,
30        }
31    }
32
33    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
34    ///
35    /// # Examples
36    ///
37    /// ```
38    /// use typed_path::{Utf8Path, Utf8UnixEncoding};
39    ///
40    /// // NOTE: A path cannot be created on its own without a defined encoding
41    /// let mut iter = Utf8Path::<Utf8UnixEncoding>::new("/tmp/foo/bar.txt").iter();
42    /// iter.next();
43    /// iter.next();
44    ///
45    /// assert_eq!(Utf8Path::<Utf8UnixEncoding>::new("foo/bar.txt"), iter.as_path());
46    /// ```
47    pub fn as_path(&self) -> &Utf8Path<T> {
48        Utf8Path::new(self.inner.as_str())
49    }
50}
51
52impl<'a, T> fmt::Debug for Utf8Iter<'a, T>
53where
54    T: Utf8Encoding + 'a,
55{
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        struct DebugHelper<'a, T>(&'a Utf8Path<T>)
58        where
59            T: Utf8Encoding;
60
61        impl<T> fmt::Debug for DebugHelper<'_, T>
62        where
63            T: Utf8Encoding,
64        {
65            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66                f.debug_list().entries(self.0.iter()).finish()
67            }
68        }
69
70        f.debug_tuple(stringify!(Iter))
71            .field(&DebugHelper(self.as_path()))
72            .finish()
73    }
74}
75
76impl<'a, T> AsRef<Utf8Path<T>> for Utf8Iter<'a, T>
77where
78    T: Utf8Encoding + 'a,
79{
80    #[inline]
81    fn as_ref(&self) -> &Utf8Path<T> {
82        self.as_path()
83    }
84}
85
86impl<'a, T> AsRef<[u8]> for Utf8Iter<'a, T>
87where
88    T: Utf8Encoding + 'a,
89{
90    #[inline]
91    fn as_ref(&self) -> &[u8] {
92        self.as_path().as_str().as_bytes()
93    }
94}
95
96impl<'a, T> AsRef<str> for Utf8Iter<'a, T>
97where
98    T: Utf8Encoding + 'a,
99{
100    #[inline]
101    fn as_ref(&self) -> &str {
102        self.as_path().as_str()
103    }
104}
105
106impl<'a, T> Iterator for Utf8Iter<'a, T>
107where
108    T: Utf8Encoding + 'a,
109{
110    type Item = &'a str;
111
112    #[inline]
113    fn next(&mut self) -> Option<Self::Item> {
114        match self.inner.next() {
115            Some(c) => Some(c.as_str()),
116            None => None,
117        }
118    }
119}
120
121impl<'a, T> DoubleEndedIterator for Utf8Iter<'a, T>
122where
123    T: Utf8Encoding + 'a,
124{
125    #[inline]
126    fn next_back(&mut self) -> Option<Self::Item> {
127        match self.inner.next_back() {
128            Some(c) => Some(c.as_str()),
129            None => None,
130        }
131    }
132}
133
134impl<'a, T> FusedIterator for Utf8Iter<'a, T> where T: Utf8Encoding + 'a {}
135
136/// An iterator over [`Utf8Path`] and its ancestors.
137///
138/// This `struct` is created by the [`ancestors`] method on [`Utf8Path`].
139/// See its documentation for more.
140///
141/// # Examples
142///
143/// ```
144/// use typed_path::{Utf8Path, Utf8UnixEncoding};
145///
146/// // NOTE: A path cannot be created on its own without a defined encoding
147/// let path = Utf8Path::<Utf8UnixEncoding>::new("/foo/bar");
148///
149/// for ancestor in path.ancestors() {
150///     println!("{}", ancestor);
151/// }
152/// ```
153///
154/// [`ancestors`]: Utf8Path::ancestors
155#[derive(Copy, Clone, Debug)]
156pub struct Utf8Ancestors<'a, T>
157where
158    T: Utf8Encoding,
159{
160    pub(crate) next: Option<&'a Utf8Path<T>>,
161}
162
163impl<'a, T> Iterator for Utf8Ancestors<'a, T>
164where
165    T: Utf8Encoding,
166{
167    type Item = &'a Utf8Path<T>;
168
169    #[inline]
170    fn next(&mut self) -> Option<Self::Item> {
171        let next = self.next;
172        self.next = next.and_then(Utf8Path::parent);
173        next
174    }
175}
176
177impl<T> FusedIterator for Utf8Ancestors<'_, T> where T: Utf8Encoding {}