1use super::functions::*;
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
8pub struct Span {
9 pub start: BytePos,
11 pub end: BytePos,
13}
14impl Span {
15 pub fn new(start: BytePos, end: BytePos) -> Self {
17 Self { start, end }
18 }
19 pub fn from_offsets(start: u32, end: u32) -> Self {
21 Self {
22 start: BytePos(start),
23 end: BytePos(end),
24 }
25 }
26 pub fn point(pos: BytePos) -> Self {
28 Self {
29 start: pos,
30 end: pos,
31 }
32 }
33 pub fn len(self) -> u32 {
35 self.end.0.saturating_sub(self.start.0)
36 }
37 pub fn is_empty(self) -> bool {
39 self.start >= self.end
40 }
41 pub fn merge(self, other: Span) -> Span {
43 Span {
44 start: BytePos(self.start.0.min(other.start.0)),
45 end: BytePos(self.end.0.max(other.end.0)),
46 }
47 }
48 pub fn contains(self, pos: BytePos) -> bool {
50 self.start <= pos && pos < self.end
51 }
52 pub fn slice<'a>(&self, src: &'a str) -> Option<&'a str> {
56 let s = self.start.to_usize();
57 let e = self.end.to_usize();
58 src.get(s..e)
59 }
60 pub fn shift(self, n: u32) -> Self {
62 Span {
63 start: self.start.shift(n),
64 end: self.end.shift(n),
65 }
66 }
67}
68#[allow(dead_code)]
70pub struct StringEncoderExt {
71 pub encoding: String,
73}
74impl StringEncoderExt {
75 pub fn utf8() -> Self {
77 Self {
78 encoding: "UTF-8".to_string(),
79 }
80 }
81 pub fn encode(&self, s: &str) -> Vec<u8> {
83 s.as_bytes().to_vec()
84 }
85 pub fn decode(&self, bytes: &[u8]) -> Result<String, std::string::FromUtf8Error> {
87 String::from_utf8(bytes.to_vec())
88 }
89 pub fn roundtrip(&self, s: &str) -> bool {
91 self.decode(&self.encode(s)).as_deref() == Ok(s)
92 }
93}
94#[allow(dead_code)]
96pub struct StringMonoidExt {
97 pub buffer: String,
99}
100impl StringMonoidExt {
101 pub fn new() -> Self {
103 Self {
104 buffer: String::new(),
105 }
106 }
107 pub fn mappend(&mut self, other: &str) {
109 self.buffer.push_str(other);
110 }
111 pub fn is_identity(&self) -> bool {
113 self.buffer.is_empty()
114 }
115}
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
118pub struct LineCol {
119 pub line: u32,
121 pub col: u32,
123}
124impl LineCol {
125 pub fn new(line: u32, col: u32) -> Self {
127 Self { line, col }
128 }
129}
130#[allow(dead_code)]
132pub struct SubstringFinder2 {
133 pub text: String,
135 pub pattern: String,
137}
138impl SubstringFinder2 {
139 pub fn new(text: impl Into<String>, pattern: impl Into<String>) -> Self {
141 Self {
142 text: text.into(),
143 pattern: pattern.into(),
144 }
145 }
146 pub fn find_all(&self) -> Vec<usize> {
148 let mut positions = Vec::new();
149 let t = &self.text;
150 let p = &self.pattern;
151 if p.is_empty() {
152 return positions;
153 }
154 let mut start = 0;
155 while let Some(pos) = t[start..].find(p.as_str()) {
156 positions.push(start + pos);
157 start += pos + p.len();
158 }
159 positions
160 }
161 pub fn find_kmp(&self) -> Vec<usize> {
163 str_ext2_kmp_search(&self.text, &self.pattern)
164 }
165}
166#[allow(dead_code)]
168pub struct LevenshteinMetric2 {
169 pub max_dist: Option<usize>,
171}
172impl LevenshteinMetric2 {
173 pub fn new() -> Self {
175 Self { max_dist: None }
176 }
177 pub fn with_max(d: usize) -> Self {
179 Self { max_dist: Some(d) }
180 }
181 pub fn distance(&self, a: &str, b: &str) -> usize {
183 str_ext2_levenshtein(a, b)
184 }
185 pub fn within_threshold(&self, a: &str, b: &str) -> bool {
187 match self.max_dist {
188 Some(d) => self.distance(a, b) <= d,
189 None => true,
190 }
191 }
192 pub fn identity_law(&self, a: &str) -> bool {
194 self.distance(a, a) == 0
195 }
196 pub fn symmetry_law(&self, a: &str, b: &str) -> bool {
198 self.distance(a, b) == self.distance(b, a)
199 }
200}
201#[derive(Debug, Default, Clone)]
206pub struct StringBuilder {
207 pub(super) buf: String,
208 pub(super) indent_level: usize,
209 indent_width: usize,
210}
211impl StringBuilder {
212 pub fn new() -> Self {
214 Self {
215 buf: String::new(),
216 indent_level: 0,
217 indent_width: 2,
218 }
219 }
220 pub fn with_capacity(cap: usize) -> Self {
222 Self {
223 buf: String::with_capacity(cap),
224 indent_level: 0,
225 indent_width: 2,
226 }
227 }
228 pub fn set_indent_width(&mut self, w: usize) -> &mut Self {
230 self.indent_width = w;
231 self
232 }
233 pub fn push_str(&mut self, s: &str) -> &mut Self {
235 self.buf.push_str(s);
236 self
237 }
238 pub fn push(&mut self, c: char) -> &mut Self {
240 self.buf.push(c);
241 self
242 }
243 pub fn newline(&mut self) -> &mut Self {
245 self.buf.push('\n');
246 self.buf
247 .push_str(&" ".repeat(self.indent_level * self.indent_width));
248 self
249 }
250 pub fn line(&mut self, s: &str) -> &mut Self {
252 self.buf.push_str(s);
253 self.newline();
254 self
255 }
256 pub fn indent(&mut self) -> &mut Self {
258 self.indent_level += 1;
259 self
260 }
261 pub fn dedent(&mut self) -> &mut Self {
263 self.indent_level = self.indent_level.saturating_sub(1);
264 self
265 }
266 pub fn push_fmt(&mut self, args: std::fmt::Arguments<'_>) -> &mut Self {
268 use std::fmt::Write;
269 let _ = self.buf.write_fmt(args);
270 self
271 }
272 pub fn len(&self) -> usize {
274 self.buf.len()
275 }
276 pub fn is_empty(&self) -> bool {
278 self.buf.is_empty()
279 }
280 pub fn finish(self) -> String {
282 self.buf
283 }
284 pub fn as_str(&self) -> &str {
286 &self.buf
287 }
288 pub fn clear(&mut self) {
290 self.buf.clear();
291 }
292 pub fn sep(&mut self, s: &str) -> &mut Self {
294 if !self.buf.is_empty() {
295 self.buf.push_str(s);
296 }
297 self
298 }
299}
300#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
302pub struct BytePos(pub u32);
303impl BytePos {
304 pub fn from_usize(n: usize) -> Self {
306 Self(n as u32)
307 }
308 pub fn to_usize(self) -> usize {
310 self.0 as usize
311 }
312 pub fn shift(self, n: u32) -> Self {
314 Self(self.0 + n)
315 }
316}
317#[allow(dead_code)]
319pub struct RollingHashExt {
320 pub base: u64,
322 pub modulus: u64,
324}
325impl RollingHashExt {
326 pub fn new() -> Self {
328 Self {
329 base: 31,
330 modulus: 1_000_000_007,
331 }
332 }
333 pub fn hash_str(&self, s: &str) -> u64 {
335 s.bytes().fold(0u64, |acc, b| {
336 (acc.wrapping_mul(self.base).wrapping_add(b as u64)) % self.modulus
337 })
338 }
339 pub fn find(&self, text: &str, pattern: &str) -> Vec<usize> {
341 str_ext2_rabin_karp(text, pattern, self.base, self.modulus)
342 }
343}