How to make `Cow` work in this case?

fn escape(string: &str) -> Cow<str> {
    lazy_static! {
        static ref RE_BACKSLASH: Regex = Regex::new(r#"\\"#).unwrap();
        static ref RE_QUOTE: Regex = Regex::new(r#"""#).unwrap();
    }
    let string1 = RE_BACKSLASH.replace_all(&string, r#"\\"#);
    let string2 = RE_QUOTE.replace_all(&string, r#"\""#);
    string2
}

I understand that this won't compile, since it will return a reference to the stack in case of string1 being Cow::Owned. However, is there any way to make this work, so that no copying will happen if there is nothing to replace?

I did found a semi-solution:

fn escape(string: &str) -> Cow<str> {
    lazy_static! {
        static ref RE_BACKSLASH: Regex = Regex::new(r#"\\"#).unwrap();
        static ref RE_QUOTE: Regex = Regex::new(r#"""#).unwrap();
    }
    let string = RE_BACKSLASH.replace_all(&string, r#"\\"#);
    let string = match string {
        Cow::Borrowed(borrowed) => RE_QUOTE.replace_all(borrowed, r#"\""#),
        Cow::Owned(owned) => RE_QUOTE.replace_all(&owned, r#"\""#).into_owned().into()
    };
    string
}

However, this would be very verbose to write if there are more replacements.

If you have to do this repeatedly, you can factor it out into a function that takes the Regex and Cow<str> as parameters:

fn escape(string: &str) -> Cow<str> {
    lazy_static! {
        static ref RE_BACKSLASH: Regex = Regex::new(r#"\\"#).unwrap();
        static ref RE_QUOTE: Regex = Regex::new(r#"""#).unwrap();
    }
    let mut string = RE_BACKSLASH.replace_all(&string, r#"\\"#);
    string = replace(&RE_QUOTE, string, r#"\""#);
    string
}

fn replace<'a>(regex: &Regex, string: Cow<'a, str>, replacement: &str) -> Cow<'a, str> {
    match string {
        Cow::Borrowed(borrowed) => regex.replace_all(borrowed, replacement),
        Cow::Owned(owned) => regex.replace_all(&owned, replacement).into_owned().into()
    }
}

Thanks. I also tried something similar with cow-utils but that didn't quite work out. I'll stick with regex.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.