sedregex 0.2.5

Sed-like regex library
Documentation
use crate::{replace_data::ReplaceData, ErrorKind};
use regex::{Regex, RegexBuilder};
use std::borrow::Cow;

/// A replace command, ready to be applied on your text.
///
/// ```
/// # use sedregex::ReplaceCommand;
/// # use std::borrow::Cow;
/// let cmd = ReplaceCommand::new("s/world/世界/i").unwrap();
/// assert_eq!("Hello, 世界!", cmd.execute("Hello, world!"));
/// assert_eq!("The 世界 is a cruel place", cmd.execute("The world is a cruel place"));
/// ```
pub struct ReplaceCommand<'a> {
    expr: Regex,
    with: Cow<'a, str>,
    is_global: bool,
}

impl<'a> ReplaceCommand<'a> {
    /// Parses the given command in a form of `s/<expr>/<replace>/<flags>` and builds a regular
    /// expression.
    ///
    /// # Usage notes
    ///
    /// * Delimiter slashes (`/`) could be escaped by a backslash: `\/`
    /// * For the list of supported commands please refer to the [`Command`](enum.Command.html) enum
    /// * For the list of supported flags please refer to the [`RegexFlag`](enum.RegexFlag.html) enum
    pub fn new(command: &'a str) -> Result<Self, ErrorKind> {
        ReplaceData::new(command).and_then(ReplaceCommand::from_replace_data)
    }

    /// Executes the command on the given text.
    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(),
        })
    }
}

/// A helper function that tries to keep borrowed as borrowed while applying a regex.
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()),
    }
}