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
use std::ffi::OsString;
use std::io;
use std::path::{Path, PathBuf};

use crate::{ParseDot, MAIN_SEPARATOR};

impl ParseDot for Path {
    #[allow(clippy::let_unit_value)]
    fn parse_dot(&self) -> io::Result<PathBuf> {
        let mut size = self.as_os_str().len();

        let _cwd = get_cwd_pathbuf!();

        let mut tokens = Vec::new();

        let mut iter = self.iter();

        if let Some(first_token) = iter.next() {
            let cwd = get_cwd!(_cwd);

            if first_token.eq(".") {
                for token in cwd.iter() {
                    tokens.push(token);
                }
                size += cwd.as_os_str().len() - 1;
            } else if first_token.eq("..") {
                let cwd_parent = cwd.parent();

                match cwd_parent {
                    Some(cwd_parent) => {
                        for token in cwd_parent.iter() {
                            tokens.push(token);
                        }
                        size += cwd_parent.as_os_str().len() - 2;
                    }
                    None => {
                        tokens.push(MAIN_SEPARATOR.as_os_str());
                        size -= 2;
                    }
                }
            } else {
                tokens.push(first_token);
            }

            for token in iter {
                //              if token.eq(".") {
                //                  size -= 2;
                //                  continue;
                //              } else
                // Don't need to check single dot. It is already filtered.
                if token.eq("..") {
                    let len = tokens.len();
                    if len > 0 && (len != 1 || tokens[0].ne(MAIN_SEPARATOR.as_os_str())) {
                        let removed = tokens.remove(len - 1);
                        size -= removed.len() + 4;
                    } else {
                        size -= 3;
                    }
                } else {
                    tokens.push(token);
                }
            }
        }

        let mut path = OsString::with_capacity(size);

        let len = tokens.len();

        if len > 0 {
            let mut iter = tokens.iter();

            if let Some(first_token) = iter.next() {
                path.push(first_token);

                if len > 1 {
                    if !first_token.eq(&MAIN_SEPARATOR.as_os_str()) {
                        path.push(MAIN_SEPARATOR.as_os_str());
                    }

                    for &token in iter.take(len - 2) {
                        path.push(token);

                        path.push(MAIN_SEPARATOR.as_os_str());
                    }

                    path.push(tokens[len - 1]);
                }
            }
        }

        let path_buf = PathBuf::from(path);

        Ok(path_buf)
    }
}