1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//! Parser group — an ordered fallback chain of parsers.
#[cfg(test)]
#[path = "group_tests.rs"]
mod group_tests;
use crate::record::LogRecord;
use crate::traits::LogParser;
/// A parser group: an ordered list of parsers tried in sequence (fallback chain).
#[derive(Debug)]
pub struct ParserGroup {
/// Human-readable name of this group.
pub name: String,
/// Ordered list of parsers; tried first-to-last.
pub parsers: Vec<Box<dyn LogParser>>,
}
impl ParserGroup {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
parsers: Vec::new(),
}
}
pub fn add_parser(&mut self, parser: Box<dyn LogParser>) {
self.parsers.push(parser);
}
/// Try each parser in order. Returns the first successful parse, or None.
pub fn parse(&self, raw: &str, source: &str, loader_id: &str, id: u64) -> Option<LogRecord> {
for parser in &self.parsers {
if let Some(mut record) = parser.parse(raw, source, loader_id, id) {
// Ensure raw is always populated (some parsers leave it empty
// to avoid double allocation — we fill it here once).
if record.raw.is_empty() {
record.raw = raw.to_string();
}
return Some(record);
}
}
None
}
}