actrpc_interceptor/interceptors/policy/
matcher.rs1use crate::interceptors::policy::{
2 config::{PolicyMatcher, PolicyMatcherKind},
3 error::PolicyError,
4};
5use globset::{Glob, GlobMatcher};
6use regex::Regex;
7
8#[derive(Debug, Clone)]
9pub struct CompiledPolicyMatcher {
10 negated: bool,
11 inner: CompiledPolicyMatcherInner,
12}
13
14#[derive(Debug, Clone)]
15enum CompiledPolicyMatcherInner {
16 Exact(String),
17 Glob(GlobMatcher),
18 Regex(Regex),
19}
20
21impl CompiledPolicyMatcher {
22 pub fn compile(rule: &str, matcher: &PolicyMatcher) -> Result<Self, PolicyError> {
23 let inner = match matcher.kind {
24 PolicyMatcherKind::Exact => CompiledPolicyMatcherInner::Exact(matcher.value.clone()),
25
26 PolicyMatcherKind::Glob => {
27 let glob =
28 Glob::new(&matcher.value).map_err(|source| PolicyError::InvalidGlob {
29 rule: rule.to_owned(),
30 source,
31 })?;
32
33 CompiledPolicyMatcherInner::Glob(glob.compile_matcher())
34 }
35
36 PolicyMatcherKind::Regex => {
37 let regex =
38 Regex::new(&matcher.value).map_err(|source| PolicyError::InvalidRegex {
39 rule: rule.to_owned(),
40 source,
41 })?;
42
43 CompiledPolicyMatcherInner::Regex(regex)
44 }
45 };
46
47 Ok(Self {
48 negated: matcher.negated,
49 inner,
50 })
51 }
52
53 pub fn matches(&self, value: Option<&str>) -> bool {
54 let matched = match value {
55 Some(value) => match &self.inner {
56 CompiledPolicyMatcherInner::Exact(expected) => value == expected,
57 CompiledPolicyMatcherInner::Glob(glob) => glob.is_match(value),
58 CompiledPolicyMatcherInner::Regex(regex) => regex.is_match(value),
59 },
60 None => false,
61 };
62
63 if self.negated { !matched } else { matched }
64 }
65}