use super::pattern::{ExecutionPattern, ModulePattern};
use super::parser::parse_pointcut;
#[derive(Debug, Clone, PartialEq)]
pub enum Pointcut {
Execution(ExecutionPattern),
Within(ModulePattern),
And(Box<Pointcut>, Box<Pointcut>),
Or(Box<Pointcut>, Box<Pointcut>),
Not(Box<Pointcut>),
}
impl Pointcut {
pub fn parse(input: &str) -> Result<Self, String> {
parse_pointcut(input)
}
pub fn and(self, other: Pointcut) -> Pointcut {
Pointcut::And(Box::new(self), Box::new(other))
}
pub fn or(self, other: Pointcut) -> Pointcut {
Pointcut::Or(Box::new(self), Box::new(other))
}
pub fn not(self) -> Pointcut {
Pointcut::Not(Box::new(self))
}
pub fn public_functions() -> Self {
use super::pattern::{ExecutionPattern, NamePattern, Visibility};
Pointcut::Execution(ExecutionPattern {
visibility: Some(Visibility::Public),
name: NamePattern::Wildcard,
return_type: None,
})
}
pub fn all_functions() -> Self {
use super::pattern::{ExecutionPattern, NamePattern};
Pointcut::Execution(ExecutionPattern {
visibility: None,
name: NamePattern::Wildcard,
return_type: None,
})
}
pub fn within_module(module_path: impl Into<String>) -> Self {
use super::pattern::ModulePattern;
Pointcut::Within(ModulePattern {
path: module_path.into(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pointcut_combinators() {
use crate::pointcut::pattern::*;
let pc1 = Pointcut::Execution(ExecutionPattern {
visibility: Some(Visibility::Public),
name: NamePattern::Wildcard,
return_type: None,
});
let pc2 = Pointcut::Within(ModulePattern {
path: "crate::api".to_string(),
});
let and_pc = pc1.clone().and(pc2.clone());
assert!(matches!(and_pc, Pointcut::And(_, _)));
let or_pc = pc1.clone().or(pc2.clone());
assert!(matches!(or_pc, Pointcut::Or(_, _)));
let not_pc = pc1.not();
assert!(matches!(not_pc, Pointcut::Not(_)));
}
}