#![warn(missing_docs)]
use regex::Captures;
use regex::Regex;
use std::borrow::Cow;
pub trait RegexTry<F, E> {
fn try_replacen<'t>(&self, text: &'t str, limit: usize, rep: F) -> Result<Cow<'t, str>, E>;
fn try_replace<'t>(&self, text: &'t str, rep: F) -> Result<Cow<'t, str>, E>;
fn try_replace_all<'t>(&self, text: &'t str, rep: F) -> Result<Cow<'t, str>, E>;
}
impl<F, E> RegexTry<F, E> for Regex
where
F: FnMut(&Captures) -> Result<String, E>,
{
fn try_replacen<'t>(&self, text: &'t str, limit: usize, mut rep: F) -> Result<Cow<'t, str>, E> {
let mut it = self.captures_iter(text).enumerate().peekable();
if it.peek().is_none() {
return Ok(Cow::Borrowed(text));
}
let mut new = String::with_capacity(text.len());
let mut last_match = 0;
for (i, cap) in it {
if limit > 0 && i >= limit {
break;
}
let m = cap.get(0).unwrap();
new.push_str(&text[last_match..m.start()]);
let replacement = rep(&cap)?;
new.push_str(&replacement);
last_match = m.end();
}
new.push_str(&text[last_match..]);
Ok(Cow::Owned(new))
}
fn try_replace<'t>(&self, text: &'t str, rep: F) -> Result<Cow<'t, str>, E> {
self.try_replacen(text, 1, rep)
}
fn try_replace_all<'t>(&self, text: &'t str, rep: F) -> Result<Cow<'t, str>, E> {
self.try_replacen(text, 0, rep)
}
}