blazehash 0.2.5

Forensic file hasher — hashdeep for the modern era, BLAKE3 by default
Documentation
use anyhow::Result;
use std::path::Path;

/// A single YARA rule match, carrying the rule name and all its tags.
#[derive(Debug, Clone)]
pub struct YaraMatch {
    pub rule_name: String,
    pub tags: Vec<String>,
}

pub struct YaraScanner {
    rules: yara_x::Rules,
}

impl YaraScanner {
    pub fn new(rules_file: &Path) -> Result<Self> {
        let source = std::fs::read_to_string(rules_file)?;
        Self::from_source(&source)
    }

    /// Build a `YaraScanner` from a YARA rules source string.
    pub fn from_source(source: &str) -> Result<Self> {
        let mut compiler = yara_x::Compiler::new();
        compiler
            .add_source(source)
            .map_err(|e| anyhow::anyhow!("YARA compile error: {e}"))?;
        let rules = compiler.build();
        Ok(Self { rules })
    }

    pub fn scan(&self, data: &[u8]) -> Result<Vec<YaraMatch>> {
        let mut scanner = yara_x::Scanner::new(&self.rules);
        let results = scanner
            .scan(data)
            .map_err(|e| anyhow::anyhow!("YARA scan error: {e}"))?;
        Ok(results
            .matching_rules()
            .map(|r| YaraMatch {
                rule_name: r.identifier().to_string(),
                tags: r.tags().map(|t| t.identifier().to_string()).collect(),
            })
            .collect())
    }
}