minify_html_common/
pattern.rs1use aho_corasick::AhoCorasick;
2
3pub struct TrieNode<V: 'static + Copy> {
5 pub offset: usize,
9 pub value: Option<V>,
10 pub children: &'static [Option<&'static TrieNode<V>>],
11}
12
13pub enum TrieNodeMatch<V: 'static + Copy> {
14 Found { len: usize, value: V },
15 NotFound { reached: usize },
16}
17
18#[allow(dead_code)]
19impl<V: 'static + Copy> TrieNode<V> {
20 pub fn shortest_matching_prefix(&self, text: &[u8], from: usize) -> (&TrieNode<V>, usize) {
38 let mut node: &TrieNode<V> = self;
39 let mut pos = from;
40 while let Some(&c) = text.get(pos) {
41 match node.children.get((c as usize).wrapping_sub(node.offset)) {
42 Some(Some(child)) => node = child,
43 None | Some(None) => break,
44 };
45 pos += 1;
46 if node.value.is_some() {
47 break;
48 };
49 }
50 (node, pos)
51 }
52
53 pub fn longest_matching_prefix(&self, text: &[u8]) -> TrieNodeMatch<V> {
54 let mut node: &TrieNode<V> = self;
55 let mut value: Option<TrieNodeMatch<V>> = None;
56 let mut pos = 0;
57 while let Some(&c) = text.get(pos) {
58 match node.children.get((c as usize).wrapping_sub(node.offset)) {
59 Some(Some(child)) => node = child,
60 None | Some(None) => break,
61 };
62 pos += 1;
63 if let Some(v) = node.value {
64 value = Some(TrieNodeMatch::Found { len: pos, value: v });
65 }
66 }
67 value.unwrap_or(TrieNodeMatch::NotFound { reached: pos })
68 }
69}
70
71pub struct Replacer {
72 searcher: AhoCorasick,
73 replacements: Vec<Vec<u8>>,
74}
75
76impl Replacer {
77 pub fn new(searcher: AhoCorasick, replacements: Vec<Vec<u8>>) -> Replacer {
78 Replacer {
79 searcher,
80 replacements,
81 }
82 }
83
84 pub fn replace_all(&self, src: &[u8]) -> Vec<u8> {
85 self.searcher.replace_all_bytes(src, &self.replacements)
86 }
87}