parcel_resolver/
invalidations.rs1use std::{
2 cell::{Cell, RefCell},
3 collections::HashSet,
4 hash::BuildHasherDefault,
5 sync::Arc,
6};
7
8use rustc_hash::FxHasher;
9
10use crate::{
11 cache::{CachedPath, IdentityHasher},
12 ResolverError,
13};
14
15#[derive(PartialEq, Eq, Hash, Debug, Clone)]
17pub enum FileCreateInvalidation {
18 Path(CachedPath),
20 FileName {
23 file_name: String,
24 above: CachedPath,
25 },
26 Glob(String),
28}
29
30#[derive(Default, Debug)]
32pub struct Invalidations {
33 pub invalidate_on_file_create:
35 RefCell<HashSet<FileCreateInvalidation, BuildHasherDefault<FxHasher>>>,
36 pub invalidate_on_file_change: RefCell<HashSet<CachedPath, BuildHasherDefault<IdentityHasher>>>,
38 pub invalidate_on_startup: Cell<bool>,
40}
41
42impl Invalidations {
43 pub fn invalidate_on_file_create(&self, path: CachedPath) {
45 self
46 .invalidate_on_file_create
47 .borrow_mut()
48 .insert(FileCreateInvalidation::Path(path));
49 }
50
51 pub fn invalidate_on_file_create_above<S: Into<String>>(&self, file_name: S, above: CachedPath) {
54 self
55 .invalidate_on_file_create
56 .borrow_mut()
57 .insert(FileCreateInvalidation::FileName {
58 file_name: file_name.into(),
59 above,
60 });
61 }
62
63 pub fn invalidate_on_glob_create<S: Into<String>>(&self, glob: S) {
65 self
66 .invalidate_on_file_create
67 .borrow_mut()
68 .insert(FileCreateInvalidation::Glob(glob.into()));
69 }
70
71 pub fn invalidate_on_file_change(&self, invalidation: CachedPath) {
73 self
74 .invalidate_on_file_change
75 .borrow_mut()
76 .insert(invalidation);
77 }
78
79 pub fn invalidate_on_startup(&self) {
81 self.invalidate_on_startup.set(true)
82 }
83
84 pub fn extend(&self, other: &Invalidations) {
86 for f in other.invalidate_on_file_create.borrow().iter() {
87 self
88 .invalidate_on_file_create
89 .borrow_mut()
90 .insert(f.clone());
91 }
92
93 for f in other.invalidate_on_file_change.borrow().iter() {
94 self
95 .invalidate_on_file_change
96 .borrow_mut()
97 .insert(f.clone());
98 }
99
100 if other.invalidate_on_startup.get() {
101 self.invalidate_on_startup();
102 }
103 }
104
105 pub(crate) fn read<V, F: FnOnce() -> Arc<Result<V, ResolverError>>>(
106 &self,
107 path: &CachedPath,
108 f: F,
109 ) -> Arc<Result<V, ResolverError>> {
110 let res = f();
111 match &*res {
112 Ok(_) => {
113 self.invalidate_on_file_change(path.clone());
114 }
115 Err(e) => {
116 if matches!(e, ResolverError::IOError(..)) {
117 self.invalidate_on_file_create(path.clone());
118 }
119 }
120 }
121 res
122 }
123}