use std::ffi::OsStr;
use std::fmt::{Debug, Display};
use std::fs::DirEntry;
use std::path::{Path, PathBuf};
use shellexpand;
use substring::Substring;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_absolute_path() {
let string_path = "./test/test_b/test_c/../";
assert_eq!(
get_absolute_path(&string_path),
format!("{}/test/test_b", env!("CARGO_MANIFEST_DIR")),
);
let string_result = get_absolute_path(&"~/test");
if string_result.contains("~") {
panic!("Result contains tilde.")
}
if !string_result.ends_with("/test") {
panic!("Result doesn't end with '/test'.")
}
}
#[test]
fn test_get_absolute_path_or_error() {
let string_path = "./test/test_b/test_c/../";
let result = match get_absolute_path_or_error(&string_path) {
Ok(string_result) => string_result,
Err(err) => panic!("{}", err,),
};
let expected = format!("{}/test/test_b", env!("CARGO_MANIFEST_DIR").to_string(),);
assert_eq!(result, expected)
}
#[test]
fn test_get_base_name_with_extension() {
let string_path = "test/test_a/text_a_a.txt";
let result = match get_base_name(&string_path) {
Some(string_result) => string_result,
None => panic!(""),
};
let expected = "text_a_a.txt".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_base_name_on_dir() {
let string_path = "test/test_b/test_c/text_b_c_a.txt";
let result = match get_base_name(&string_path) {
Some(string_result) => string_result,
None => panic!(""),
};
let expected = "text_b_c_a.txt".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_common_path() {
let slice_of_strings = [
"src/helpers_disk/A/B/C",
"src/helpers_disk/A/B",
"src/helpers_disk/A",
];
let result = match get_common_path(&slice_of_strings) {
Ok(string_result) => string_result,
Err(err) => panic!("{}", err),
};
let expected = "src".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_common_prefix() {
let slice_of_strings = [
"src/helpers_disk/A/B/C",
"src/helpers_disk/A/B",
"src/helpers_disk/A",
];
let result = match get_common_prefix(&slice_of_strings) {
Ok(string_result) => string_result,
Err(err) => panic!("{}", err),
};
let expected = "src/helpers_disk/A".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_dir_name() {
let string_path = "test/test_b/test_c/text_b_c_a.txt";
let result = match get_dir_name(&string_path) {
Some(string_result) => string_result,
None => panic!("Failed"),
};
let expected = "test/test_b/test_c".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_dir_ancestor_n_levels_up() {
let string_path = "test/test_b/test_c/text_b_c_a.txt";
let int_layers_up: usize = 2;
let result = match get_dir_ancestor_n_levels_up(&string_path, int_layers_up) {
Some(string_result) => string_result,
None => panic!("Failed"),
};
let expected = "test/test_b".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_dir_ancestor_that_exists() {
let string_path = "test/test_b/test_c/text_b_c_a.txt/A/B/C";
let result = match get_dir_ancestor_that_exists(&string_path) {
Some(string_result) => string_result,
None => panic!("Failed"),
};
let expected = "test/test_b/test_c/text_b_c_a.txt".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_extension() {
let string_path = "test/test_b/test_c/text_b_c_a.txt";
let result = match get_extension(&string_path) {
Some(string_result) => string_result,
None => panic!("Failed"),
};
let expected = "txt".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_only_dirs_from_slice() {
let slice_of_strings = [
"test/test_b",
"test/test_b/test_c",
"test/test_b/test_c/text_b_c_b.txt",
"test/test_b/test_c/text_b_c_a.txt",
"test/test_a",
"test/test_a/text_a_a.txt",
];
let result = get_only_dirs_from_slice(&slice_of_strings);
let expected = ["test/test_b", "test/test_b/test_c", "test/test_a"]
.iter()
.map(|item| format!("{}", item,))
.collect::<Vec<String>>();
assert_eq!(result, expected,)
}
#[test]
fn test_get_only_file_paths_from_slice() {
let slice_of_strings = [
"test/test_b",
"test/test_b/test_c",
"test/test_b/test_c/text_b_c_b.txt",
"test/test_b/test_c/text_b_c_a.txt",
"test/test_a",
"test/test_a/text_a_a.txt",
];
let result = get_only_file_paths_from_slice(&slice_of_strings);
let expected = [
"test/test_b/test_c/text_b_c_b.txt",
"test/test_b/test_c/text_b_c_a.txt",
"test/test_a/text_a_a.txt",
]
.iter()
.map(|item| format!("{}", item,))
.collect::<Vec<String>>();
assert_eq!(result, expected,)
}
#[test]
fn test_get_path_joined() {
let slice_of_strings = ["A", "B", "C"];
let result = match get_path_joined(&slice_of_strings) {
Some(string_result) => string_result,
None => panic!("Failed"),
};
let expected = "A/B/C".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_paths_in_dir() {
let string_path = "test";
let result = match get_paths_in_dir(&string_path) {
Ok(vec_result) => vec_result,
Err(err) => panic!("{}", err,),
};
let expected = ["test/test_a", "test/test_b"]
.iter()
.map(|item_str| item_str.to_string())
.collect::<Vec<String>>();
assert_eq!(result, expected)
}
#[test]
fn test_get_paths_in_dir_and_sub_dirs() {
let string_path = "test";
let result = match get_paths_in_dir_and_sub_dirs(&string_path) {
Ok(vec_result) => vec_result,
Err(err) => panic!("{}", err),
};
let expected = [
"test/test_b",
"test/test_b/test_c",
"test/test_b/test_c/text_b_c_b.txt",
"test/test_b/test_c/text_b_c_a.txt",
"test/test_a",
"test/test_a/text_a_a.txt",
]
.iter()
.map(|item_str| item_str.to_string())
.collect::<Vec<String>>();
assert_eq!(result, expected)
}
#[test]
fn test_get_paths_sorted_by_size_starting_with_shortest() {
let slice_of_strings = ["/A/B/C", "/A", "/A/B"];
let result = match get_paths_sorted_by_size_starting_with_shortest(&slice_of_strings) {
Ok(vec_result) => vec_result,
Err(err) => panic!("{}", err),
};
let expected = ["/A", "/A/B", "/A/B/C"]
.iter()
.map(|item_str| item_str.to_string())
.collect::<Vec<String>>();
assert_eq!(result, expected)
}
#[test]
fn test_get_paths_to_only_dirs_in_dir_and_sub_dirs() {
let string_path = "test";
let result = match get_paths_to_only_dirs_in_dir_and_sub_dirs(&string_path) {
Ok(vec_result) => vec_result,
Err(err) => panic!("{}", err,),
};
let expected = ["test/test_b", "test/test_b/test_c", "test/test_a"]
.iter()
.map(|item_str| item_str.to_string())
.collect::<Vec<String>>();
assert_eq!(result, expected)
}
#[test]
fn test_get_paths_to_only_files_in_dir_and_sub_dirs() {
let string_path = "test";
let result = match get_paths_to_only_files_in_dir_and_sub_dirs(&string_path) {
Ok(vec_result) => vec_result,
Err(err) => panic!("{}", err,),
};
let expected = [
"test/test_b/test_c/text_b_c_b.txt",
"test/test_b/test_c/text_b_c_a.txt",
"test/test_a/text_a_a.txt",
]
.iter()
.map(|item_str| item_str.to_string())
.collect::<Vec<String>>();
assert_eq!(result, expected)
}
#[test]
fn test_get_relative_path() {
let string_path_abs_root = "/A/B/C";
let string_path_abs = "/A/B/C/D";
let result = match get_relative_path(&string_path_abs, &string_path_abs_root) {
Ok(string_result) => string_result,
Err(err) => panic!("{}", err,),
};
let expected = "D".to_string();
assert_eq!(result, expected)
}
#[test]
fn test_get_vec_by_splitting_path() {
let string_path = "test/test_b/test_c/text_b_c_a.txt";
let result = match get_vec_by_splitting_path(&string_path) {
Some(vec_result) => vec_result,
None => panic!("Failed"),
};
let expected = ["test", "test_b", "test_c", "text_b_c_a.txt"]
.iter()
.map(|item_str| item_str.to_string())
.collect::<Vec<String>>();
assert_eq!(result, expected)
}
#[test]
fn test_is_absolute() {
assert_eq!(is_absolute(&"/A/B/C"), true,)
}
#[test]
fn test_is_existing_path() {
assert_eq!(is_existing_path(&"test/test_b/test_c/text_b_c_a.txt"), true,)
}
#[test]
fn test_is_path_type() {
assert_eq!(
is_path_type(&Path::new(&"test/test_b/test_c/text_b_c_a.txt")),
true,
)
}
#[test]
fn test_is_path_buf_type() {
assert_eq!(
is_path_buf_type(&PathBuf::from("test/test_b/test_c/text_b_c_a.txt")),
true,
)
}
#[test]
fn test_is_path_inside_dir_parent() {
assert_eq!(
is_path_inside_dir_parent(&"test/test_b/test_c/text_b_c_a.txt", &"test/test_b"),
true,
)
}
#[test]
fn test_raise_error_if_path_is_not_in_project_absolute() {
let mut string_path = "/badpath";
match raise_error_if_path_is_not_in_project(&string_path) {
Ok( () ) => {
panic!(
"{}",
[
"Did not return error on bad absolute path.".to_string(),
format!("string_path = {}", string_path,)
]
.join("\n")
)
}
Err( _err ) => {}
}
string_path = "test";
match raise_error_if_path_is_not_in_project(&string_path) {
Ok(()) => {}
Err(_err) => {
panic!(
"{}",
[
"Returned error on good relative path.".to_string(),
format!("string_path = {}", string_path,),
]
.join("\n")
)
}
}
string_path = "bad/test";
match raise_error_if_path_is_not_in_project(&string_path) {
Ok(()) => {
panic!(
"{}",
[
"Did not return error on bad relative path.".to_string(),
format!("string_path = {}", string_path,),
]
.join("\n")
)
}
Err(_err) => {}
}
}
#[test]
fn test_raise_error_if_path_points_to_src() {
match raise_error_if_path_points_to_src(&"src") {
Ok(()) => { panic!("Did not return error") }
Err( _err ) => {},
}
match raise_error_if_path_points_to_src(&"src/") {
Ok(()) => { panic!("Did not return error") }
Err(_err) => {},
}
match raise_error_if_path_points_to_src(&format!("{}/src/", env!("CARGO_MANIFEST_DIR"),)) {
Ok(()) => {panic!("No error returned")}
Err(_err) => {},
}
match raise_error_if_path_points_to_src(&"src/") {
Ok(()) => {panic!("No error returned")}
Err(_err) => {},
}
}
#[test]
fn test_raise_error_if_path_points_to_cargo_toml() {
let mut string_path = format!("{}/Cargo.toml", env!("CARGO_MANIFEST_DIR"),);
match raise_error_if_path_points_to_cargo_toml(&string_path) {
Ok(()) => {
panic!(
"{}",
[
"Didn't raise error when passed the absolute path to Cargo.toml"
.to_string(),
format!("string_path = {}", string_path,),
]
.join("\n")
)
}
Err(_err) => {}
}
string_path = "Cargo.toml".to_string();
match raise_error_if_path_points_to_cargo_toml(&string_path) {
Ok(()) => {
panic!(
"{}",
[
"Didn't raise error when passed the relative path to Cargo.toml".to_string(),
format!("string_path = {}", string_path,),
]
.join("\n")
)
}
Err(_err) => {},
}
string_path = "src".to_string();
match raise_error_if_path_points_to_cargo_toml(&string_path) {
Ok(()) => {}
Err(_err) => {
panic!(
"{}",
[
"Raised error when not pointing to Cargo.toml".to_string(),
format!("string_path = {}", string_path,),
]
.join("\n")
)
}
}
}
#[test]
fn test_raise_error_if_path_points_to_main_rs() {
let mut string_path = format!("{}/src/main.rs", env!("CARGO_MANIFEST_DIR"),);
match raise_error_if_path_points_to_main_rs(&string_path) {
Ok(()) => {
panic!(
"{}",
[
"Failed to return error when passed absolute path to main.rs".to_string(),
format!("string_path = {}", string_path,),
]
.join("\n")
)
}
Err(_err) => {}
}
string_path = "src/main.rs".to_string();
match raise_error_if_path_points_to_main_rs(&string_path) {
Ok(()) => {
panic!(
"{}",
[
"Failed to return error when passed relative path to main.rs".to_string(),
format!("string_path = {}", string_path,),
]
.join("\n")
)
}
Err(_err) => {}
}
string_path = "src".to_string();
match raise_error_if_path_points_to_main_rs(&string_path) {
Ok(()) => {
}
Err(_err) => {
panic!(
"{}",
[
"Raised error when not pointing at main.rs".to_string(),
format!("string_path = {}", string_path,),
]
.join("\n")
)
}
}
}
}
pub fn get_absolute_path<T: Debug + Display>(arg_string_path: &T) -> String {
let string_path = get_path_with_tilde_expanded_if_necessary(&arg_string_path);
match std::fs::canonicalize(PathBuf::from(&string_path)) {
Ok(path_buf_result) => match path_buf_result.to_str() {
Some(str_result) => str_result.to_string(),
None => return string_path,
},
Err(_err) => string_path,
}
}
pub fn get_absolute_path_or_error<T: Debug + Display>(
arg_string_path: &T,
) -> Result<String, String> {
let string_path = get_path_with_tilde_expanded_if_necessary(&arg_string_path);
match std::fs::canonicalize(PathBuf::from(&string_path)) {
Ok(path_buf_result) => match path_buf_result.to_str() {
Some(str_result) => Ok(str_result.to_string()),
None => {
return Err([
"Error: Failed to extract str from PathBuf.".to_string(),
format!("arg_string_path = {}", arg_string_path,),
format!("path built = {}", string_path,),
]
.join("\n"))
}
},
Err(err) => {
return Err([
"Error: Failed to 'canonicalize' string_path.".to_string(),
format!("arg_string_path = {}", arg_string_path,),
format!("err = {}", err,),
format!("path built = {}", string_path,),
]
.join("\n"))
}
}
}
pub fn get_base_name<T: Debug + Display>(arg_string_path: &T) -> Option<String> {
match Path::new(&format!("{}", arg_string_path,)).file_name() {
Some(os_str_result) => match os_str_result.to_str() {
Some(str_result) => Some(str_result.to_string()),
None => return None,
},
None => return None,
}
}
pub fn get_common_path<T: Debug + Display>(arg_slice_of_strings: &[T]) -> Result<String, String> {
let vec_of_path_bufs =
get_path_bufs_sorted_by_size_starting_with_shortest(&arg_slice_of_strings);
let mut path_buf_prefix_to_return = match vec_of_path_bufs.get(0) {
Some(path_buf_result) => path_buf_result.clone(),
None => {
return Err([
"Error: Failed to get value at index 0.".to_string(),
format!(
"arg_slice_of_strings.len() = {}",
arg_slice_of_strings.len()
),
format!(
"arg_slice_of_strings.len() = {:#?}",
arg_slice_of_strings.len()
),
]
.join("\n"))
}
};
loop {
let bool_all_path_bufs_meet_requirement = {
let mut bool_all_path_bufs_meet_requirement = true;
for item_path_buf in &vec_of_path_bufs {
if !item_path_buf.starts_with(&path_buf_prefix_to_return) {
bool_all_path_bufs_meet_requirement = false;
break;
}
}
bool_all_path_bufs_meet_requirement
};
if bool_all_path_bufs_meet_requirement {
match path_buf_prefix_to_return.to_str() {
Some(_str_result) => break,
None => {
return Err([
"Error: Failed to extract str from PathBuf.".to_string(),
format!(
"path buf value at failure = {:?}",
path_buf_prefix_to_return
),
format!("arg_slice_of_strings = {:#?}", arg_slice_of_strings,),
]
.join("\n"))
}
}
} else {
path_buf_prefix_to_return = match path_buf_prefix_to_return.parent() {
Some(path_result) => PathBuf::from(path_result),
None => {
return Err([
"Error: Attempted to access non-existent parent.".to_string(),
format!(
"path buf value at failure = {:?}",
path_buf_prefix_to_return
),
format!("arg_slice_of_strings = {:#?}", arg_slice_of_strings,),
]
.join("\n"))
}
}
}
}
loop {
if path_buf_prefix_to_return.exists() {
break;
}
path_buf_prefix_to_return = match path_buf_prefix_to_return.parent() {
Some(path_result) => PathBuf::from(path_result),
None => {
return Err([
"Error: Attempted to access non-existent parent.".to_string(),
format!(
"path buf value at failure = {:?}",
path_buf_prefix_to_return
),
format!("arg_slice_of_strings = {:#?}", arg_slice_of_strings,),
]
.join("\n"))
}
}
}
match path_buf_prefix_to_return.to_str() {
Some(str_result) => Ok(str_result.to_string()),
None => Err([
"Error: Failed to extract str from PathBuf.".to_string(),
format!(
"path buf value at failure = {:?}",
path_buf_prefix_to_return
),
format!("arg_slice_of_strings = {:#?}", arg_slice_of_strings,),
]
.join("\n")),
}
}
pub fn get_common_prefix<T: Debug + Display>(arg_slice_of_strings: &[T]) -> Result<String, String> {
let vec_of_path_bufs =
get_path_bufs_sorted_by_size_starting_with_shortest(&arg_slice_of_strings);
let mut path_buf_to_return = match vec_of_path_bufs.get(0) {
Some(path_buf_result) => path_buf_result.clone(),
None => {
return Err([
"Error: Failed to get value at index 0.".to_string(),
format!(
"arg_slice_of_strings.len() = {}",
arg_slice_of_strings.len()
),
format!(
"arg_slice_of_strings.len() = {:#?}",
arg_slice_of_strings.len()
),
]
.join("\n"))
}
};
loop {
let bool_all_path_bufs_meet_requirement = {
let mut bool_all_path_bufs_meet_requirement = true;
for item_path_buf in &vec_of_path_bufs {
if !item_path_buf.starts_with(&path_buf_to_return) {
bool_all_path_bufs_meet_requirement = false;
break;
}
}
bool_all_path_bufs_meet_requirement
};
if bool_all_path_bufs_meet_requirement {
break;
}
path_buf_to_return = match path_buf_to_return.parent() {
Some(path_result) => PathBuf::from(path_result),
None => {
return Err([
"Error: Attempted to access non-existent parent.".to_string(),
format!("path buf value at failure = {:?}", path_buf_to_return),
format!("arg_slice_of_strings = {:#?}", arg_slice_of_strings,),
]
.join("\n"))
}
}
}
match path_buf_to_return.to_str() {
Some(str_result) => Ok(str_result.to_string()),
None => {
return Err([
"Error: Failed to extract str from PathBuf.".to_string(),
format!("path buf value at failure = {:?}", path_buf_to_return),
format!("arg_slice_of_strings = {:#?}", arg_slice_of_strings,),
]
.join("\n"))
}
}
}
pub fn get_dir_ancestor_n_levels_up<T: Debug + Display>(
arg_string_path: &T,
arg_n: usize,
) -> Option<String> {
let mut path_buf = PathBuf::from(format!("{}", arg_string_path,));
for _ in 0..arg_n {
path_buf = match path_buf.parent() {
Some(path_result) => PathBuf::from(path_result),
None => return None,
};
}
match path_buf.to_str() {
Some(str_result) => Some(str_result.to_string()),
None => None,
}
}
pub fn get_dir_ancestor_that_exists<T: Debug + Display>(arg_string_path: &T) -> Option<String> {
let mut path_buf = PathBuf::from(format!("{}", arg_string_path,));
loop {
if path_buf.exists() {
return match path_buf.to_str() {
Some(str_result) => Some(str_result.to_string()),
None => None,
};
} else {
path_buf = match path_buf.parent() {
Some(path_result) => PathBuf::from(path_result),
None => return None,
};
}
}
}
pub fn get_dir_cwd() -> Result<String, String> {
match std::env::current_dir() {
Ok(path_buf_from_env) => match path_buf_from_env.to_str() {
Some(str_result) => Ok(str_result.to_string()),
None => {
return Err([
"Error: could not get str from PathBuf.".to_string(),
format!("path_buf_from_env = {:?}", path_buf_from_env,),
]
.join("\n"))
}
},
Err(err) => {
return Err([
"Error: could not get PathBuf from std::env::current_dir().".to_string(),
format!("err = {}", err,),
format!("std::env::current_dir() = {:?}", std::env::current_dir(),),
]
.join("\n"))
}
}
}
pub fn get_dir_name<T: Debug + Display>(arg_string_path: &T) -> Option<String> {
match PathBuf::from(format!("{}", arg_string_path,)).parent() {
Some(path_result) => match path_result.to_str() {
Some(str_result) => Some(str_result.to_string()),
None => None,
},
None => None,
}
}
pub fn get_dir_proj_root() -> String {
env!("CARGO_MANIFEST_DIR").to_string()
}
pub fn get_extension<T: Debug + Display>(arg_string_path: &T) -> Option<String> {
match Path::new(&format!("{}", arg_string_path,)).extension() {
Some(os_str_result) => match os_str_result.to_str() {
Some(str_result) => Some(str_result.to_string()),
None => return None,
},
None => return None,
}
}
pub fn get_file_path_binary() -> Result<String, String> {
match std::env::current_exe() {
Ok(path_buf_result) => match path_buf_result.to_str() {
Some(str_result) => Ok(str_result.to_string()),
None => Err([
"Error: failed to convert path to binary file from PathBuff to str".to_string(),
format!("path_buf_from_current_exe = {:?}", path_buf_result,),
]
.join("\n")),
},
Err(err) => Err([
"Error: failed to get path to binary file outputted by compilation process".to_string(),
format!("err = {}", err,),
]
.join("\n")),
}
}
pub fn get_only_dirs_from_slice<T: Debug + Display>(arg_slice_of_strings: &[T]) -> Vec<String> {
arg_slice_of_strings
.iter()
.map(|item| format!("{}", item))
.filter(|item_string| PathBuf::from(item_string).is_dir())
.collect::<Vec<String>>()
}
pub fn get_only_file_paths_from_slice<T: Debug + Display>(
arg_slice_of_strings: &[T],
) -> Vec<String> {
arg_slice_of_strings
.iter()
.map(|item| format!("{}", item))
.filter(|item_string| PathBuf::from(item_string).is_file())
.collect::<Vec<String>>()
}
pub fn get_path_joined<T: Debug + Display>(arg_slice_of_strings: &[T]) -> Option<String> {
match arg_slice_of_strings
.iter()
.map(|item| format!("{}", item,))
.collect::<PathBuf>()
.to_str()
{
Some(str_result) => Some(str_result.to_string()),
None => None,
}
}
pub fn get_path_with_tilde_expanded_if_necessary<T: Debug + Display>(
arg_string_path: &T,
) -> String {
let mut string_path = format!("{}", arg_string_path,);
if string_path.starts_with("~") {
string_path = [
shellexpand::tilde("~").to_string(),
string_path.substring(1, string_path.len()).to_string(),
]
.join("")
}
string_path
}
pub fn get_paths_in_dir<T: Debug + Display>(arg_string_path: &T) -> Result<Vec<String>, String> {
let slice_of_read_dirs = match std::fs::read_dir(&format!("{}", arg_string_path,)) {
Ok(data_from_read_dir) => data_from_read_dir,
Err(err) => {
return Err([
"Error: failed to read directory.".to_string(),
format!("err = {}", err,),
format!("arg_string_path_dir = {}", &arg_string_path,),
]
.join("\n"))
}
};
let mut vec_to_return = vec![];
for item_dir_entry_result in slice_of_read_dirs {
vec_to_return.push(match &item_dir_entry_result {
Ok(item_dir_entry_from_result) => match item_dir_entry_from_result.path().to_str() {
Some(str_from_path_buf_to_return) => str_from_path_buf_to_return.to_string(),
None => {
return Err([
"Error: failed to extract str from arg_path_buf".to_string(),
format!(
"item_dir_entry_from_result = {:?}",
&item_dir_entry_from_result,
),
]
.join("\n"))
}
},
Err(err) => {
return Err([
"Error: failed to extract item_dir_entry".to_string(),
format!("err = {}", err,),
format!("item_dir_entry_result = {:?}", &item_dir_entry_result,),
]
.join("\n"))
}
})
}
Ok(vec_to_return)
}
pub fn get_paths_in_dir_and_sub_dirs<T: Debug + Display>(
arg_string_path: &T,
) -> Result<Vec<String>, String> {
let slice_of_read_dirs = match std::fs::read_dir(&format!("{}", arg_string_path,)) {
Ok(data_from_read_dir) => data_from_read_dir,
Err(err) => {
return Err([
"Error: failed to read directory.".to_string(),
format!("err = {}", err,),
format!("arg_string_path = {}", &arg_string_path,),
]
.join("\n"))
}
};
let mut vec_of_string_paths_files_contained_in_dir = vec![];
for item_dir_entry_result in slice_of_read_dirs {
vec_of_string_paths_files_contained_in_dir.push(match &item_dir_entry_result {
Ok(item_dir_entry) => match item_dir_entry.path().to_str() {
Some(str_from_path_buf) => str_from_path_buf.to_string(),
None => {
return Err([
"Error: failed to extract str from arg_path_buf".to_string(),
format!("item_dir_entry = {:?}", &item_dir_entry,),
]
.join("\n"))
}
},
Err(err) => {
return Err([
"Error: failed to extract item_dir_entry".to_string(),
format!("err = {}", err,),
format!("item_dir_entry_result = {:?}", &item_dir_entry_result,),
]
.join("\n"))
}
})
}
let mut stack_of_dir_entries_to_process = Vec::from(vec_of_string_paths_files_contained_in_dir);
let mut vec_to_return: Vec<String> = Vec::new();
loop {
match stack_of_dir_entries_to_process.pop() {
Some(item_string_path_dir) => {
vec_to_return.push(item_string_path_dir.clone());
let metadata_from_path = match std::fs::metadata(&item_string_path_dir) {
Ok(metadata_extracted) => metadata_extracted,
Err(err) => {
return Err([
"Error: failed to get meta data from arg_string_path.".to_string(),
format!("err = {:?}", err,),
format!("arg_string_path = {}", arg_string_path,),
]
.join("\n"))
}
};
if metadata_from_path.is_dir() {
stack_of_dir_entries_to_process.extend({
let string_path_dir = format!("{}", item_string_path_dir,);
let read_dir_results = match std::fs::read_dir(&string_path_dir) {
Ok(data_from_read_dir) => data_from_read_dir,
Err(err) => {
return Err([
"Error: failed to read directory.".to_string(),
format!("err = {}", err,),
format!("string_path_dir = {}", &string_path_dir,),
]
.join("\n"))
}
};
let mut vec_of_results = vec![];
for item_dir_entry_result in read_dir_results {
vec_of_results.push(match &item_dir_entry_result {
Ok(item_dir_entry_from_result) => {
match item_dir_entry_from_result.path().to_str() {
Some(str_from_path_buf) => str_from_path_buf.to_string(),
None => {
return Err([
"Error: failed to extract str from arg_path_buf"
.to_string(),
format!(
"item_dir_entry_from_result.path() = {:?}",
&item_dir_entry_from_result.path(),
),
]
.join("\n"))
}
}
}
Err(err) => {
return Err([
"Error: failed to extract item_dir_entry".to_string(),
format!("err = {}", err,),
format!(
"item_dir_entry_result = {:?}",
&item_dir_entry_result,
),
]
.join("\n"))
}
})
}
vec_of_results
});
}
}
None => break,
}
}
Ok(vec_to_return)
}
pub fn get_paths_sorted_by_size_starting_with_shortest<T: Debug + Display>(
arg_slice_of_strings: &[T],
) -> Result<Vec<String>, String> {
let vec_of_path_bufs =
get_path_bufs_sorted_by_size_starting_with_shortest(&arg_slice_of_strings);
let mut vec_to_return = vec![];
for item_path_buf in vec_of_path_bufs {
match item_path_buf.to_str() {
Some(str_result) => vec_to_return.push(str_result.to_string()),
None => {
return Err([
"Error: failed to extract str from PathBuf".to_string(),
format!("item_path_buf = {:?}", item_path_buf,),
]
.join("\n"))
}
}
}
Ok(vec_to_return)
}
pub fn get_paths_to_only_dirs_in_dir_and_sub_dirs<T: Display>(
arg_string_path_dir: &T,
) -> Result<Vec<String>, String> {
Ok(
match get_paths_in_dir_and_sub_dirs(&format!("{}", arg_string_path_dir,)) {
Ok(result) => result,
Err(err) => return Err(err),
}
.iter()
.filter(|item_string_path| Path::new(&format!("{}", item_string_path,)).is_dir())
.map(|item_string_path| item_string_path.clone())
.collect::<Vec<String>>(),
)
}
pub fn get_paths_to_only_files_in_dir_and_sub_dirs<T: Display>(
arg_string_path_dir: &T,
) -> Result<Vec<String>, String> {
Ok(
match get_paths_in_dir_and_sub_dirs(&format!("{}", arg_string_path_dir,)) {
Ok(result) => result,
Err(err) => return Err(err),
}
.iter()
.filter(|item_string_path| Path::new(&format!("{}", item_string_path,)).is_file())
.map(|item_string_path| item_string_path.clone())
.collect::<Vec<String>>(),
)
}
pub fn get_relative_path<T1: Debug + Display, T2: Debug + Display>(
arg_string_path: &T1,
arg_string_path_root_prefix: &T2,
) -> Result<String, String> {
match PathBuf::from(format!("{}", arg_string_path,))
.strip_prefix(&PathBuf::from(format!("{}", arg_string_path_root_prefix,)))
{
Ok(path_result) => match path_result.to_str() {
Some(str_result) => Ok(str_result.to_string()),
None => {
return Err([
"Error: failed getting str from path.".to_string(),
format!("path_relative (datatype: Path) = {:?}", path_result,),
]
.join("\n"))
}
},
Err(err) => {
return Err([
"Error: strip_prefix() failed.".to_string(),
format!("err = {}", err,),
format!("arg_string_path = {}", arg_string_path,),
format!(
"arg_string_path_root_prefix = {}",
arg_string_path_root_prefix,
),
]
.join("\n"))
}
}
}
pub fn get_vec_by_splitting_path<T: Debug + Display>(arg_string_path: &T) -> Option<Vec<String>> {
let mut vec_to_return = vec![];
for item_os_str in PathBuf::from(format!("{}", arg_string_path,)).iter() {
match item_os_str.to_str() {
Some(str_result) => vec_to_return.push(str_result.to_string()),
None => return None,
}
}
Some(vec_to_return)
}
pub fn are_paths_the_same<T1: Debug + Display, T2: Debug + Display, T3: Debug + Display>(
arg_string_path_left: &T1,
arg_string_path_right: &T2,
arg_string_path_working_dir: &T3,
) -> bool {
let path_buf_working_dir = PathBuf::from(format!("{}", arg_string_path_working_dir,));
let path_buf_left = {
let path_buf_from_arg = PathBuf::from(format!("{}", arg_string_path_left,));
if path_buf_from_arg.is_absolute() {
path_buf_from_arg
} else {
[&path_buf_working_dir, &path_buf_from_arg]
.iter()
.collect::<PathBuf>()
}
};
let path_buf_right = {
let path_buf_from_arg = PathBuf::from(format!("{}", arg_string_path_right,));
if path_buf_from_arg.is_absolute() {
PathBuf::from(format!("{}", arg_string_path_right,))
} else {
[&path_buf_working_dir, &path_buf_from_arg]
.iter()
.collect::<PathBuf>()
}
};
path_buf_left == path_buf_right
}
pub fn are_paths_the_same_assume_cwd<T1: Debug + Display, T2: Debug + Display>(
arg_string_path_left: &T1,
arg_string_path_right: &T2,
) -> Result<bool, String> {
Ok(are_paths_the_same(
&arg_string_path_left,
&arg_string_path_right,
&match get_dir_cwd() {
Ok(string_result) => string_result,
Err(err) => return Err(err),
},
))
}
pub fn are_paths_the_same_assume_project_dir<T1: Debug + Display, T2: Debug + Display>(
arg_string_path_left: &T1,
arg_string_path_right: &T2,
) -> bool {
are_paths_the_same(
&arg_string_path_left,
&arg_string_path_right,
&env!("CARGO_MANIFEST_DIR"),
)
}
pub fn has_parent<T: Debug + Display>(arg_string_path: &T) -> bool {
match PathBuf::from(format!("{}", arg_string_path)).parent() {
Some(_result) => true,
None => false,
}
}
pub fn is_absolute<T: Debug + Display>(arg_string_path: &T) -> bool {
PathBuf::from(format!("{}", arg_string_path,)).is_absolute()
}
pub fn is_dir<T: Debug + Display>(arg_string_path: &T) -> bool {
return PathBuf::from(format!("{}", arg_string_path,)).is_dir();
}
pub fn is_existing_path<T: Debug + Display>(arg_string_path: &T) -> bool {
return PathBuf::from(format!("{}", arg_string_path,)).exists();
}
pub fn is_file<T: Debug + Display>(arg_string_path: &T) -> bool {
return PathBuf::from(format!("{}", arg_string_path,)).is_file();
}
pub fn is_path_type<T>(_arg: &T) -> bool {
std::any::type_name::<T>()
.to_string()
.ends_with("std::path::Path")
}
pub fn is_path_buf_type<T>(_arg: &T) -> bool {
std::any::type_name::<T>()
.to_string()
.ends_with("std::path::PathBuf")
}
pub fn is_path_inside_dir_parent<T1: Display, T2: Display>(
arg_string_path: &T1,
arg_string_dir_parent: &T2,
) -> bool {
Path::new(&format!("{}", arg_string_path,)).starts_with(format!("{}", arg_string_dir_parent,))
}
pub fn raise_error_if_path_does_not_exist<T: Debug + Display>(
arg_string_path: &T,
) -> Result<(), String> {
if !Path::new(format!("{}", arg_string_path,).as_str()).exists() {
return Err(
[
"Error: path does not exist.".to_string(),
format!("arg_string_path = {}", arg_string_path,),
match get_dir_ancestor_that_exists(&arg_string_path) {
Some(string_result) => {
format!("ancestor that actually exists = {}", string_result,)
}
None => format!("No existing ancestor exists."),
},
]
.join("\n"),
);
}
Ok(())
}
pub fn raise_error_if_path_is_not_in_project<T: Debug + Display>(
arg_string_path: &T,
) -> Result<(), String> {
let path_buf_control = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let bool_raise_error = {
let path_buf_from_arg = PathBuf::from(format!("{}", arg_string_path,));
if path_buf_from_arg.is_absolute() {
!path_buf_from_arg.starts_with(&path_buf_control)
} else {
![&path_buf_control, &path_buf_from_arg]
.iter()
.collect::<PathBuf>()
.exists()
}
};
if bool_raise_error {
return Err(
[
"Error: arg_string_path is either the project directory or outside it.".to_string(),
format!("arg_string_path = {}", arg_string_path,),
format!("path_buf_control = {:?}", path_buf_control,),
]
.join("\n"),
);
}
Ok(())
}
pub fn raise_error_if_path_points_to_project_root<T: Display>(
arg_string_path: &T,
) -> Result<(), String> {
if Path::new(&format!("{}", arg_string_path,))
== Path::new(&env!("CARGO_MANIFEST_DIR").to_string())
{
return Err(
[
"Error: arg_string_path points at project root directory.".to_string(),
format!("arg_string_path = {}", arg_string_path,),
]
.join("\n"),
);
}
Ok(())
}
pub fn raise_error_if_path_points_to_src<T: Debug + Display>(
arg_string_path: &T,
) -> Result<(), String> {
if are_paths_the_same_assume_project_dir(arg_string_path, &"src") {
return Err(
[
"Error: arg_string_path points at the src directory.".to_string(),
format!("arg_string_path = {}", arg_string_path,),
]
.join("\n"),
);
}
Ok(())
}
pub fn raise_error_if_path_points_to_cargo_toml<T: Debug + Display>(
arg_string_path: &T,
) -> Result<(), String> {
if are_paths_the_same_assume_project_dir(arg_string_path, &"Cargo.toml") {
return Err(
[
"Error: arg_string_path points at Cargo.toml.".to_string(),
format!("arg_string_path = {}", &arg_string_path,),
]
.join("\n"),
);
}
Ok(())
}
pub fn raise_error_if_path_points_to_main_rs<T: Debug + Display>(
arg_string_path: &T,
) -> Result<(), String> {
if are_paths_the_same_assume_project_dir(arg_string_path, &"src/main.rs") {
return Err(
[
"Error: arg_string_path points at main.rs.".to_string(),
format!("arg_string_path = {}", arg_string_path,),
]
.join("\n"),
);
}
Ok(())
}
pub fn get_path_buf_from_type_string<T: Debug + Display>(arg_string: &T) -> PathBuf {
PathBuf::from(format!("{}", arg_string,))
}
pub fn get_string_from_type_dir_entry(arg_dir_entry: &DirEntry) -> Option<String> {
match arg_dir_entry.path().to_str() {
Some(str_result) => Some(str_result.to_string()),
None => None,
}
}
pub fn get_string_from_type_osstr(arg_osstr: &OsStr) -> Option<String> {
match arg_osstr.to_str() {
Some(str_result) => Some(str_result.to_string()),
None => None,
}
}
pub fn get_string_from_type_path(arg_path: &Path) -> Option<String> {
match arg_path.to_str() {
Some(str_result) => Some(str_result.to_string()),
None => None,
}
}
pub fn get_string_from_type_path_buf(arg_path_buf: &PathBuf) -> Option<String> {
match arg_path_buf.to_str() {
Some(str_result) => Some(str_result.to_string()),
None => None,
}
}
fn get_path_bufs_sorted_by_size_starting_with_shortest<T: Debug + Display>(
arg_slice_of_strings: &[T],
) -> Vec<PathBuf> {
let mut vec_of_path_bufs = arg_slice_of_strings
.iter()
.map(|item| PathBuf::from(format!("{}", item)))
.collect::<Vec<PathBuf>>();
vec_of_path_bufs.sort_by(|item_path_buf_left, item_path_buf_right| {
item_path_buf_left.cmp(item_path_buf_right)
});
vec_of_path_bufs
}