use crate::rule::{MatchKind, Rule, RuleKind};
#[derive(Clone, Debug, Default)]
pub struct CompiledRule {
pub query: Option<String>,
pub regex: bool,
pub from: Option<String>,
pub from_kind: Option<String>,
pub to: Option<String>,
pub to_kind: Option<String>,
pub kind: Option<String>,
}
impl CompiledRule {
#[must_use]
pub fn is_empty(&self) -> bool {
self.query.is_none() && self.from.is_none() && self.to.is_none() && self.kind.is_none()
}
}
#[must_use]
pub fn compile_rule_to_inspect_args(rule: &Rule) -> CompiledRule {
let mut compiled = CompiledRule::default();
let needle = rule_needle(rule);
let kind_str = kind_to_string(rule.match_spec.kind);
match rule.kind {
RuleKind::Source => {
compiled.from.clone_from(&needle);
compiled.from_kind = Some(kind_str.to_string());
}
RuleKind::Sink => {
compiled.query.clone_from(&needle);
compiled.to = needle;
compiled.to_kind = Some(kind_str.to_string());
compiled.kind = Some(kind_str.to_string());
}
RuleKind::Sanitizer => {
}
RuleKind::Typing => {
}
}
let target = match rule.match_spec.kind {
MatchKind::Call | MatchKind::New | MatchKind::Missing => rule.match_spec.callee.as_ref(),
MatchKind::Read | MatchKind::Write | MatchKind::Return | MatchKind::Param | MatchKind::Type => {
rule.match_spec.target.as_ref()
}
};
if let Some(rule_target) = target {
if rule_target.regex.is_some() {
compiled.regex = true;
}
}
compiled
}
fn rule_needle(rule: &Rule) -> Option<String> {
let target = match rule.match_spec.kind {
MatchKind::Call | MatchKind::New | MatchKind::Missing => rule.match_spec.callee.as_ref()?,
MatchKind::Read | MatchKind::Write | MatchKind::Return | MatchKind::Param | MatchKind::Type => {
rule.match_spec.target.as_ref()?
}
};
if let Some(regex) = target.regex.as_deref() {
return Some(regex.to_string());
}
if let Some(attribute) = target.attribute.as_ref() {
return attribute.last().cloned();
}
target.name.clone()
}
fn kind_to_string(match_kind: MatchKind) -> &'static str {
match match_kind {
MatchKind::Call => "call",
MatchKind::New => "call",
MatchKind::Read => "read",
MatchKind::Write => "write",
MatchKind::Return => "return",
MatchKind::Param => "decl",
MatchKind::Type => "type",
MatchKind::Missing => "call",
}
}