Skip to main content

oo_ide/log_matcher/
types.rs

1//! Compiled output types for log matchers.
2//!
3//! All regex fields are stored behind [`Arc`] so that [`CompiledMatcher`] is
4//! cheaply cloneable and safe to share across threads.
5
6use std::fmt;
7use std::sync::Arc;
8
9use regex::Regex;
10
11// ---------------------------------------------------------------------------
12// MatcherId
13// ---------------------------------------------------------------------------
14
15/// Unique identifier for a compiled matcher, e.g. `"rust.cargo.error"`.
16#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct MatcherId(pub String);
18
19impl fmt::Display for MatcherId {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        write!(f, "{}", self.0)
22    }
23}
24
25// ---------------------------------------------------------------------------
26// EmitSeverity
27// ---------------------------------------------------------------------------
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum EmitSeverity {
31    Error,
32    Warning,
33    Info,
34    Hint,
35}
36
37impl fmt::Display for EmitSeverity {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            Self::Error => write!(f, "error"),
41            Self::Warning => write!(f, "warning"),
42            Self::Info => write!(f, "info"),
43            Self::Hint => write!(f, "hint"),
44        }
45    }
46}
47
48// ---------------------------------------------------------------------------
49// EmitTemplate
50// ---------------------------------------------------------------------------
51
52/// Template describing the diagnostic to emit when a matcher fires.
53///
54/// Template strings may contain `{{ capture_name }}` placeholders that are
55/// substituted with named regex capture group values at runtime.
56#[derive(Debug, Clone)]
57pub struct EmitTemplate {
58    pub severity: EmitSeverity,
59    /// Required template for the primary message.
60    pub message: String,
61    pub file: Option<String>,
62    pub line: Option<String>,
63    pub column: Option<String>,
64    pub code: Option<String>,
65}
66
67// ---------------------------------------------------------------------------
68// EndCondition
69// ---------------------------------------------------------------------------
70
71#[derive(Debug, Clone, PartialEq, Eq)]
72pub enum EndCondition {
73    /// The block ends when the next `start` pattern matches another line.
74    NextStart,
75    /// The block ends on a blank line.
76    BlankLine,
77}
78
79// ---------------------------------------------------------------------------
80// BodyRule
81// ---------------------------------------------------------------------------
82
83#[derive(Debug, Clone)]
84pub struct BodyRule {
85    pub pattern: Arc<Regex>,
86    /// If `true`, this rule may be skipped if the line does not match.
87    pub optional: bool,
88    /// If `true`, this rule may match zero or more consecutive lines.
89    pub repeat: bool,
90}
91
92// ---------------------------------------------------------------------------
93// CompiledMatcher
94// ---------------------------------------------------------------------------
95
96/// A fully-compiled, thread-safe log matcher ready for use by the parsing engine.
97///
98/// Regex fields are behind [`Arc`] so cloning is O(1) and the type is
99/// `Send + Sync`.
100#[derive(Debug, Clone)]
101pub struct CompiledMatcher {
102    pub id: MatcherId,
103    pub source: String,
104    pub priority: u32,
105    pub schema_version: u32,
106    pub start: Arc<Regex>,
107    pub body: Vec<BodyRule>,
108    /// Optional safety cap on accumulated body lines before force-emitting.
109    pub max_lines: Option<u32>,
110    pub end: EndCondition,
111    pub emit: EmitTemplate,
112}
113
114// Compile-time assertion: CompiledMatcher must be Send + Sync.
115// Arc<Regex> satisfies this because Regex is Send + Sync.
116fn _assert_send_sync() {
117    fn require<T: Send + Sync>() {}
118    require::<CompiledMatcher>();
119}