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> { None } pub const MAIN_SEP_STR: &str = "/"; pub const MAIN_SEP: char = '/'; /// Make a POSIX path absolute without changing its semantics. pub(crate) fn absolute(path: &Path) -> io::Result { // This is mostly a wrapper around collecting `Path::components`, with // exceptions made where this conflicts with the POSIX specification. // See 4.13 Pathname Resolution, IEEE Std 1003.1-2017 // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13 // Get the components, skipping the redundant leading "." component if it exists. let mut components = path.strip_prefix(".").unwrap_or(path).components(); let path_os = path.as_os_str().as_encoded_bytes(); let mut normalized = if path.is_absolute() { // "If a pathname begins with two successive characters, the // first component following the leading characters may be // interpreted in an implementation-defined manner, although more than // two leading characters shall be treated as a single // 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- character and contains one or more trailing // characters". // A trailing is also meaningful if "a symbolic link is // encountered during pathname resolution". if path_os.ends_with(b"/") { normalized.push(""); } Ok(normalized) }