weggli-ruleset 0.1.8

Ruleset managment/matching/reporting for weggli patterns
Documentation
use std::borrow::Cow;
use std::fmt::Debug;
use std::sync::Arc;

use rustc_hash::FxHashSet;
use serde::{Deserialize, Serialize};
use weggli::result::QueryResult;

use crate::matcher::RuleMatch;
use crate::rule::Severity;

#[derive(Deserialize, Serialize)]
pub struct RuleMatchReport<'a> {
    rule: Cow<'a, str>,
    checker: Cow<'a, str>,
    #[serde(skip_serializing_if = "str::is_empty")]
    description: Cow<'a, str>,
    #[serde(skip_serializing_if = "FxHashSet::<String>::is_empty")]
    tags: Cow<'a, FxHashSet<String>>,
    severity: Severity,
    source: Arc<str>,
    #[serde(rename = "match")]
    match_result: Cow<'a, QueryResult>,
}

impl<'a> Debug for RuleMatchReport<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut m = f.debug_struct("RuleMatchReport");

        m.field("rule", &self.rule as _);
        m.field("checker", &self.checker as _);

        if let Some(ref description) = self.description() {
            m.field("description", description as _);
        }

        m.field("tags", self.tags());
        m.field("severity", &self.severity as _);
        m.field("matches", &self.match_result as _);

        m.finish_non_exhaustive()
    }
}

impl<'a> RuleMatchReport<'a> {
    pub fn new(m: &'a RuleMatch) -> Self {
        Self {
            rule: Cow::Borrowed(m.rule().id()),
            description: Cow::Borrowed(m.rule().description().unwrap_or_default()),
            checker: Cow::Borrowed(m.checker().name()),
            tags: Cow::Borrowed(m.rule().tags()),
            severity: m.rule().severity(),
            source: m.source(),
            match_result: Cow::Borrowed(m.result()),
        }
    }

    pub fn rule(&self) -> &str {
        &self.rule
    }

    pub fn checker(&self) -> &str {
        &self.checker
    }

    pub fn description(&self) -> Option<&str> {
        if self.description.is_empty() {
            None
        } else {
            Some(&self.description)
        }
    }

    pub fn severity(&self) -> Severity {
        self.severity
    }

    pub fn tags(&self) -> &FxHashSet<String> {
        &self.tags
    }

    pub fn source(&self) -> &str {
        &self.source
    }

    pub fn result(&self) -> &QueryResult {
        &self.match_result
    }

    pub fn display(&self, before: usize, after: usize, line_numbers: bool) -> String {
        self.match_result
            .display(&self.source, before, after, line_numbers)
    }

    pub fn into_owned(self) -> RuleMatchReport<'static> {
        RuleMatchReport {
            rule: self.rule.into_owned().into(),
            description: self.description.into_owned().into(),
            checker: self.checker.into_owned().into(),
            tags: Cow::Owned(self.tags.into_owned()),
            severity: self.severity,
            source: self.source,
            match_result: Cow::Owned(self.match_result.into_owned()),
        }
    }
}