turbopack_core/
condition.rs

1use serde::{Deserialize, Serialize};
2use turbo_tasks::{NonLocalValue, trace::TraceRawVcs};
3use turbo_tasks_fs::FileSystemPath;
4
5#[derive(Debug, Clone, Serialize, Deserialize, TraceRawVcs, PartialEq, Eq, NonLocalValue)]
6pub enum ContextCondition {
7    All(Vec<ContextCondition>),
8    Any(Vec<ContextCondition>),
9    Not(Box<ContextCondition>),
10    InDirectory(String),
11    InPath(FileSystemPath),
12}
13
14impl ContextCondition {
15    /// Creates a condition that matches if all of the given conditions match.
16    pub fn all(conditions: Vec<ContextCondition>) -> ContextCondition {
17        ContextCondition::All(conditions)
18    }
19
20    /// Creates a condition that matches if any of the given conditions match.
21    pub fn any(conditions: Vec<ContextCondition>) -> ContextCondition {
22        ContextCondition::Any(conditions)
23    }
24
25    /// Creates a condition that matches if the given condition does not match.
26    #[allow(clippy::should_implement_trait)]
27    pub fn not(condition: ContextCondition) -> ContextCondition {
28        ContextCondition::Not(Box::new(condition))
29    }
30
31    /// Returns true if the condition matches the context.
32    pub fn matches(&self, path: &FileSystemPath) -> bool {
33        match self {
34            ContextCondition::All(conditions) => conditions.iter().all(|c| c.matches(path)),
35            ContextCondition::Any(conditions) => conditions.iter().any(|c| c.matches(path)),
36            ContextCondition::Not(condition) => !condition.matches(path),
37            ContextCondition::InPath(other_path) => path.is_inside_or_equal_ref(other_path),
38            ContextCondition::InDirectory(dir) => {
39                // `dir` must be a substring and bracketd by either `'/'` or the end of the path.
40                if let Some(pos) = path.path.find(dir) {
41                    let end = pos + dir.len();
42                    (pos == 0 || path.path.as_bytes()[pos - 1] == b'/')
43                        && (end == path.path.len() || path.path.as_bytes()[end] == b'/')
44                } else {
45                    false
46                }
47            }
48        }
49    }
50}