use std::{ffi::OsString, path::PathBuf};
use crate::{PathPrefix, PathType, PavedPath, UNIX_PATH_SEPARATOR, WINDOWS_PATH_SEPARATOR};
impl PavedPath {
pub(crate) fn push_dir_raw(&mut self, dir: OsString) {
if dir == "." || dir.is_empty() {
return;
}
if dir == ".." {
if self.directories.is_empty() || self.directories.last().unwrap() == ".." {
self.directories.push(dir.to_os_string());
} else {
self.directories.pop();
}
return;
}
let lossy_dir = dir.to_string_lossy();
let pattern = [WINDOWS_PATH_SEPARATOR, UNIX_PATH_SEPARATOR];
if lossy_dir.find(pattern).is_some() {
for d in lossy_dir.split(pattern) {
self.push_dir_raw(OsString::from(d));
}
} else {
self.directories.push(dir);
}
}
pub(crate) fn build_windows_pathbuf(&self) -> PathBuf {
let mut buf = OsString::new();
match self.path_type {
PathType::Absolute => match &self.path_prefix {
Some(drv) => match drv {
PathPrefix::Drive(chr) => {
buf.push(format!("{chr}:{sep}", sep = WINDOWS_PATH_SEPARATOR))
}
PathPrefix::UNC(s1, s2) => {
buf.push(format!("{sep}{sep}", sep = WINDOWS_PATH_SEPARATOR));
buf.push(s1);
buf.push(WINDOWS_PATH_SEPARATOR.to_string());
buf.push(s2);
buf.push(WINDOWS_PATH_SEPARATOR.to_string());
}
},
None => buf.push(WINDOWS_PATH_SEPARATOR.to_string()),
},
PathType::Relative => buf.push(format!(".{sep}", sep = WINDOWS_PATH_SEPARATOR)),
};
for d in &self.directories {
buf.push(d);
buf.push(WINDOWS_PATH_SEPARATOR.to_string());
}
if let Some(f) = &self.file {
buf.push(f);
}
PathBuf::from(buf)
}
pub(crate) fn build_unix_pathbuf(&self) -> PathBuf {
let mut buf = OsString::new();
match self.path_type {
PathType::Absolute => buf.push(UNIX_PATH_SEPARATOR.to_string()),
PathType::Relative => buf.push(format!(".{}", UNIX_PATH_SEPARATOR)),
}
for d in &self.directories {
buf.push(d);
buf.push(UNIX_PATH_SEPARATOR.to_string());
}
if let Some(f) = &self.file {
buf.push(f);
}
PathBuf::from(buf)
}
pub(crate) fn rebuild_inner(&mut self) {
let new_pathbuf = if cfg!(windows) {
self.build_windows_pathbuf()
} else {
self.build_unix_pathbuf()
};
self.inner = new_pathbuf;
}
}