Skip to content

Commit c6065b5

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 c6065b5

File tree

3 files changed

+75
-1
lines changed

3 files changed

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

+37
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,43 @@ 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+
///
1000+
/// # Example
1001+
///
1002+
/// ```
1003+
/// use regex::bytes::{Regex, Replacer};
1004+
///
1005+
/// fn replace_all_twice<R: Replacer>(re: Regex, src: &[u8], mut rep: R)
1006+
/// -> Vec<u8> {
1007+
/// let dst = re.replace_all(src, rep.by_ref());
1008+
/// let dst = re.replace_all(&dst, rep.by_ref());
1009+
/// dst.into_owned()
1010+
/// }
1011+
/// ```
1012+
fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
1013+
ReplacerRef(self)
1014+
}
1015+
}
1016+
1017+
/// By-reference adaptor for a `Replacer`
1018+
///
1019+
/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
1020+
#[derive(Debug)]
1021+
pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
1022+
1023+
impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
1024+
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
1025+
self.0.replace_append(caps, dst)
1026+
}
1027+
fn no_expansion<'r>(&'r mut self) -> Option<Cow<'r, [u8]>> {
1028+
self.0.no_expansion()
1029+
}
9931030
}
9941031

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

src/re_unicode.rs

+37
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,43 @@ 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+
/// # Example
1045+
///
1046+
/// ```
1047+
/// use regex::{Regex, Replacer};
1048+
///
1049+
/// fn replace_all_twice<R: Replacer>(re: Regex, src: &str, mut rep: R)
1050+
/// -> String {
1051+
/// let dst = re.replace_all(src, rep.by_ref());
1052+
/// let dst = re.replace_all(&dst, rep.by_ref());
1053+
/// dst.into_owned()
1054+
/// }
1055+
/// ```
1056+
fn by_ref<'r>(&'r mut self) -> ReplacerRef<'r, Self> {
1057+
ReplacerRef(self)
1058+
}
1059+
}
1060+
1061+
/// By-reference adaptor for a `Replacer`
1062+
///
1063+
/// Returned by [`Replacer::by_ref`](trait.Replacer.html#method.by_ref).
1064+
#[derive(Debug)]
1065+
pub struct ReplacerRef<'a, R: ?Sized + 'a>(&'a mut R);
1066+
1067+
impl<'a, R: Replacer + ?Sized + 'a> Replacer for ReplacerRef<'a, R> {
1068+
fn replace_append(&mut self, caps: &Captures, dst: &mut String) {
1069+
self.0.replace_append(caps, dst)
1070+
}
1071+
fn no_expansion(&mut self) -> Option<Cow<str>> {
1072+
self.0.no_expansion()
1073+
}
10371074
}
10381075

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

0 commit comments

Comments
 (0)