#![forbid(unsafe_code)]
#![warn(missing_docs)]
#![warn(clippy::pedantic)]
#![cfg_attr(
not(test),
deny(
clippy::unwrap_used,
clippy::expect_used,
clippy::todo,
clippy::unimplemented,
clippy::panic
)
)]
#![allow(
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::missing_errors_doc
)]
pub(crate) mod condition;
pub(crate) mod parse;
pub(crate) mod selection;
use parse::{SigmaRule, compile_rule};
pub(crate) fn escape_dsl_string(s: &str) -> String {
let mut out = String::with_capacity(s.len() + 4);
for ch in s.chars() {
if ch == '"' || ch == '\\' {
out.push('\\');
}
out.push(ch);
}
out
}
pub(crate) fn base64_offset(s: &str) -> Vec<String> {
use base64::{Engine as _, engine::general_purpose};
if s.is_empty() {
return vec![];
}
let n = s.len();
let mut variants = Vec::with_capacity(3);
for i in 0usize..3 {
let mut prefixed = vec![0u8; i];
prefixed.extend_from_slice(s.as_bytes());
let encoded = general_purpose::STANDARD.encode(&prefixed);
let start = (i * 4 + 2) / 3;
let end = ((i + n) * 4) / 3;
if start < end {
variants.push(encoded[start..end].to_string());
}
}
variants
}
#[derive(Debug, Clone, Default)]
pub struct SigmaCompiler;
impl SigmaCompiler {
#[must_use]
pub fn new() -> Self {
Self
}
pub fn compile(&self, yaml: &str) -> secir::Result<secir::Template> {
let rule: SigmaRule =
serde_yaml::from_str(yaml).map_err(|source| secir::Error::TemplateValidation {
id: "sigma".to_string(),
reason: format!("failed to parse sigma YAML: {source}"),
})?;
compile_rule(rule)
}
pub fn compile_str(yaml: &str) -> secir::Result<secir::Template> {
Self::new().compile(yaml)
}
}