neural_shared/scanner/
mod.rs1use crate::Result;
4use ignore::WalkBuilder;
5use std::path::{Path, PathBuf};
6
7pub struct Scanner {
9 root: PathBuf,
10}
11
12impl Scanner {
13 pub fn new(root: impl AsRef<Path>) -> Self {
15 Self {
16 root: root.as_ref().to_path_buf(),
17 }
18 }
19
20 pub fn scan(&self) -> Result<Vec<PathBuf>> {
22 let mut files = Vec::new();
23
24 for result in WalkBuilder::new(&self.root)
25 .hidden(false) .git_ignore(true) .build()
28 {
29 let entry = result?;
30 let path = entry.path();
31
32 if self.is_supported_file(path) {
33 files.push(path.to_path_buf());
34 }
35 }
36
37 Ok(files)
38 }
39
40 fn is_supported_file(&self, path: &Path) -> bool {
42 if !path.is_file() {
43 return false;
44 }
45
46 path.extension()
47 .and_then(|ext| ext.to_str())
48 .map(|ext| matches!(ext, "py" | "ts" | "tsx" | "js" | "jsx"))
49 .unwrap_or(false)
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn test_is_supported_file() {
59 use std::fs;
60 use tempfile::tempdir;
61
62 let dir = tempdir().unwrap();
63 let scanner = Scanner::new(dir.path());
64
65 let py_file = dir.path().join("test.py");
67 let ts_file = dir.path().join("test.ts");
68 let tsx_file = dir.path().join("test.tsx");
69 let rs_file = dir.path().join("test.rs");
70 let txt_file = dir.path().join("test.txt");
71
72 fs::write(&py_file, "").unwrap();
73 fs::write(&ts_file, "").unwrap();
74 fs::write(&tsx_file, "").unwrap();
75 fs::write(&rs_file, "").unwrap();
76 fs::write(&txt_file, "").unwrap();
77
78 assert!(scanner.is_supported_file(&py_file));
79 assert!(scanner.is_supported_file(&ts_file));
80 assert!(scanner.is_supported_file(&tsx_file));
81 assert!(!scanner.is_supported_file(&rs_file));
82 assert!(!scanner.is_supported_file(&txt_file));
83 }
84}