file_system/fundamentals/path/
components.rs

1use core::str::Split;
2
3use super::{Path, SEPARATOR};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum Component<'a> {
7    Root,
8    Current,
9    Parent,
10    Normal(&'a str),
11}
12
13impl<'a> From<&'a str> for Component<'a> {
14    fn from(item: &'a str) -> Self {
15        match item {
16            "" => Component::Root,
17            "/" => Component::Root,
18            "." => Component::Current,
19            ".." => Component::Parent,
20            _ => Component::Normal(item),
21        }
22    }
23}
24
25#[derive(Debug, Clone)]
26pub struct Components<'a>(Split<'a, char>);
27
28impl<'a> Components<'a> {
29    pub fn new(path: &'_ Path) -> Components<'_> {
30        Components(path.as_str().split(SEPARATOR))
31    }
32
33    pub fn get_common_components(self, other: Components<'a>) -> usize {
34        self.zip(other).take_while(|(a, b)| a == b).count()
35    }
36}
37
38impl<'a> Iterator for Components<'a> {
39    type Item = Component<'a>;
40
41    fn next(&mut self) -> Option<Self::Item> {
42        self.0.next().map(Component::from)
43    }
44}
45
46impl DoubleEndedIterator for Components<'_> {
47    fn next_back(&mut self) -> Option<Self::Item> {
48        self.0.next_back().map(Component::from)
49    }
50}
51
52#[cfg(test)]
53mod tests {
54
55    use alloc::{vec, vec::Vec};
56
57    use super::*;
58
59    #[test]
60    fn test_components() {
61        assert_eq!(
62            Components::new(Path::from_str("/a/b/c")).collect::<Vec<_>>(),
63            vec![
64                Component::Root,
65                Component::Normal("a"),
66                Component::Normal("b"),
67                Component::Normal("c")
68            ]
69        );
70
71        assert_eq!(
72            Components::new(Path::from_str("/a/./b/c")).collect::<Vec<_>>(),
73            vec![
74                Component::Root,
75                Component::Normal("a"),
76                Component::Current,
77                Component::Normal("b"),
78                Component::Normal("c")
79            ]
80        );
81
82        assert_eq!(
83            Components::new(Path::from_str("a/b/c")).collect::<Vec<_>>(),
84            vec![
85                Component::Normal("a"),
86                Component::Normal("b"),
87                Component::Normal("c")
88            ]
89        );
90
91        assert_eq!(
92            Components::new(Path::from_str("a/./../b/c")).collect::<Vec<_>>(),
93            vec![
94                Component::Normal("a"),
95                Component::Current,
96                Component::Parent,
97                Component::Normal("b"),
98                Component::Normal("c")
99            ]
100        );
101    }
102}