|
| 1 | +use pyo3::prelude::*; |
| 2 | + |
| 3 | +use regex::Regex; |
| 4 | + |
| 5 | +use mimalloc::MiMalloc; |
| 6 | + |
| 7 | + |
| 8 | +#[global_allocator] |
| 9 | +static GLOBAL: MiMalloc = MiMalloc; |
| 10 | + |
| 11 | + |
| 12 | +#[pyclass(name=Regex)] |
| 13 | +struct PyRegex { |
| 14 | + regex: Regex, |
| 15 | +} |
| 16 | + |
| 17 | +#[pymethods] |
| 18 | +impl PyRegex { |
| 19 | + #[new] |
| 20 | + fn new(pattern: &str) -> Self { |
| 21 | + PyRegex { regex: Regex::new(pattern).unwrap() } |
| 22 | + } |
| 23 | + |
| 24 | + /// Matches the compiled regex string to another string passed to this |
| 25 | + /// function. |
| 26 | + /// |
| 27 | + /// Args: |
| 28 | + /// other: |
| 29 | + /// The other string to be matched against the compiled regex |
| 30 | + /// |
| 31 | + /// Returns: |
| 32 | + /// A bool signifying if it is a match or not. |
| 33 | + fn is_match(&self, other: &str) -> bool { |
| 34 | + self.regex.is_match(other) |
| 35 | + } |
| 36 | + |
| 37 | + /// Matches the compiled regex string to another string passed to this |
| 38 | + /// function at a specific point marked by the start parameter. |
| 39 | + /// |
| 40 | + /// Args: |
| 41 | + /// other: |
| 42 | + /// The other string to be matched against the compiled regex. |
| 43 | + /// start: |
| 44 | + /// The starting index of the string you want to match against. |
| 45 | + /// |
| 46 | + /// Returns: |
| 47 | + /// A bool signifying if it is a match or not. |
| 48 | + fn is_match_at(&self, other: &str, start: usize) -> bool { |
| 49 | + self.regex.is_match_at(other, start) |
| 50 | + } |
| 51 | + |
| 52 | + /// Matches the compiled regex string to another string passed to this |
| 53 | + /// function, if a match is found it returns the matched string otherwise |
| 54 | + /// it returns None. |
| 55 | + /// |
| 56 | + /// Args: |
| 57 | + /// other: |
| 58 | + /// The other string to be matched against the compiled regex. |
| 59 | + /// |
| 60 | + /// Returns: |
| 61 | + /// Optional[str] - This can either be the matched text or None. |
| 62 | + fn find(&self, other: &str) -> Option<String> { |
| 63 | + let matched = match self.regex.find(other) { |
| 64 | + Some(m) => m, |
| 65 | + _ => return None, |
| 66 | + }; |
| 67 | + |
| 68 | + Some(matched.as_str().to_string()) |
| 69 | + } |
| 70 | + |
| 71 | + /// Matches the compiled regex string to another string passed to this |
| 72 | + /// function and returns all matched strings in a list, if no matches it |
| 73 | + /// returns a empty list |
| 74 | + /// |
| 75 | + /// Args: |
| 76 | + /// other: |
| 77 | + /// The other string to be matched against the compiled regex. |
| 78 | + /// |
| 79 | + /// Returns: |
| 80 | + /// A list with n amount of text objects containing matched strings. |
| 81 | + fn findall(&self, other: &str) -> Vec<String> { |
| 82 | + let matched: Vec<String> = self.regex |
| 83 | + .find_iter(other) |
| 84 | + .map(|match_| { |
| 85 | + match_.as_str().to_string() |
| 86 | + }) |
| 87 | + .collect(); |
| 88 | + |
| 89 | + matched |
| 90 | + } |
| 91 | + |
| 92 | + fn all_captures(&self, other: &str) -> Option<Vec<Vec<Option<String>>>> { |
| 93 | + let mut caps = Vec::new(); |
| 94 | + for capture in self.regex.captures_iter(other) { |
| 95 | + let new = list_captures(capture); |
| 96 | + caps.push(new); |
| 97 | + } |
| 98 | + Some(caps) |
| 99 | + } |
| 100 | + |
| 101 | + fn captures(&self, other: &str) -> Option<Vec<Option<String>>> { |
| 102 | + let capture = match self.regex.captures(other) { |
| 103 | + Some(c) => c, |
| 104 | + _ => return None, |
| 105 | + }; |
| 106 | + let new = list_captures(capture); |
| 107 | + |
| 108 | + Some(new) |
| 109 | + } |
| 110 | +} |
| 111 | + |
| 112 | + |
| 113 | +fn list_captures(capture: regex::Captures) ->Vec<Option<String>> { |
| 114 | + let mut new: Vec<Option<String>> = capture |
| 115 | + .iter() |
| 116 | + .map(|m| { |
| 117 | + match m { |
| 118 | + Some(thing) => { |
| 119 | + Some(thing.as_str().to_string()) |
| 120 | + } |
| 121 | + _ => None, |
| 122 | + } |
| 123 | + }) |
| 124 | + .collect(); |
| 125 | + new.remove(0); |
| 126 | + |
| 127 | + new |
| 128 | +} |
| 129 | + |
| 130 | + |
| 131 | +/// |
| 132 | +/// Wraps all our existing pyobjects together in the module |
| 133 | +/// |
| 134 | +#[pymodule] |
| 135 | +fn regex(_py: Python, m: &PyModule) -> PyResult<()> { |
| 136 | + m.add_class::<PyRegex>()?; |
| 137 | + Ok(()) |
| 138 | +} |
0 commit comments