1use crate::finder::Checker;
2use std::fs;
3use std::path::Path;
4
5pub struct ExecutableChecker;
6
7impl ExecutableChecker {
8 pub fn new() -> ExecutableChecker {
9 ExecutableChecker
10 }
11}
12
13impl Checker for ExecutableChecker {
14 #[cfg(any(unix, target_os = "wasi"))]
15 fn is_valid(&self, path: &Path) -> bool {
16 use rustix::fs as rfs;
17 rfs::access(path, access:rfs::Access::EXEC_OK).is_ok()
18 }
19
20 #[cfg(windows)]
21 fn is_valid(&self, _path: &Path) -> bool {
22 true
23 }
24}
25
26pub struct ExistedChecker;
27
28impl ExistedChecker {
29 pub fn new() -> ExistedChecker {
30 ExistedChecker
31 }
32}
33
34impl Checker for ExistedChecker {
35 #[cfg(target_os = "windows")]
36 fn is_valid(&self, path: &Path) -> bool {
37 fs::symlink_metadata(path)
38 .map(|metadata| {
39 let file_type = metadata.file_type();
40 file_type.is_file() || file_type.is_symlink()
41 })
42 .unwrap_or(false)
43 }
44
45 #[cfg(not(target_os = "windows"))]
46 fn is_valid(&self, path: &Path) -> bool {
47 fs::metadata(path)
48 .map(|metadata| metadata.is_file())
49 .unwrap_or(default:false)
50 }
51}
52
53pub struct CompositeChecker {
54 checkers: Vec<Box<dyn Checker>>,
55}
56
57impl CompositeChecker {
58 pub fn new() -> CompositeChecker {
59 CompositeChecker {
60 checkers: Vec::new(),
61 }
62 }
63
64 pub fn add_checker(mut self, checker: Box<dyn Checker>) -> CompositeChecker {
65 self.checkers.push(checker);
66 self
67 }
68}
69
70impl Checker for CompositeChecker {
71 fn is_valid(&self, path: &Path) -> bool {
72 self.checkers.iter().all(|checker: &Box| checker.is_valid(path))
73 }
74}
75