From c6065b578ac54ea9309eb320522c64026eb6c2df Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 14 Feb 2018 11:49:14 -0800 Subject: [PATCH] Add Replacer::by_ref adaptor to use a Replacer without consuming it Note: This can't simply return `&mut Self` because a generic `impl Replacer for &mut R` would conflict with libstd's generic `impl FnMut for &mut F`. --- src/lib.rs | 2 +- src/re_bytes.rs | 37 +++++++++++++++++++++++++++++++++++++ src/re_unicode.rs | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 0dd551f23f..86d9bae6da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -527,7 +527,7 @@ pub use re_trait::Locations; pub use re_unicode::{ Regex, Match, Captures, CaptureNames, Matches, CaptureMatches, SubCaptureMatches, - Replacer, NoExpand, Split, SplitN, + Replacer, ReplacerRef, NoExpand, Split, SplitN, escape, }; diff --git a/src/re_bytes.rs b/src/re_bytes.rs index 459369de93..84ec8a8260 100644 --- a/src/re_bytes.rs +++ b/src/re_bytes.rs @@ -990,6 +990,43 @@ pub trait Replacer { fn no_expansion<'r>(&'r mut self) -> Option> { None } + + /// Return a `Replacer` that borrows and wraps this `Replacer`. + /// + /// This is useful when you want to take a generic `Replacer` (which might + /// not be cloneable) and use it without consuming it, so it can be used + /// more than once. + /// + /// # Example + /// + /// ``` + /// use regex::bytes::{Regex, Replacer}; + /// + /// fn replace_all_twice(re: Regex, src: &[u8], mut rep: R) + /// -> Vec { + /// let dst = re.replace_all(src, rep.by_ref()); + /// let dst = re.replace_all(&dst, rep.by_ref()); + /// dst.into_owned() + /// } + /// ``` + fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> { + ReplacerRef(self) + } +} + +/// By-reference adaptor for a `Replacer` +/// +/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref). +#[derive(Debug)] +pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R); + +impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> { + fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) { + self.0.replace_append(caps, dst) + } + fn no_expansion<'r>(&'r mut self) -> Option> { + self.0.no_expansion() + } } impl<'a> Replacer for &'a [u8] { diff --git a/src/re_unicode.rs b/src/re_unicode.rs index 7fb68257bb..4fb606d72e 100644 --- a/src/re_unicode.rs +++ b/src/re_unicode.rs @@ -1034,6 +1034,43 @@ pub trait Replacer { fn no_expansion<'r>(&'r mut self) -> Option> { None } + + /// Return a `Replacer` that borrows and wraps this `Replacer`. + /// + /// This is useful when you want to take a generic `Replacer` (which might + /// not be cloneable) and use it without consuming it, so it can be used + /// more than once. + /// + /// # Example + /// + /// ``` + /// use regex::{Regex, Replacer}; + /// + /// fn replace_all_twice(re: Regex, src: &str, mut rep: R) + /// -> String { + /// let dst = re.replace_all(src, rep.by_ref()); + /// let dst = re.replace_all(&dst, rep.by_ref()); + /// dst.into_owned() + /// } + /// ``` + fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> { + ReplacerRef(self) + } +} + +/// By-reference adaptor for a `Replacer` +/// +/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref). +#[derive(Debug)] +pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R); + +impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> { + fn replace_append(&mut self, caps: &Captures, dst: &mut String) { + self.0.replace_append(caps, dst) + } + fn no_expansion(&mut self) -> Option> { + self.0.no_expansion() + } } impl<'a> Replacer for &'a str {