pub(crate) fn is_first_rar_volume(filename: &str) -> bool {
let lower = filename.to_lowercase();
if lower.ends_with(".rar") {
if let Some(stem) = lower.strip_suffix(".rar")
&& let Some(part_idx) = stem.rfind(".part")
{
let num_str = &stem[part_idx + 5..]; if !num_str.is_empty() && num_str.chars().all(|c| c.is_ascii_digit()) {
let num: u32 = num_str.parse().unwrap_or(0);
return num == 1;
}
}
return true;
}
false
}
#[allow(dead_code)]
pub(crate) fn is_rar_file(filename: &str) -> bool {
let lower = filename.to_lowercase();
if lower.ends_with(".rar") {
return true;
}
if lower.len() >= 4 {
let ext = &lower[lower.len() - 4..];
if ext.starts_with(".r") && ext[2..].chars().all(|c| c.is_ascii_digit()) {
return true;
}
}
false
}
pub(crate) fn is_par2_file(filename: &str) -> bool {
let lower = filename.to_lowercase();
lower.ends_with(".par2")
}
#[allow(clippy::unwrap_used, clippy::expect_used)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn plain_rar_is_first_volume() {
assert!(is_first_rar_volume("movie.rar"));
assert!(is_first_rar_volume("Movie.RAR"));
assert!(is_first_rar_volume("some.file.name.rar"));
}
#[test]
fn part01_rar_is_first_volume() {
assert!(is_first_rar_volume("movie.part01.rar"));
assert!(is_first_rar_volume("movie.part001.rar"));
assert!(is_first_rar_volume("movie.part0001.rar"));
assert!(is_first_rar_volume("movie.part1.rar"));
assert!(is_first_rar_volume("Movie.Part01.RAR"));
}
#[test]
fn part02_rar_is_not_first_volume() {
assert!(!is_first_rar_volume("movie.part02.rar"));
assert!(!is_first_rar_volume("movie.part002.rar"));
assert!(!is_first_rar_volume("movie.part10.rar"));
assert!(!is_first_rar_volume("movie.part2.rar"));
}
#[test]
fn old_style_split_is_not_first_volume() {
assert!(!is_first_rar_volume("movie.r00"));
assert!(!is_first_rar_volume("movie.r01"));
assert!(!is_first_rar_volume("movie.r99"));
}
#[test]
fn non_rar_files_are_not_first_volume() {
assert!(!is_first_rar_volume("movie.mkv"));
assert!(!is_first_rar_volume("movie.par2"));
assert!(!is_first_rar_volume("movie.zip"));
assert!(!is_first_rar_volume("movie.7z"));
}
#[test]
fn is_rar_file_detects_all_rar_extensions() {
assert!(is_rar_file("movie.rar"));
assert!(is_rar_file("movie.part01.rar"));
assert!(is_rar_file("movie.r00"));
assert!(is_rar_file("movie.r01"));
assert!(is_rar_file("movie.r99"));
assert!(is_rar_file("Movie.RAR"));
}
#[test]
fn is_rar_file_rejects_non_rar() {
assert!(!is_rar_file("movie.mkv"));
assert!(!is_rar_file("movie.par2"));
assert!(!is_rar_file("movie.zip"));
}
#[test]
fn is_par2_file_works() {
assert!(is_par2_file("movie.par2"));
assert!(is_par2_file("movie.vol00+01.PAR2"));
assert!(!is_par2_file("movie.rar"));
assert!(!is_par2_file("movie.par"));
}
}