msg_tool\ext/
fancy_regex.rs1use anyhow::Result;
3use fancy_regex::Regex;
4
5pub trait FancyRegexExt {
7 fn py_split<'a>(&'a self, input: &'a str) -> Result<PySplit<'a>>;
10}
11
12pub struct PySplit<'a> {
14 str: &'a str,
15 pos: Vec<(usize, usize)>,
16 start: usize,
17}
18
19impl<'a> Iterator for PySplit<'a> {
20 type Item = &'a str;
21
22 fn next(&mut self) -> Option<Self::Item> {
23 if self.start >= self.str.len() {
24 return None;
25 }
26 match self.pos.first().cloned() {
27 Some((start, end)) => {
28 if self.start < start {
29 let result = &self.str[self.start..start];
30 self.start = start;
31 if start == end {
32 self.pos.remove(0);
33 }
34 Some(result)
35 } else if self.start < end {
36 let result = &self.str[self.start..end];
37 self.start = end;
38 self.pos.remove(0);
39 Some(result)
40 } else {
41 unreachable!();
42 }
43 }
44 None => {
45 if self.start < self.str.len() {
46 let result = &self.str[self.start..];
47 self.start = self.str.len();
48 Some(result)
49 } else {
50 None
51 }
52 }
53 }
54 }
55}
56
57impl FancyRegexExt for Regex {
58 fn py_split<'a>(&'a self, input: &'a str) -> Result<PySplit<'a>> {
59 let mut poss = Vec::new();
60 for pos in self.find_iter(input) {
61 let pos = pos?;
62 poss.push((pos.start(), pos.end()));
63 }
64 Ok(PySplit {
65 str: input,
66 pos: poss,
67 start: 0,
68 })
69 }
70}