dm_database_parser_sqllog/
matcher.rs

1use daachorse::DoubleArrayAhoCorasick;
2
3/// 围绕 daachorse::DoubleArrayAhoCorasick 的简单适配器。
4/// 存储原始模式(按顺序),并提供一个辅助方法
5/// 用于获取每个模式在输入中首次出现的位置。
6pub struct Matcher {
7    ac: DoubleArrayAhoCorasick<usize>,
8    patterns: Vec<String>,
9}
10
11impl Matcher {
12    /// 从一组模式构建一个 Matcher(模式顺序重要)。
13    /// 空模式会被忽略;至少需要一个非空模式。
14    pub fn from_patterns<S: AsRef<str>>(patterns: &[S]) -> Self {
15        // 收集所有权的非空模式
16        let patterns_owned: Vec<String> = patterns
17            .iter()
18            .map(|s| s.as_ref().to_string())
19            .filter(|s| !s.is_empty())
20            .collect();
21
22        if patterns_owned.is_empty() {
23            panic!("failed to build daachorse automaton: no non-empty patterns provided");
24        }
25
26        // 构建有所有权的字节缓冲,以便向 daachorse 传递切片
27        let pats_bufs: Vec<Vec<u8>> = patterns_owned.iter().map(|s| s.as_bytes().to_vec()).collect();
28        let pats_slices: Vec<&[u8]> = pats_bufs.iter().map(|v| v.as_slice()).collect();
29
30        let ac = DoubleArrayAhoCorasick::new(&pats_slices)
31            .unwrap_or_else(|e| panic!("failed to build daachorse automaton: {}", e));
32
33        Matcher { ac, patterns: patterns_owned }
34    }
35
36    /// 返回一个 Vec<Option<usize>>,表示每个模式的首次匹配起始位置
37    ///(顺序与构建 Matcher 时提供的模式相同)。
38    pub fn find_first_positions(&self, haystack: &[u8]) -> Vec<Option<usize>> {
39        let mut first: Vec<Option<usize>> = vec![None; self.patterns.len()];
40        for m in self.ac.find_iter(haystack) {
41            let id = m.value();
42            if id < first.len() && first[id].is_none() {
43                first[id] = Some(m.start());
44            }
45        }
46        first
47    }
48
49    /// Expose number of patterns
50    pub fn patterns_len(&self) -> usize {
51        self.patterns.len()
52    }
53}