Skip to content

Commit 908e344

Browse files
committed
Add Replacer::by_ref adaptor to use a Replacer without consuming it
Note: This can't simply return `&mut Self` because a generic `impl<R: Replacer> Replacer for &mut R` would conflict with libstd's generic `impl<F: FnMut> FnMut for &mut F`.
1 parent 9ee9943 commit 908e344

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ pub use re_trait::Locations;
527527
pub use re_unicode::{
528528
Regex, Match, Captures,
529529
CaptureNames, Matches, CaptureMatches, SubCaptureMatches,
530-
Replacer, NoExpand, Split, SplitN,
530+
Replacer, ReplacerRef, NoExpand, Split, SplitN,
531531
escape,
532532
};
533533

src/re_bytes.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,29 @@ pub trait Replacer {
990990
fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
991991
None
992992
}
993+
994+
/// Return a `Replacer` that borrows and wraps this `Replacer`.
995+
///
996+
/// This is useful when you want to take a generic `Replacer` (which might
997+
/// not be cloneable) and use it without consuming it, so it can be used
998+
/// more than once.
999+
fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
1000+
ReplacerRef(self)
1001+
}
1002+
}
1003+
1004+
/// By-reference adaptor for a `Replacer`
1005+
///
1006+
/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
1007+
pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
1008+
1009+
impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
1010+
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
1011+
self.0.replace_append(caps, dst)
1012+
}
1013+
fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
1014+
self.0.no_expansion()
1015+
}
9931016
}
9941017

9951018
impl<'a> Replacer for &'a [u8] {

src/re_unicode.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,40 @@ pub trait Replacer {
10341034
fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, str>> {
10351035
None
10361036
}
1037+
1038+
/// Return a `Replacer` that borrows and wraps this `Replacer`.
1039+
///
1040+
/// This is useful when you want to take a generic `Replacer` (which might
1041+
/// not be cloneable) and use it without consuming it, so it can be used
1042+
/// more than once:
1043+
///
1044+
/// ```
1045+
/// use regex::{Regex, Replacer};
1046+
///
1047+
/// fn replace_all_twice<R: Replacer>(re: Regex, src: &str, mut rep: R)
1048+
/// -> String {
1049+
/// let dst = re.replace_all(src, rep.by_ref());
1050+
/// let dst = re.replace_all(&dst, rep.by_ref());
1051+
/// dst.into_owned()
1052+
/// }
1053+
/// ```
1054+
fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
1055+
ReplacerRef(self)
1056+
}
1057+
}
1058+
1059+
/// By-reference adaptor for a `Replacer`
1060+
///
1061+
/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
1062+
pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
1063+
1064+
impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
1065+
fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
1066+
self.0.replace_append(caps, dst)
1067+
}
1068+
fn no_expansion(&mut self) -> Option<Cow<str>> {
1069+
self.0.no_expansion()
1070+
}
10371071
}
10381072

10391073
impl<'a> Replacer for &'a str {

0 commit comments

Comments
 (0)