typed_path/windows/utf8/
components.rs1mod component;
2
3use core::{cmp, fmt, iter};
4
5pub use component::*;
6
7use crate::windows::WindowsComponents;
8use crate::{private, Components, Utf8Components, Utf8Encoding, Utf8Path};
9
10#[derive(Clone)]
12pub struct Utf8WindowsComponents<'a> {
13 inner: WindowsComponents<'a>,
14}
15
16impl<'a> Utf8WindowsComponents<'a> {
17 pub(crate) fn new(path: &'a str) -> Self {
18 Self {
19 inner: WindowsComponents::new(path.as_bytes()),
20 }
21 }
22
23 pub fn as_path<T>(&self) -> &'a Utf8Path<T>
38 where
39 T: Utf8Encoding,
40 {
41 Utf8Path::new(self.as_str())
42 }
43}
44
45impl private::Sealed for Utf8WindowsComponents<'_> {}
46
47impl<'a> Utf8Components<'a> for Utf8WindowsComponents<'a> {
48 type Component = Utf8WindowsComponent<'a>;
49
50 fn as_str(&self) -> &'a str {
51 unsafe { core::str::from_utf8_unchecked(self.inner.as_bytes()) }
54 }
55
56 fn is_absolute(&self) -> bool {
61 self.inner.is_absolute()
62 }
63
64 fn has_root(&self) -> bool {
69 self.inner.has_root()
70 }
71}
72
73impl<'a> Utf8WindowsComponents<'a> {
74 fn peek_front(&self) -> Option<<Self as Utf8Components<'a>>::Component> {
75 self.clone().next()
76 }
77
78 #[inline]
80 pub fn has_prefix(&self) -> bool {
81 self.prefix().is_some()
82 }
83
84 pub fn prefix(&self) -> Option<Utf8WindowsPrefixComponent<'_>> {
86 match self.peek_front() {
87 Some(Utf8WindowsComponent::Prefix(p)) => Some(p),
88 _ => None,
89 }
90 }
91
92 #[inline]
94 pub fn prefix_kind(&self) -> Option<Utf8WindowsPrefix<'_>> {
95 self.prefix().map(|p| p.kind())
96 }
97
98 pub fn has_any_verbatim_prefix(&self) -> bool {
100 matches!(
101 self.prefix_kind(),
102 Some(
103 Utf8WindowsPrefix::Verbatim(_)
104 | Utf8WindowsPrefix::UNC(..)
105 | Utf8WindowsPrefix::Disk(_)
106 )
107 )
108 }
109
110 pub fn has_verbatim_prefix(&self) -> bool {
112 matches!(self.prefix_kind(), Some(Utf8WindowsPrefix::Verbatim(_)))
113 }
114
115 pub fn has_verbatim_unc_prefix(&self) -> bool {
117 matches!(self.prefix_kind(), Some(Utf8WindowsPrefix::VerbatimUNC(..)))
118 }
119
120 pub fn has_verbatim_disk_prefix(&self) -> bool {
122 matches!(self.prefix_kind(), Some(Utf8WindowsPrefix::VerbatimDisk(_)))
123 }
124
125 pub fn has_device_ns_prefix(&self) -> bool {
127 matches!(self.prefix_kind(), Some(Utf8WindowsPrefix::DeviceNS(_)))
128 }
129
130 pub fn has_unc_prefix(&self) -> bool {
132 matches!(self.prefix_kind(), Some(Utf8WindowsPrefix::UNC(..)))
133 }
134
135 pub fn has_disk_prefix(&self) -> bool {
137 matches!(self.prefix_kind(), Some(Utf8WindowsPrefix::Disk(_)))
138 }
139
140 pub fn has_physical_root(&self) -> bool {
145 self.inner.has_physical_root()
146 }
147
148 pub fn has_implicit_root(&self) -> bool {
153 match self.prefix().map(|p| p.kind()) {
154 Some(Utf8WindowsPrefix::Disk(_)) | None => false,
155 Some(_) => true,
156 }
157 }
158}
159
160impl AsRef<[u8]> for Utf8WindowsComponents<'_> {
161 #[inline]
162 fn as_ref(&self) -> &[u8] {
163 self.as_str().as_bytes()
164 }
165}
166
167impl AsRef<str> for Utf8WindowsComponents<'_> {
168 #[inline]
169 fn as_ref(&self) -> &str {
170 self.as_str()
171 }
172}
173
174impl<T> AsRef<Utf8Path<T>> for Utf8WindowsComponents<'_>
175where
176 T: Utf8Encoding,
177{
178 #[inline]
179 fn as_ref(&self) -> &Utf8Path<T> {
180 Utf8Path::new(self.as_str())
181 }
182}
183
184impl fmt::Debug for Utf8WindowsComponents<'_> {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 struct DebugHelper<'a>(Utf8WindowsComponents<'a>);
187
188 impl fmt::Debug for DebugHelper<'_> {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 f.debug_list().entries(self.0.clone()).finish()
191 }
192 }
193
194 f.debug_tuple("Utf8WindowsComponents")
195 .field(&DebugHelper(self.clone()))
196 .finish()
197 }
198}
199
200impl<'a> Iterator for Utf8WindowsComponents<'a> {
201 type Item = <Self as Utf8Components<'a>>::Component;
202
203 fn next(&mut self) -> Option<Self::Item> {
204 self.inner
205 .next()
206 .map(|c| unsafe { Utf8WindowsComponent::from_utf8_unchecked(&c) })
207 }
208}
209
210impl DoubleEndedIterator for Utf8WindowsComponents<'_> {
211 fn next_back(&mut self) -> Option<Self::Item> {
212 self.inner
213 .next_back()
214 .map(|c| unsafe { Utf8WindowsComponent::from_utf8_unchecked(&c) })
215 }
216}
217
218impl iter::FusedIterator for Utf8WindowsComponents<'_> {}
219
220impl cmp::PartialEq for Utf8WindowsComponents<'_> {
221 #[inline]
222 fn eq(&self, other: &Self) -> bool {
223 PartialEq::eq(&self.inner, &other.inner)
224 }
225}
226
227impl cmp::Eq for Utf8WindowsComponents<'_> {}
228
229impl cmp::PartialOrd for Utf8WindowsComponents<'_> {
230 #[inline]
231 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
232 Some(self.cmp(other))
233 }
234}
235
236impl cmp::Ord for Utf8WindowsComponents<'_> {
237 #[inline]
238 fn cmp(&self, other: &Self) -> cmp::Ordering {
239 Ord::cmp(&self.inner, &other.inner)
240 }
241}