shadowforge_lib/domain/archive/
mod.rs1use crate::domain::types::ArchiveFormat;
6
7#[must_use]
11pub fn detect_format(data: &[u8]) -> Option<ArchiveFormat> {
12 if data.first() == Some(&0x50) && data.get(1) == Some(&0x4B) {
13 Some(ArchiveFormat::Zip)
15 } else if data.first() == Some(&0x1F) && data.get(1) == Some(&0x8B) {
16 Some(ArchiveFormat::TarGz)
18 } else if data.len() >= 263 && data.get(257..262) == Some(b"ustar") {
19 Some(ArchiveFormat::Tar)
21 } else {
22 None
23 }
24}
25
26pub const MAX_NESTING_DEPTH: u8 = 3;
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 type TestResult = Result<(), Box<dyn std::error::Error>>;
34
35 #[test]
36 fn detect_zip_by_magic() {
37 let data = [0x50, 0x4B, 0x03, 0x04, 0, 0, 0, 0];
38 assert_eq!(detect_format(&data), Some(ArchiveFormat::Zip));
39 }
40
41 #[test]
42 fn detect_tar_gz_by_magic() {
43 let data = [0x1F, 0x8B, 0, 0];
44 assert_eq!(detect_format(&data), Some(ArchiveFormat::TarGz));
45 }
46
47 #[test]
48 fn detect_tar_by_ustar() -> TestResult {
49 let mut data = vec![0u8; 300];
50 data.get_mut(257..262)
51 .ok_or("slice out of bounds")?
52 .copy_from_slice(b"ustar");
53 assert_eq!(detect_format(&data), Some(ArchiveFormat::Tar));
54 Ok(())
55 }
56
57 #[test]
58 fn detect_unknown_returns_none() {
59 let data = [0xFF, 0xFE, 0x00, 0x01];
60 assert_eq!(detect_format(&data), None);
61 }
62
63 #[test]
64 fn detect_empty_returns_none() {
65 assert_eq!(detect_format(&[]), None);
66 }
67}