1 | use crate::finder::Checker; |
2 | use std::fs; |
3 | use std::path::Path; |
4 | |
5 | pub struct ExecutableChecker; |
6 | |
7 | impl ExecutableChecker { |
8 | pub fn new() -> ExecutableChecker { |
9 | ExecutableChecker |
10 | } |
11 | } |
12 | |
13 | impl 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 | |
26 | pub struct ExistedChecker; |
27 | |
28 | impl ExistedChecker { |
29 | pub fn new() -> ExistedChecker { |
30 | ExistedChecker |
31 | } |
32 | } |
33 | |
34 | impl 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 | |
53 | pub struct CompositeChecker { |
54 | checkers: Vec<Box<dyn Checker>>, |
55 | } |
56 | |
57 | impl 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 | |
70 | impl 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 | |