2020-04-04 11:40:27 +02:00
|
|
|
use std::ffi::{OsStr, OsString};
|
|
|
|
use std::path::{Path, PathBuf};
|
2017-10-20 21:54:43 +02:00
|
|
|
|
2020-04-04 11:40:27 +02:00
|
|
|
use crate::filesystem::strip_current_dir;
|
2017-10-20 21:54:43 +02:00
|
|
|
|
2020-04-04 11:40:27 +02:00
|
|
|
/// Removes the parent component of the path
|
|
|
|
pub fn basename(path: &Path) -> &OsStr {
|
2022-02-28 09:16:42 +01:00
|
|
|
path.file_name().unwrap_or(path.as_os_str())
|
2017-11-03 01:39:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes the extension from the path
|
2020-04-04 11:40:27 +02:00
|
|
|
pub fn remove_extension(path: &Path) -> OsString {
|
|
|
|
let dirname = dirname(path);
|
2022-02-28 09:16:42 +01:00
|
|
|
let stem = path.file_stem().unwrap_or(path.as_os_str());
|
2017-10-20 21:54:43 +02:00
|
|
|
|
2020-04-04 11:40:27 +02:00
|
|
|
let path = PathBuf::from(dirname).join(stem);
|
2017-10-20 21:54:43 +02:00
|
|
|
|
2020-04-04 11:40:27 +02:00
|
|
|
strip_current_dir(&path).to_owned().into_os_string()
|
2017-11-03 01:39:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes the basename from the path.
|
2020-04-04 11:40:27 +02:00
|
|
|
pub fn dirname(path: &Path) -> OsString {
|
|
|
|
path.parent()
|
|
|
|
.map(|p| {
|
|
|
|
if p == OsStr::new("") {
|
|
|
|
OsString::from(".")
|
|
|
|
} else {
|
|
|
|
p.as_os_str().to_owned()
|
|
|
|
}
|
|
|
|
})
|
2020-05-01 11:22:30 +02:00
|
|
|
.unwrap_or_else(|| path.as_os_str().to_owned())
|
2017-10-20 21:54:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
2018-07-05 00:44:35 +02:00
|
|
|
mod path_tests {
|
2018-10-03 10:36:15 +02:00
|
|
|
use super::*;
|
2020-04-04 11:40:27 +02:00
|
|
|
use std::path::MAIN_SEPARATOR;
|
2017-10-20 21:54:43 +02:00
|
|
|
|
|
|
|
fn correct(input: &str) -> String {
|
2017-11-03 01:39:03 +01:00
|
|
|
input.replace('/', &MAIN_SEPARATOR.to_string())
|
2017-10-20 21:54:43 +02:00
|
|
|
}
|
|
|
|
|
2018-07-05 00:44:35 +02:00
|
|
|
macro_rules! func_tests {
|
|
|
|
($($name:ident: $func:ident for $input:expr => $output:expr)+) => {
|
|
|
|
$(
|
|
|
|
#[test]
|
|
|
|
fn $name() {
|
2020-04-04 11:40:27 +02:00
|
|
|
let input_path = PathBuf::from(&correct($input));
|
|
|
|
let output_string = OsString::from(correct($output));
|
|
|
|
assert_eq!($func(&input_path), output_string);
|
2018-07-05 00:44:35 +02:00
|
|
|
}
|
|
|
|
)+
|
|
|
|
}
|
2017-10-20 21:54:43 +02:00
|
|
|
}
|
|
|
|
|
2018-07-05 00:44:35 +02:00
|
|
|
func_tests! {
|
|
|
|
remove_ext_simple: remove_extension for "foo.txt" => "foo"
|
|
|
|
remove_ext_dir: remove_extension for "dir/foo.txt" => "dir/foo"
|
|
|
|
hidden: remove_extension for ".foo" => ".foo"
|
|
|
|
remove_ext_utf8: remove_extension for "💖.txt" => "💖"
|
|
|
|
remove_ext_empty: remove_extension for "" => ""
|
2017-10-20 21:54:43 +02:00
|
|
|
|
2018-07-05 00:44:35 +02:00
|
|
|
basename_simple: basename for "foo.txt" => "foo.txt"
|
|
|
|
basename_dir: basename for "dir/foo.txt" => "foo.txt"
|
|
|
|
basename_empty: basename for "" => ""
|
|
|
|
basename_utf8_0: basename for "💖/foo.txt" => "foo.txt"
|
|
|
|
basename_utf8_1: basename for "dir/💖.txt" => "💖.txt"
|
2017-10-20 21:54:43 +02:00
|
|
|
|
2018-07-05 00:44:35 +02:00
|
|
|
dirname_simple: dirname for "foo.txt" => "."
|
|
|
|
dirname_dir: dirname for "dir/foo.txt" => "dir"
|
|
|
|
dirname_utf8_0: dirname for "💖/foo.txt" => "💖"
|
|
|
|
dirname_utf8_1: dirname for "dir/💖.txt" => "dir"
|
2017-10-20 21:54:43 +02:00
|
|
|
}
|
2017-10-26 09:18:06 +02:00
|
|
|
|
|
|
|
#[test]
|
2020-04-04 11:40:27 +02:00
|
|
|
#[cfg(windows)]
|
|
|
|
fn dirname_root() {
|
2020-04-04 13:41:14 +02:00
|
|
|
assert_eq!(dirname(&PathBuf::from("C:")), OsString::from("C:"));
|
2020-04-04 11:40:27 +02:00
|
|
|
assert_eq!(dirname(&PathBuf::from("\\")), OsString::from("\\"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(not(windows))]
|
2018-07-05 00:44:35 +02:00
|
|
|
fn dirname_root() {
|
2020-04-04 11:40:27 +02:00
|
|
|
assert_eq!(dirname(&PathBuf::from("/")), OsString::from("/"));
|
2017-10-26 09:18:06 +02:00
|
|
|
}
|
2017-10-20 21:54:43 +02:00
|
|
|
}
|