Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_text/src/pattern.rs

3.4 KiB, 3 runs

created by r1870400018:1105, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use oxedyne_fe2o3_core::prelude::*;
2
3#[derive(Clone, Debug)]
4pub enum BoolOp {
5 And,
6 Or,
7 Not,
8}
9
10#[derive(Clone, Debug)]
11pub enum SacssOp {
12 StartsWith(String),
13 EndsWith(String),
14 Contains(String),
15}
16
17#[derive(Clone, Debug)]
18pub struct SacssNode {
19 pub op: Option<BoolOp>,
20 pub matcher_op: Option<SacssOp>,
21 pub children: Vec<usize>,
22 pub watching: bool,
23 pub matching_indices: Vec<usize>,
24}
25
26#[derive(Clone, Debug)]
27pub struct Sacss {
28 pub nodes: Vec<SacssNode>,
29 pub buffer: String,
30}
31
32impl SacssNode {
33 pub fn new_leaf(matcher_op: SacssOp) -> Self {
34 SacssNode {
35 op: None,
36 matcher_op: Some(matcher_op),
37 children: Vec::new(),
38 watching: false,
39 matching_indices: Vec::new(),
40 }
41 }
42
43 pub fn new_branch(op: BoolOp, children: Vec<usize>) -> Self {
44 SacssNode {
45 op: Some(op),
46 matcher_op: None,
47 children,
48 watching: false,
49 matching_indices: Vec::new(),
50 }
51 }
52}
53
54/// Sacss implements the Stateful Algorithm for Composable, Streaming Search (SACSS).
55impl Sacss {
56 pub fn new(root: SacssNode) -> Self {
57 Sacss {
58 nodes: vec![root],
59 buffer: String::new(),
60 }
61 }
62
63 pub fn process_char(&mut self, c: char) -> Vec<(usize, usize)> {
64 self.buffer.push(c);
65 self.update_and_match()
66 }
67
68 fn update_and_match(&mut self) -> Vec<(usize, usize)> {
69 let mut results = Vec::new();
70 self.update_node(0, &mut results);
71 results
72 }
73
74 fn update_node(&mut self, node_index: usize, results: &mut Vec<(usize, usize)>) {
75 let buffer_len = self.buffer.len();
76
77 if let Some(matcher_op) = &self.nodes[node_index].matcher_op.clone() {
78 match matcher_op {
79 SacssOp::StartsWith(pattern) => {
80 self.update_starts_with(node_index, &pattern, buffer_len, results);
81 }
82 // Implement other cases as needed
83 _ => {}
84 }
85 }
86
87 // Traverse children if it's a branch node
88 let children = self.nodes[node_index].children.clone();
89 for &child_index in &children {
90 self.update_node(child_index, results);
91 }
92 }
93
94 fn update_starts_with(&mut self, node_index: usize, pattern: &str, buffer_len: usize, results: &mut Vec<(usize, usize)>) {
95 let node = &mut self.nodes[node_index];
96
97 // Check if we need to start watching
98 if !node.watching && self.buffer.ends_with(&pattern[0..1]) {
99 node.watching = true;
100 }
101
102 // Check for completed matches
103 if node.watching {
104 if self.buffer.ends_with(pattern) {
105 let start = buffer_len - pattern.len();
106 results.push((start, buffer_len));
107 node.matching_indices.push(start);
108 node.watching = false;
109 } else if !pattern.starts_with(&self.buffer[buffer_len - 1..]) {
110 node.watching = false;
111 }
112 }
113
114 // Check existing matching indices for potential new results
115 let new_matches: Vec<(usize, usize)> = node.matching_indices
116 .iter()
117 .filter(|&&start| start + pattern.len() == buffer_len)
118 .map(|&start| (start, buffer_len))
119 .collect();
120 results.extend(new_matches);
121 }
122}