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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::borrow::Cow;
use std::ffi::OsString;
use std::io;
use std::path::{Component, Path, PathBuf};
use crate::{ParseDot, MAIN_SEPARATOR};
impl ParseDot for Path {
#[inline]
fn parse_dot(&self) -> io::Result<Cow<Path>> {
let cwd = get_cwd!();
self.parse_dot_from(&cwd)
}
fn parse_dot_from(&self, cwd: &Path) -> io::Result<Cow<Path>> {
let mut iter = self.components();
let mut has_dots = false;
if let Some(first_component) = iter.next() {
let mut tokens = Vec::new();
let first_is_root = match first_component {
Component::RootDir => {
tokens.push(MAIN_SEPARATOR.as_os_str());
true
}
Component::CurDir => {
for token in cwd.iter() {
tokens.push(token);
}
has_dots = true;
true
}
Component::ParentDir => {
match cwd.parent() {
Some(cwd_parent) => {
for token in cwd_parent.iter() {
tokens.push(token);
}
}
None => {
tokens.push(MAIN_SEPARATOR.as_os_str());
}
}
has_dots = true;
true
}
_ => {
tokens.push(first_component.as_os_str());
false
}
};
for component in iter {
match component {
Component::CurDir => {
has_dots = true;
}
Component::ParentDir => {
let tokens_length = tokens.len();
if tokens_length > 0 && (tokens_length != 1 || !first_is_root) {
tokens.remove(tokens_length - 1);
}
has_dots = true;
}
_ => {
tokens.push(component.as_os_str());
}
}
}
let tokens_length = tokens.len();
debug_assert!(tokens_length > 0);
let mut size = tokens.iter().fold(tokens_length - 1, |acc, &x| acc + x.len());
if first_is_root && tokens_length > 1 {
size -= 1;
}
if has_dots || size != self.as_os_str().len() {
let mut path_string = OsString::with_capacity(size);
let mut iter = tokens.iter();
path_string.push(iter.next().unwrap());
if tokens_length > 1 {
if !first_is_root {
path_string.push(MAIN_SEPARATOR.as_os_str());
}
for token in iter.take(tokens_length - 2) {
path_string.push(token);
path_string.push(MAIN_SEPARATOR.as_os_str());
}
path_string.push(tokens[tokens_length - 1]);
}
let path_buf = PathBuf::from(path_string);
Ok(Cow::from(path_buf))
} else {
Ok(Cow::from(self))
}
} else {
Ok(Cow::from(self))
}
}
}