1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use crate::alloc_prelude::*;
pub const PATH_SEPARATOR: char = '/';
pub fn normalize(path: &str) -> String {
let mut portions: Vec<String> = Vec::new();
let mut chars = path.chars().collect::<Vec<char>>();
if chars.last() == Some(&PATH_SEPARATOR) && chars.len() > 1 {
while chars.last() == Some(&PATH_SEPARATOR) {
chars.pop();
}
}
while chars.first() == Some(&PATH_SEPARATOR) {
chars.remove(0);
}
chars.push('/');
let mut current = String::new();
for c in chars.iter() {
if *c == PATH_SEPARATOR {
match current.as_str() {
"" | "." => {}
".." => {
portions.pop();
}
_ => {
portions.push(current);
}
}
current = String::new();
} else {
current.push(*c);
}
}
String::from(PATH_SEPARATOR) + &portions.join(&String::from(PATH_SEPARATOR))
}
pub fn split(path: &str) -> Vec<String> {
normalize(path)
.split(PATH_SEPARATOR)
.filter(|x| x != &"")
.map(String::from)
.collect()
}
pub fn join(parts: &[String]) -> String {
let sep = String::from(PATH_SEPARATOR);
let npath = parts.join(&sep) + &sep;
normalize(&npath)
}