Skip to main content

online_dsl_forge/runtime/
context.rs

1use regex::Regex;
2
3use crate::parser::SourceSpan;
4use crate::sema::{CompiledRegexCache, RegexFlavor, RegexPolicy, SecurityProfile};
5
6use super::EvalError;
7
8#[derive(Clone, Copy)]
9pub struct RuntimeCallContext<'a> {
10  profile: &'a SecurityProfile,
11  regex_cache: &'a CompiledRegexCache,
12  span: SourceSpan,
13}
14
15impl<'a> RuntimeCallContext<'a> {
16  pub(crate) fn new(
17    profile: &'a SecurityProfile,
18    regex_cache: &'a CompiledRegexCache,
19    span: SourceSpan,
20  ) -> Self {
21    Self {
22      profile,
23      regex_cache,
24      span,
25    }
26  }
27
28  pub fn profile(&self) -> &'a SecurityProfile {
29    self.profile
30  }
31
32  pub fn regex_policy(&self) -> RegexPolicy {
33    self.profile.default_regex_policy
34  }
35
36  pub fn regex_cache(&self) -> &'a CompiledRegexCache {
37    self.regex_cache
38  }
39
40  pub fn span(&self) -> SourceSpan {
41    self.span
42  }
43
44  pub fn precompiled_regex(&self, flavor: RegexFlavor, pattern: &str) -> Option<&'a Regex> {
45    self.regex_cache.get(flavor, pattern)
46  }
47
48  pub fn require_precompiled_regex(
49    &self,
50    flavor: RegexFlavor,
51    pattern: &str,
52  ) -> Result<&'a Regex, EvalError> {
53    self.precompiled_regex(flavor, pattern).ok_or_else(|| {
54      EvalError::new(
55        format!(
56          "precompiled {} regex is missing",
57          regex_flavor_label(flavor)
58        ),
59        self.span,
60      )
61    })
62  }
63
64  pub fn precompiled_regex_is_match(
65    &self,
66    flavor: RegexFlavor,
67    pattern: &str,
68    haystack: &str,
69  ) -> Result<bool, EvalError> {
70    self
71      .require_precompiled_regex(flavor, pattern)
72      .map(|regex| regex.is_match(haystack))
73  }
74}
75
76fn regex_flavor_label(flavor: RegexFlavor) -> &'static str {
77  match flavor {
78    RegexFlavor::Default => "default",
79    RegexFlavor::HeaderName => "header_name",
80  }
81}