Skip to main content

dolang_vfs/path/
components.rs

1//! Component iteration and Windows prefix classification.
2
3use std::fmt;
4
5use typed_path::{Utf8TypedComponent, Utf8TypedComponents, Utf8WindowsPrefix};
6
7use super::Path;
8
9/// One component of a [`Path`].
10#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct Component<'a>(pub(super) Utf8TypedComponent<'a>);
12
13impl<'a> Component<'a> {
14    /// Returns the component text.
15    pub fn as_str(&self) -> &'a str {
16        self.0.as_str()
17    }
18
19    /// Returns whether this is a root component.
20    pub fn is_root(&self) -> bool {
21        self.0.is_root()
22    }
23
24    /// Returns whether this is an ordinary named component.
25    pub fn is_normal(&self) -> bool {
26        self.0.is_normal()
27    }
28
29    /// Returns whether this is a parent (`..`) component.
30    pub fn is_parent(&self) -> bool {
31        self.0.is_parent()
32    }
33
34    /// Returns whether this is a current-directory (`.`) component.
35    pub fn is_current(&self) -> bool {
36        self.0.is_current()
37    }
38}
39
40impl fmt::Debug for Component<'_> {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        fmt::Debug::fmt(&self.0, f)
43    }
44}
45
46impl fmt::Display for Component<'_> {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        f.write_str(self.as_str())
49    }
50}
51
52/// Iterator over the components of a [`Path`].
53#[derive(Clone)]
54pub struct Components<'a>(pub(super) Utf8TypedComponents<'a>);
55
56impl<'a> Components<'a> {
57    /// Returns the remaining components as a path.
58    pub fn to_path(&self) -> Path<'a> {
59        Path(self.0.to_path())
60    }
61
62    /// Returns the remaining components as a string.
63    pub fn as_str(&self) -> &'a str {
64        self.0.as_str()
65    }
66
67    /// Returns whether the path being iterated is absolute.
68    pub fn is_absolute(&self) -> bool {
69        self.0.is_absolute()
70    }
71
72    /// Returns whether the path being iterated has a root.
73    pub fn has_root(&self) -> bool {
74        self.0.has_root()
75    }
76}
77
78impl<'a> Iterator for Components<'a> {
79    type Item = Component<'a>;
80
81    fn next(&mut self) -> Option<Self::Item> {
82        self.0.next().map(Component)
83    }
84}
85
86impl DoubleEndedIterator for Components<'_> {
87    fn next_back(&mut self) -> Option<Self::Item> {
88        self.0.next_back().map(Component)
89    }
90}
91
92impl std::iter::FusedIterator for Components<'_> {}
93
94impl fmt::Debug for Components<'_> {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96        fmt::Debug::fmt(&self.0, f)
97    }
98}
99
100/// Leading prefix of a Windows path.
101#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
102#[non_exhaustive]
103pub enum WindowsPrefix<'a> {
104    /// Verbatim prefix, e.g. `\\?\cat_pics`.
105    Verbatim(&'a str),
106    /// Verbatim UNC prefix, e.g. `\\?\UNC\server\share`.
107    VerbatimUNC(&'a str, &'a str),
108    /// Verbatim disk prefix, e.g. `\\?\C:`.
109    VerbatimDisk(char),
110    /// Device namespace prefix, e.g. `\\.\COM42`.
111    DeviceNS(&'a str),
112    /// UNC prefix, e.g. `\\server\share`.
113    UNC(&'a str, &'a str),
114    /// Disk prefix, e.g. `C:`.
115    Disk(char),
116}
117
118impl WindowsPrefix<'_> {
119    /// Returns whether this prefix uses verbatim (`\\?\`) syntax.
120    pub fn is_verbatim(&self) -> bool {
121        matches!(
122            self,
123            Self::Verbatim(_) | Self::VerbatimUNC(..) | Self::VerbatimDisk(_)
124        )
125    }
126}
127
128impl<'a> From<Utf8WindowsPrefix<'a>> for WindowsPrefix<'a> {
129    fn from(prefix: Utf8WindowsPrefix<'a>) -> Self {
130        match prefix {
131            Utf8WindowsPrefix::Verbatim(name) => Self::Verbatim(name),
132            Utf8WindowsPrefix::VerbatimUNC(server, share) => Self::VerbatimUNC(server, share),
133            Utf8WindowsPrefix::VerbatimDisk(disk) => Self::VerbatimDisk(disk),
134            Utf8WindowsPrefix::DeviceNS(name) => Self::DeviceNS(name),
135            Utf8WindowsPrefix::UNC(server, share) => Self::UNC(server, share),
136            Utf8WindowsPrefix::Disk(disk) => Self::Disk(disk),
137        }
138    }
139}