image_optimizer/file_ops/
image_scanner.rs1use std::ffi::OsStr;
2use std::path::PathBuf;
3use walkdir::WalkDir;
4
5const SUPPORTED_EXTENSIONS: &[&str] = &["jpg", "jpeg", "png", "webp", "svg"];
7
8pub fn scan_images(path: &std::path::Path, recursive: bool) -> Vec<PathBuf> {
47 let mut image_files = Vec::new();
48
49 if path.is_file() {
50 if let Some(extension) = path.extension().and_then(OsStr::to_str)
51 && SUPPORTED_EXTENSIONS.contains(&extension.to_lowercase().as_str())
52 {
53 image_files.push(path.to_path_buf());
54 }
55 return image_files;
56 }
57
58 let walker = if recursive {
59 WalkDir::new(path)
60 } else {
61 WalkDir::new(path).max_depth(1)
62 };
63
64 for entry in walker.into_iter().filter_map(Result::ok) {
65 if entry.file_type().is_file()
66 && let Some(extension) = entry.path().extension().and_then(OsStr::to_str)
67 && SUPPORTED_EXTENSIONS.contains(&extension.to_lowercase().as_str())
68 {
69 image_files.push(entry.path().to_path_buf());
70 }
71 }
72
73 image_files
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use std::fs;
80 use std::path::Path;
81
82 #[test]
83 fn test_supported_extensions() {
84 assert!(SUPPORTED_EXTENSIONS.contains(&"jpg"));
85 assert!(SUPPORTED_EXTENSIONS.contains(&"jpeg"));
86 assert!(SUPPORTED_EXTENSIONS.contains(&"png"));
87 assert!(SUPPORTED_EXTENSIONS.contains(&"webp"));
88 assert!(SUPPORTED_EXTENSIONS.contains(&"svg"));
89 assert!(!SUPPORTED_EXTENSIONS.contains(&"gif"));
90 assert!(!SUPPORTED_EXTENSIONS.contains(&"txt"));
91 }
92
93 #[test]
94 fn test_scan_single_file() {
95 let temp_dir = std::env::temp_dir();
96 let test_file = temp_dir.join("test.jpg");
97 fs::write(&test_file, "fake jpg content").unwrap();
98
99 let result = scan_images(&test_file, false);
100 assert_eq!(result.len(), 1);
101 assert_eq!(result[0], test_file);
102
103 fs::remove_file(&test_file).unwrap();
104 }
105
106 #[test]
107 fn test_scan_unsupported_file() {
108 let temp_dir = std::env::temp_dir();
109 let test_file = temp_dir.join("test.txt");
110 fs::write(&test_file, "text content").unwrap();
111
112 let result = scan_images(&test_file, false);
113 assert_eq!(result.len(), 0);
114
115 fs::remove_file(&test_file).unwrap();
116 }
117
118 #[test]
119 fn test_scan_nonexistent_path() {
120 let nonexistent = Path::new("/nonexistent/path");
121 let result = scan_images(nonexistent, false);
122 assert_eq!(result.len(), 0);
123 }
124
125 #[test]
126 fn test_case_insensitive_extensions() {
127 let temp_dir = std::env::temp_dir();
128 let test_files = [
129 ("test_upper.JPG", "jpg"),
130 ("test_upper.JPEG", "jpeg"),
131 ("test_upper.PNG", "png"),
132 ("test_upper.WEBP", "webp"),
133 ("test_upper.SVG", "svg"),
134 ];
135
136 for (filename, _) in &test_files {
137 let test_file = temp_dir.join(filename);
138 fs::write(&test_file, "fake content").unwrap();
139
140 let result = scan_images(&test_file, false);
141 assert_eq!(result.len(), 1, "Failed for file: {}", filename);
142 assert_eq!(result[0], test_file);
143
144 fs::remove_file(&test_file).unwrap();
145 }
146 }
147}