Skip to content

Commit b432cc2

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 b432cc2

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

src/lib.rs

+1-1
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

+22
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,28 @@ 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 not be cloneable)
997+
/// and use it without consuming it, so it can be used more than once.
998+
fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
999+
ReplacerRef(self)
1000+
}
1001+
}
1002+
1003+
/// By-reference adaptor for a `Replacer`
1004+
///
1005+
/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
1006+
pub struct ReplacerRef<'a, R>(&'a mut R) where R: Replacer + ?Sized + 'a;
1007+
1008+
impl<'a, R> Replacer for ReplacerRef<'a, R> where R: Replacer + ?Sized + 'a {
1009+
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
1010+
self.0.replace_append(caps, dst)
1011+
}
1012+
fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
1013+
self.0.no_expansion()
1014+
}
9931015
}
9941016

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

src/re_unicode.rs

+32
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,38 @@ 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 not be cloneable)
1041+
/// and use it without consuming it, so it can be used more than once:
1042+
///
1043+
/// ```
1044+
/// use regex::{Regex, Replacer};
1045+
///
1046+
/// fn replace_all_twice<R: Replacer>(re: Regex, src: &str, mut rep: R) -> String {
1047+
/// let dst = re.replace_all(src, rep.by_ref());
1048+
/// let dst = re.replace_all(&dst, rep.by_ref());
1049+
/// dst.into_owned()
1050+
/// }
1051+
/// ```
1052+
fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
1053+
ReplacerRef(self)
1054+
}
1055+
}
1056+
1057+
/// By-reference adaptor for a `Replacer`
1058+
///
1059+
/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
1060+
pub struct ReplacerRef<'a, R>(&'a mut R) where R: Replacer + ?Sized + 'a;
1061+
1062+
impl<'a, R> Replacer for ReplacerRef<'a, R> where R: Replacer + ?Sized + 'a {
1063+
fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
1064+
self.0.replace_append(caps, dst)
1065+
}
1066+
fn no_expansion(&mut self) -> Option<Cow<str>> {
1067+
self.0.no_expansion()
1068+
}
10371069
}
10381070

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

0 commit comments

Comments
 (0)