Improve the search_for
utilty function, and remove the recursive
This commit is contained in:
parent
eb78da0a71
commit
dfc198e55e
1 changed files with 45 additions and 19 deletions
62
src/utils.rs
62
src/utils.rs
|
@ -7,16 +7,38 @@ use std::path::Path;
|
||||||
pub fn search_for(
|
pub fn search_for(
|
||||||
search_directory: &str,
|
search_directory: &str,
|
||||||
max_depth: u8,
|
max_depth: u8,
|
||||||
regx: &str,
|
regx: ®ex::Regex,
|
||||||
) -> Result<Option<String>, String> {
|
) -> std::io::Result<Option<String>> {
|
||||||
// Search in the track directory.
|
let mut max_depth = max_depth;
|
||||||
for entry in std::fs::read_dir(search_directory).map_err(|e| e.to_string())? {
|
let mut search_directory = search_directory;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(path) = search(search_directory, regx)? {
|
||||||
|
return Ok(Some(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if max_depth == 0 {
|
||||||
|
break Ok(None);
|
||||||
|
} else {
|
||||||
|
// If the max depth is not reached, search in the parent directory.
|
||||||
|
max_depth -= 1;
|
||||||
|
search_directory = {
|
||||||
|
let Some(parent) = Path::new(search_directory).parent() else { return Ok(None); };
|
||||||
|
let Some(parent) = parent.to_str() else { return Ok(None); };
|
||||||
|
parent
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn search(search_directory: &str, matcher: ®ex::Regex) -> std::io::Result<Option<String>> {
|
||||||
|
for entry in std::fs::read_dir(search_directory)? {
|
||||||
let Ok(entry) = entry else { continue; };
|
let Ok(entry) = entry else { continue; };
|
||||||
let Ok(file_type) = entry.file_type() else { continue; };
|
let Ok(file_type) = entry.file_type() else { continue; };
|
||||||
if file_type.is_file() {
|
if file_type.is_file() {
|
||||||
let Ok(file_name) = entry.file_name().into_string() else { continue; };
|
let Ok(file_name) = entry.file_name().into_string() else { continue; };
|
||||||
// Check if the file name matches the regular expression.
|
// Check if the file name matches the regular expression.
|
||||||
let matcher = regex::Regex::new(regx).map_err(|e| e.to_string())?;
|
|
||||||
if matcher.is_match(&file_name) {
|
if matcher.is_match(&file_name) {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
let Some(path) = path.to_str() else { continue; };
|
let Some(path) = path.to_str() else { continue; };
|
||||||
|
@ -24,15 +46,7 @@ pub fn search_for(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the max depth is reached, return `None`.
|
|
||||||
if max_depth == 0 {
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else {
|
|
||||||
// If the max depth is not reached, search in the parent directory (recursively).
|
|
||||||
let Some(parent) = Path::new(search_directory).parent() else { return Ok(None); };
|
|
||||||
let Some(parent) = parent.to_str() else { return Ok(None); };
|
|
||||||
search_for(parent, max_depth - 1, regx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace all the placeholders in the template with their matching value.
|
/// Replace all the placeholders in the template with their matching value.
|
||||||
|
@ -101,7 +115,7 @@ mod tests {
|
||||||
let cover_path = search_for(
|
let cover_path = search_for(
|
||||||
"tests/samples/Owl City/Cinematic/cover",
|
"tests/samples/Owl City/Cinematic/cover",
|
||||||
1,
|
1,
|
||||||
r"cover|.\.jpg|.\.png",
|
®ex::Regex::new(r"cover|.\.jpg|.\.png").unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_matches!(cover_path, Ok(Some(_)));
|
assert_matches!(cover_path, Ok(Some(_)));
|
||||||
|
@ -114,7 +128,10 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_search_for_cover_without_the_cover_key_world() {
|
fn test_search_for_cover_without_the_cover_key_world() {
|
||||||
let cover_path = search_for(
|
let cover_path = search_for(
|
||||||
"tests/samples/Owl City/Cinematic/cover", 1, r".\.jpg|.\.png");
|
"tests/samples/Owl City/Cinematic/cover",
|
||||||
|
1,
|
||||||
|
®ex::Regex::new(r".\.jpg|.\.png").unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
assert_matches!(cover_path, Ok(Some(_)));
|
assert_matches!(cover_path, Ok(Some(_)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -126,7 +143,10 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_search_for_cover_without_the_cover_key_world_and_jpg() {
|
fn test_search_for_cover_without_the_cover_key_world_and_jpg() {
|
||||||
let cover_path = search_for(
|
let cover_path = search_for(
|
||||||
"tests/samples/Owl City/Cinematic/cover", 1, r".\.png");
|
"tests/samples/Owl City/Cinematic/cover",
|
||||||
|
1,
|
||||||
|
®ex::Regex::new(r".\.png").unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
assert_matches!(cover_path, Ok(Some(_)));
|
assert_matches!(cover_path, Ok(Some(_)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -138,7 +158,10 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_search_for_lrc_file_started_from_the_cover_directory() {
|
fn test_search_for_lrc_file_started_from_the_cover_directory() {
|
||||||
let lrc_path = search_for(
|
let lrc_path = search_for(
|
||||||
"tests/samples/Owl City/Cinematic/cover", 1, r".\.lrc");
|
"tests/samples/Owl City/Cinematic/cover",
|
||||||
|
1,
|
||||||
|
®ex::Regex::new(r".\.lrc").unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
assert_matches!(lrc_path, Ok(Some(_)));
|
assert_matches!(lrc_path, Ok(Some(_)));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -150,7 +173,10 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_search_for_not_exits_file() {
|
fn test_search_for_not_exits_file() {
|
||||||
let result = search_for(
|
let result = search_for(
|
||||||
"tests/samples/Owl City/Cinematic/cover", 3, r".\.mp3");
|
"tests/samples/Owl City/Cinematic/cover",
|
||||||
|
3,
|
||||||
|
®ex::Regex::new(r".\.mp3").unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
assert_matches!(result, Ok(None));
|
assert_matches!(result, Ok(None));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue