msg_tool\ext/
fancy_regex.rs

1//!Extensions for fancy_regex crate.
2use anyhow::Result;
3use fancy_regex::Regex;
4
5/// Extension trait for [fancy_regex::Regex] to provide more convenient methods.
6pub trait FancyRegexExt {
7    /// Splits the input string by the regex pattern.
8    /// Like python's `re.split()`, but returns an iterator.
9    fn py_split<'a>(&'a self, input: &'a str) -> Result<PySplit<'a>>;
10}
11
12/// An iterator that splits a string by a regex pattern, similar to Python's `re.split()`.
13pub 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}