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 && (path.extension().is_some() || matches_arch(path))
44 }
45
46 #[cfg(not(target_os = "windows"))]
47 fn is_valid(&self, path: &Path) -> bool {
48 fs::metadata(path)
49 .map(|metadata| metadata.is_file())
50 .unwrap_or(default:false)
51 }
52}
53
54#[cfg(target_os = "windows")]
55fn matches_arch(path: &Path) -> bool {
56 use std::os::windows::prelude::OsStrExt;
57
58 let os_str = path
59 .as_os_str()
60 .encode_wide()
61 .chain(std::iter::once(0))
62 .collect::<Vec<u16>>();
63 let mut out = 0;
64 let is_executable = unsafe {
65 windows_sys::Win32::Storage::FileSystem::GetBinaryTypeW(os_str.as_ptr(), &mut out)
66 };
67 is_executable != 0
68}
69
70pub struct CompositeChecker {
71 checkers: Vec<Box<dyn Checker>>,
72}
73
74impl CompositeChecker {
75 pub fn new() -> CompositeChecker {
76 CompositeChecker {
77 checkers: Vec::new(),
78 }
79 }
80
81 pub fn add_checker(mut self, checker: Box<dyn Checker>) -> CompositeChecker {
82 self.checkers.push(checker);
83 self
84 }
85}
86
87impl Checker for CompositeChecker {
88 fn is_valid(&self, path: &Path) -> bool {
89 self.checkers.iter().all(|checker: &Box| checker.is_valid(path))
90 }
91}
92