1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use crate::{replace_data::ReplaceData, ErrorKind};
use regex::{Regex, RegexBuilder};
use std::borrow::Cow;
pub struct ReplaceCommand<'a> {
expr: Regex,
with: Cow<'a, str>,
is_global: bool,
}
impl<'a> ReplaceCommand<'a> {
pub fn new(command: &'a str) -> Result<Self, ErrorKind> {
ReplaceData::new(command).and_then(ReplaceCommand::from_replace_data)
}
pub fn execute<'b>(&self, text: impl Into<Cow<'b, str>>) -> Cow<'b, str> {
let text = text.into();
if self.is_global {
regex_cow(text, &self.expr, Regex::replace_all, self.with.as_ref())
} else {
regex_cow(text, &self.expr, Regex::replace, self.with.as_ref())
}
}
pub(crate) fn from_replace_data(data: ReplaceData<'a>) -> Result<Self, ErrorKind> {
let mut builder = RegexBuilder::new(&data.pattern);
data.flags.apply(&mut builder);
let regex = builder.build().map_err(ErrorKind::RegexError)?;
Ok(ReplaceCommand {
expr: regex,
with: data.with,
is_global: data.flags.is_global(),
})
}
}
fn regex_cow<'a, R, F>(s: Cow<'a, str>, re: &Regex, f: F, rep: R) -> Cow<'a, str>
where
for<'r, 't> F: FnOnce(&'r Regex, &'t str, R) -> Cow<'t, str>,
R: regex::Replacer,
{
match s {
Cow::Borrowed(b) => f(re, b, rep),
Cow::Owned(o) => Cow::Owned(f(re, &o, rep).into_owned()),
}
}