typed_path/typed/utf8/
components.rs

1mod component;
2use core::{cmp, fmt, iter};
3
4pub use component::*;
5
6use crate::typed::Utf8TypedPath;
7use crate::unix::Utf8UnixComponents;
8use crate::windows::Utf8WindowsComponents;
9use crate::{private, Utf8Components};
10
11#[derive(Clone)]
12pub enum Utf8TypedComponents<'a> {
13    Unix(Utf8UnixComponents<'a>),
14    Windows(Utf8WindowsComponents<'a>),
15}
16
17impl<'a> Utf8TypedComponents<'a> {
18    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
19    ///
20    /// # Examples
21    ///
22    /// ```
23    /// use typed_path::Utf8TypedPath;
24    ///
25    /// let mut components = Utf8TypedPath::derive("/tmp/foo/bar.txt").components();
26    /// components.next();
27    /// components.next();
28    ///
29    /// assert_eq!(Utf8TypedPath::derive("foo/bar.txt"), components.to_path());
30    /// ```
31    pub fn to_path(&self) -> Utf8TypedPath<'a> {
32        match self {
33            Self::Unix(components) => Utf8TypedPath::Unix(components.as_path()),
34            Self::Windows(components) => Utf8TypedPath::Windows(components.as_path()),
35        }
36    }
37
38    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
39    pub fn as_str(&self) -> &'a str {
40        impl_typed_fn!(self, as_str)
41    }
42
43    /// Reports back whether the iterator represents an absolute path
44    ///
45    /// The definition of an absolute path can vary:
46    ///
47    /// * On Unix, a path is absolute if it starts with the root, so `is_absolute` and [`has_root`]
48    ///   are equivalent.
49    ///
50    /// * On Windows, a path is absolute if it has a prefix and starts with the root: `c:\windows`
51    ///   is absolute, while `c:temp` and `\temp` are not.
52    ///
53    /// [`has_root`]: Utf8TypedComponents::has_root
54    pub fn is_absolute(&self) -> bool {
55        impl_typed_fn!(self, is_absolute)
56    }
57
58    /// Returns `true` if the iterator represents a path that has a root.
59    ///
60    /// The definition of what it means for a path to have a root can vary:
61    ///
62    /// * On Unix, a path has a root if it begins with `/`.
63    ///
64    /// * On Windows, a path has a root if it:
65    ///     * has no prefix and begins with a separator, e.g., `\windows`
66    ///     * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows`
67    ///     * has any non-disk prefix, e.g., `\\server\share`
68    pub fn has_root(&self) -> bool {
69        impl_typed_fn!(self, has_root)
70    }
71}
72
73impl private::Sealed for Utf8TypedComponents<'_> {}
74
75impl AsRef<[u8]> for Utf8TypedComponents<'_> {
76    #[inline]
77    fn as_ref(&self) -> &[u8] {
78        impl_typed_fn!(self, as_ref)
79    }
80}
81
82impl AsRef<str> for Utf8TypedComponents<'_> {
83    #[inline]
84    fn as_ref(&self) -> &str {
85        impl_typed_fn!(self, as_ref)
86    }
87}
88
89impl fmt::Debug for Utf8TypedComponents<'_> {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        struct DebugHelper<'a>(Utf8TypedComponents<'a>);
92
93        impl fmt::Debug for DebugHelper<'_> {
94            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95                f.debug_list().entries(self.0.clone()).finish()
96            }
97        }
98
99        f.debug_tuple("Utf8TypedComponents")
100            .field(&DebugHelper(self.clone()))
101            .finish()
102    }
103}
104
105impl<'a> Iterator for Utf8TypedComponents<'a> {
106    type Item = Utf8TypedComponent<'a>;
107
108    fn next(&mut self) -> Option<Self::Item> {
109        match self {
110            Self::Unix(it) => it.next().map(Utf8TypedComponent::Unix),
111            Self::Windows(it) => it.next().map(Utf8TypedComponent::Windows),
112        }
113    }
114}
115
116impl DoubleEndedIterator for Utf8TypedComponents<'_> {
117    fn next_back(&mut self) -> Option<Self::Item> {
118        match self {
119            Self::Unix(it) => it.next_back().map(Utf8TypedComponent::Unix),
120            Self::Windows(it) => it.next_back().map(Utf8TypedComponent::Windows),
121        }
122    }
123}
124
125impl iter::FusedIterator for Utf8TypedComponents<'_> {}
126
127impl cmp::PartialEq for Utf8TypedComponents<'_> {
128    #[inline]
129    fn eq(&self, other: &Self) -> bool {
130        match (self, other) {
131            (Self::Unix(a), Self::Unix(b)) => a.eq(b),
132            (Self::Windows(a), Self::Windows(b)) => a.eq(b),
133            _ => false,
134        }
135    }
136}
137
138impl cmp::Eq for Utf8TypedComponents<'_> {}
139
140impl cmp::PartialOrd for Utf8TypedComponents<'_> {
141    #[inline]
142    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
143        match (self, other) {
144            (Self::Unix(a), Self::Unix(b)) => a.partial_cmp(b),
145            (Self::Windows(a), Self::Windows(b)) => a.partial_cmp(b),
146            _ => None,
147        }
148    }
149}