notify_debouncer_full/
cache.rs1use std::{
2 collections::HashMap,
3 path::{Path, PathBuf},
4};
5
6use file_id::{get_file_id, FileId};
7use notify::RecursiveMode;
8use walkdir::WalkDir;
9
10pub trait FileIdCache {
14 fn cached_file_id(&self, path: &Path) -> Option<impl AsRef<FileId>>;
18
19 fn add_path(&mut self, path: &Path, recursive_mode: RecursiveMode);
23
24 fn remove_path(&mut self, path: &Path);
28
29 fn rescan(&mut self, root_paths: &[(PathBuf, RecursiveMode)]) {
36 for (path, recursive_mode) in root_paths {
37 self.add_path(path, *recursive_mode);
38 }
39 }
40}
41
42#[derive(Debug, Clone, Default)]
47pub struct FileIdMap {
48 paths: HashMap<PathBuf, FileId>,
49}
50
51impl FileIdMap {
52 pub fn new() -> Self {
54 Default::default()
55 }
56
57 fn dir_scan_depth(is_recursive: bool) -> usize {
58 if is_recursive {
59 usize::MAX
60 } else {
61 1
62 }
63 }
64}
65
66impl FileIdCache for FileIdMap {
67 fn cached_file_id(&self, path: &Path) -> Option<impl AsRef<FileId>> {
68 self.paths.get(path)
69 }
70
71 fn add_path(&mut self, path: &Path, recursive_mode: RecursiveMode) {
72 let is_recursive = recursive_mode == RecursiveMode::Recursive;
73
74 for (path, file_id) in WalkDir::new(path)
75 .follow_links(true)
76 .max_depth(Self::dir_scan_depth(is_recursive))
77 .into_iter()
78 .filter_map(|entry| {
79 let path = entry.ok()?.into_path();
80 let file_id = get_file_id(&path).ok()?;
81 Some((path, file_id))
82 })
83 {
84 self.paths.insert(path, file_id);
85 }
86 }
87
88 fn remove_path(&mut self, path: &Path) {
89 self.paths.retain(|p, _| !p.starts_with(path));
90 }
91}
92
93#[derive(Debug, Clone, Default)]
97pub struct NoCache;
98
99impl NoCache {
100 pub fn new() -> Self {
102 Default::default()
103 }
104}
105
106impl FileIdCache for NoCache {
107 fn cached_file_id(&self, _path: &Path) -> Option<impl AsRef<FileId>> {
108 Option::<&FileId>::None
109 }
110
111 fn add_path(&mut self, _path: &Path, _recursive_mode: RecursiveMode) {}
112
113 fn remove_path(&mut self, _path: &Path) {}
114}
115
116#[cfg(any(target_os = "linux", target_os = "android"))]
118pub type RecommendedCache = NoCache;
119#[cfg(not(any(target_os = "linux", target_os = "android")))]
121pub type RecommendedCache = FileIdMap;