file_system/fundamentals/path/
components.rs1use 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 strip_prefix(self, components: &Components<'a>) -> Option<Components<'a>> {
34 let mut self_iter = self.clone();
35 let components_iter = components.clone();
36
37 for component in components_iter {
38 match self_iter.next() {
39 Some(self_component) if self_component == component => {}
40 _ => return None,
41 }
42 }
43
44 Some(Components(self_iter.0))
45 }
46
47 pub fn get_common_components(self, other: Components<'a>) -> usize {
48 self.zip(other).take_while(|(a, b)| a == b).count()
49 }
50}
51
52impl<'a> Iterator for Components<'a> {
53 type Item = Component<'a>;
54
55 fn next(&mut self) -> Option<Self::Item> {
56 self.0.next().map(Component::from)
57 }
58}
59
60impl DoubleEndedIterator for Components<'_> {
61 fn next_back(&mut self) -> Option<Self::Item> {
62 self.0.next_back().map(Component::from)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68
69 use alloc::{vec, vec::Vec};
70
71 use super::*;
72
73 #[test]
74 fn test_components() {
75 assert_eq!(
76 Components::new(Path::from_str("/a/b/c")).collect::<Vec<_>>(),
77 vec![
78 Component::Root,
79 Component::Normal("a"),
80 Component::Normal("b"),
81 Component::Normal("c")
82 ]
83 );
84
85 assert_eq!(
86 Components::new(Path::from_str("/a/./b/c")).collect::<Vec<_>>(),
87 vec![
88 Component::Root,
89 Component::Normal("a"),
90 Component::Current,
91 Component::Normal("b"),
92 Component::Normal("c")
93 ]
94 );
95
96 assert_eq!(
97 Components::new(Path::from_str("a/b/c")).collect::<Vec<_>>(),
98 vec![
99 Component::Normal("a"),
100 Component::Normal("b"),
101 Component::Normal("c")
102 ]
103 );
104
105 assert_eq!(
106 Components::new(Path::from_str("a/./../b/c")).collect::<Vec<_>>(),
107 vec![
108 Component::Normal("a"),
109 Component::Current,
110 Component::Parent,
111 Component::Normal("b"),
112 Component::Normal("c")
113 ]
114 );
115 }
116}