use super::types::ArchiveType;
pub fn detect_archive_type(path: &str) -> Option<ArchiveType> {
let lower = path.to_lowercase();
if lower.ends_with(".zip") {
Some(ArchiveType::Zip)
} else if lower.ends_with(".tar.gz") || lower.ends_with(".tgz") {
Some(ArchiveType::TarGz)
} else if lower.ends_with(".tar.bz2") || lower.ends_with(".tbz2") {
Some(ArchiveType::TarBz2)
} else if lower.ends_with(".tar.xz") || lower.ends_with(".txz") {
Some(ArchiveType::TarXz)
} else if lower.ends_with(".tar") {
Some(ArchiveType::Tar)
} else if lower.ends_with(".7z") {
Some(ArchiveType::SevenZip)
} else if lower.ends_with(".rar") {
Some(ArchiveType::Rar)
} else {
None
}
}
pub fn detect_by_magic(data: &[u8]) -> Option<ArchiveType> {
if data.len() < 8 {
return None;
}
match &data[..4] {
[0x50, 0x4B, 0x03, 0x04] => Some(ArchiveType::Zip),
[0x1F, 0x8B, _, _] => Some(ArchiveType::TarGz),
[0x42, 0x5A, _, _] => Some(ArchiveType::TarBz2),
[0xFD, 0x37, 0x7A, 0x58] => Some(ArchiveType::TarXz),
[0x37, 0x7A, 0xBC, 0xAF] => Some(ArchiveType::SevenZip),
[0x52, 0x61, 0x72, 0x21] => Some(ArchiveType::Rar),
_ => {
if data.len() >= 263 && &data[257..262] == b"ustar" {
Some(ArchiveType::Tar)
} else {
None
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_detect_by_extension() {
assert_eq!(detect_archive_type("file.zip"), Some(ArchiveType::Zip));
assert_eq!(detect_archive_type("file.tar.gz"), Some(ArchiveType::TarGz));
assert_eq!(detect_archive_type("file.tgz"), Some(ArchiveType::TarGz));
assert_eq!(detect_archive_type("file.tar"), Some(ArchiveType::Tar));
assert_eq!(detect_archive_type("file.7z"), Some(ArchiveType::SevenZip));
assert_eq!(detect_archive_type("file.txt"), None);
}
#[test]
fn test_detect_by_magic() {
assert_eq!(
detect_by_magic(&[0x50, 0x4B, 0x03, 0x04, 0, 0, 0, 0]),
Some(ArchiveType::Zip)
);
assert_eq!(
detect_by_magic(&[0x1F, 0x8B, 0x08, 0x00, 0, 0, 0, 0]),
Some(ArchiveType::TarGz)
);
}
}