turbopack_core/
condition.rs1use bincode::{Decode, Encode};
2use turbo_tasks::{NonLocalValue, trace::TraceRawVcs};
3use turbo_tasks_fs::FileSystemPath;
4
5#[derive(Debug, Clone, TraceRawVcs, PartialEq, Eq, NonLocalValue, Encode, Decode)]
6pub enum ContextCondition {
7 All(Vec<ContextCondition>),
8 Any(Vec<ContextCondition>),
9 Not(Box<ContextCondition>),
10 InDirectory(String),
11 InNodeModules,
14 InPath(FileSystemPath),
15}
16
17impl ContextCondition {
18 pub fn all(conditions: Vec<ContextCondition>) -> ContextCondition {
20 ContextCondition::All(conditions)
21 }
22
23 pub fn any(conditions: Vec<ContextCondition>) -> ContextCondition {
25 ContextCondition::Any(conditions)
26 }
27
28 #[allow(clippy::should_implement_trait)]
30 pub fn not(condition: ContextCondition) -> ContextCondition {
31 ContextCondition::Not(Box::new(condition))
32 }
33
34 pub fn matches(&self, path: &FileSystemPath) -> bool {
36 match self {
37 ContextCondition::All(conditions) => conditions.iter().all(|c| c.matches(path)),
38 ContextCondition::Any(conditions) => conditions.iter().any(|c| c.matches(path)),
39 ContextCondition::Not(condition) => !condition.matches(path),
40 ContextCondition::InPath(other_path) => path.is_inside_or_equal_ref(other_path),
41 ContextCondition::InNodeModules => is_in_directory(path, "node_modules"),
42 ContextCondition::InDirectory(dir) => {
43 is_in_directory(path, dir)
45 }
46 }
47 }
48}
49
50fn is_in_directory(path: &FileSystemPath, dir: &str) -> bool {
51 if let Some(pos) = path.path.find(dir) {
52 let end = pos + dir.len();
53 (pos == 0 || path.path.as_bytes()[pos - 1] == b'/')
54 && (end == path.path.len() || path.path.as_bytes()[end] == b'/')
55 } else {
56 false
57 }
58}