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
use crate::env;
use crate::ffi::OsStr;
use crate::io;
use crate::path::{Path, PathBuf, Prefix};

#[inline]
pub fn is_sep_byte(b: u8) -> bool {
    b == b'/'
}

#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
    b == b'/'
}

#[inline]
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
    None
}

pub const MAIN_SEP_STR: &str = "/";
pub const MAIN_SEP: char = '/';

/// 在不改变其语义的情况下,使 POSIX 路径成为绝对路径。
pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
    // 这主要是收集 `Path::components` 的包装器,但与 POSIX 规范冲突的情况除外。
    //
    // 请参见 4.13 路径名解析,IEEE Std 1003.1-2017
    // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13

    // 获取组件,跳过多余的前导 "." 组件 (如果存在)。
    let mut components = path.strip_prefix(".").unwrap_or(path).components();
    let path_os = path.as_os_str().bytes();

    let mut normalized = if path.is_absolute() {
        // ` 如果路径名以两个连续的 <slash> 字符,前导后的第一个组件 <slash> 字符可以以实现定义的方式解释,尽管有两个以上的前导 <slash> 字符应被视为单个 <slash>
        //
        // character."
        //
        //
        if path_os.starts_with(b"//") && !path_os.starts_with(b"///") {
            components.next();
            PathBuf::from("//")
        } else {
            PathBuf::new()
        }
    } else {
        env::current_dir()?
    };
    normalized.extend(components);

    // "Interfaces using pathname resolution may specify additional constraints when a pathname that does not name an existing directory contains at least one non- <slash> character and contains one or more trailing <slash> characters".
    //
    // 尾随 <slash> 如果 "a symbolic link is encountered during pathname resolution" 也是有意义的。
    //
    //
    //
    if path_os.ends_with(b"/") {
        normalized.push("");
    }

    Ok(normalized)
}