diff --git a/src/re_bytes.rs b/src/re_bytes.rs index ca01e0ec98..5ef41bc1b4 100644 --- a/src/re_bytes.rs +++ b/src/re_bytes.rs @@ -1077,9 +1077,9 @@ impl<'c, 't> Iterator for SubCaptureMatches<'c, 't> { /// string. /// /// In general, users of this crate shouldn't need to implement this trait, -/// since implementations are already provided for `&[u8]` and -/// `FnMut(&Captures) -> Vec` (or any `FnMut(&Captures) -> T` -/// where `T: AsRef<[u8]>`), which covers most use cases. +/// since implementations are already provided for `&[u8]` along with other +/// variants of bytes types and `FnMut(&Captures) -> Vec` (or any +/// `FnMut(&Captures) -> T` where `T: AsRef<[u8]>`), which covers most use cases. pub trait Replacer { /// Appends text to `dst` to replace the current match. /// @@ -1148,10 +1148,55 @@ impl<'a> Replacer for &'a [u8] { } fn no_expansion(&mut self) -> Option> { - match find_byte(b'$', *self) { - Some(_) => None, - None => Some(Cow::Borrowed(*self)), - } + no_expansion(self) + } +} + +impl<'a> Replacer for &'a Vec { + fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) { + caps.expand(*self, dst); + } + + fn no_expansion(&mut self) -> Option> { + no_expansion(self) + } +} + +impl Replacer for Vec { + fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) { + caps.expand(self, dst); + } + + fn no_expansion(&mut self) -> Option> { + no_expansion(self) + } +} + +impl<'a> Replacer for Cow<'a, [u8]> { + fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) { + caps.expand(self.as_ref(), dst); + } + + fn no_expansion(&mut self) -> Option> { + no_expansion(self) + } +} + +impl<'a> Replacer for &'a Cow<'a, [u8]> { + fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) { + caps.expand(self.as_ref(), dst); + } + + fn no_expansion(&mut self) -> Option> { + no_expansion(self) + } +} + +fn no_expansion>(t: &T) -> Option> { + let s = t.as_ref(); + match find_byte(b'$', s) { + Some(_) => None, + None => Some(Cow::Borrowed(s)), } } diff --git a/src/re_unicode.rs b/src/re_unicode.rs index ea95c1b6df..afdc61d218 100644 --- a/src/re_unicode.rs +++ b/src/re_unicode.rs @@ -1119,9 +1119,9 @@ impl<'r, 't> Iterator for Matches<'r, 't> { /// Replacer describes types that can be used to replace matches in a string. /// /// In general, users of this crate shouldn't need to implement this trait, -/// since implementations are already provided for `&str` and -/// `FnMut(&Captures) -> String` (or any `FnMut(&Captures) -> T` -/// where `T: AsRef`), which covers most use cases. +/// since implementations are already provided for `&str` along with other +/// variants of string types and `FnMut(&Captures) -> String` (or any +/// `FnMut(&Captures) -> T` where `T: AsRef`), which covers most use cases. pub trait Replacer { /// Appends text to `dst` to replace the current match. /// @@ -1190,10 +1190,55 @@ impl<'a> Replacer for &'a str { } fn no_expansion(&mut self) -> Option> { - match find_byte(b'$', self.as_bytes()) { - Some(_) => None, - None => Some(Cow::Borrowed(*self)), - } + no_expansion(self) + } +} + +impl<'a> Replacer for &'a String { + fn replace_append(&mut self, caps: &Captures, dst: &mut String) { + self.as_str().replace_append(caps, dst) + } + + fn no_expansion(&mut self) -> Option> { + no_expansion(self) + } +} + +impl Replacer for String { + fn replace_append(&mut self, caps: &Captures, dst: &mut String) { + self.as_str().replace_append(caps, dst) + } + + fn no_expansion(&mut self) -> Option> { + no_expansion(self) + } +} + +impl<'a> Replacer for Cow<'a, str> { + fn replace_append(&mut self, caps: &Captures, dst: &mut String) { + self.as_ref().replace_append(caps, dst) + } + + fn no_expansion(&mut self) -> Option> { + no_expansion(self) + } +} + +impl<'a> Replacer for &'a Cow<'a, str> { + fn replace_append(&mut self, caps: &Captures, dst: &mut String) { + self.as_ref().replace_append(caps, dst) + } + + fn no_expansion(&mut self) -> Option> { + no_expansion(self) + } +} + +fn no_expansion>(t: &T) -> Option> { + let s = t.as_ref(); + match find_byte(b'$', s.as_bytes()) { + Some(_) => None, + None => Some(Cow::Borrowed(s)), } } diff --git a/tests/macros_bytes.rs b/tests/macros_bytes.rs index 03c370d698..3d6c8c3ac8 100644 --- a/tests/macros_bytes.rs +++ b/tests/macros_bytes.rs @@ -4,7 +4,6 @@ macro_rules! t { ($re:expr) => { text!($re) } } macro_rules! match_text { ($text:expr) => { $text.as_bytes() } } macro_rules! use_ { ($($path: tt)*) => { use regex::bytes::$($path)*; } } macro_rules! empty_vec { () => { >::new() } } - macro_rules! bytes { ($text:expr) => { $text } } macro_rules! no_expand { diff --git a/tests/macros_str.rs b/tests/macros_str.rs index 9b996b33b9..7b7eb110c2 100644 --- a/tests/macros_str.rs +++ b/tests/macros_str.rs @@ -4,6 +4,7 @@ macro_rules! t { ($text:expr) => { text!($text) } } macro_rules! match_text { ($text:expr) => { $text.as_str() } } macro_rules! use_ { ($($path: tt)*) => { use regex::$($path)*; } } macro_rules! empty_vec { () => { >::new() } } +macro_rules! bytes { ($text:expr) => { std::str::from_utf8($text.as_ref()).unwrap() } } macro_rules! no_expand { ($text:expr) => {{ diff --git a/tests/replace.rs b/tests/replace.rs index c156a399ff..700aff2430 100644 --- a/tests/replace.rs +++ b/tests/replace.rs @@ -130,3 +130,101 @@ replace!( t!("${1}a $1a"), "ba " ); + +replace!( + impl_string, + replace, + r"[0-9]", + "age: 26", + t!("Z".to_string()), + "age: Z6" +); +replace!( + impl_string_ref, + replace, + r"[0-9]", + "age: 26", + t!(&"Z".to_string()), + "age: Z6" +); +replace!( + impl_cow_str_borrowed, + replace, + r"[0-9]", + "age: 26", + t!(std::borrow::Cow::<'_, str>::Borrowed("Z")), + "age: Z6" +); +replace!( + impl_cow_str_borrowed_ref, + replace, + r"[0-9]", + "age: 26", + t!(&std::borrow::Cow::<'_, str>::Borrowed("Z")), + "age: Z6" +); +replace!( + impl_cow_str_owned, + replace, + r"[0-9]", + "age: 26", + t!(std::borrow::Cow::<'_, str>::Owned("Z".to_string())), + "age: Z6" +); +replace!( + impl_cow_str_owned_ref, + replace, + r"[0-9]", + "age: 26", + t!(&std::borrow::Cow::<'_, str>::Owned("Z".to_string())), + "age: Z6" +); + +replace!( + impl_vec_u8, + replace, + r"[0-9]", + "age: 26", + bytes!(vec![b'Z']), + "age: Z6" +); +replace!( + impl_vec_u8_ref, + replace, + r"[0-9]", + "age: 26", + bytes!(&vec![b'Z']), + "age: Z6" +); +replace!( + impl_cow_slice_borrowed, + replace, + r"[0-9]", + "age: 26", + bytes!(std::borrow::Cow::<'_, [u8]>::Borrowed(&[b'Z'])), + "age: Z6" +); +replace!( + impl_cow_slice_borrowed_ref, + replace, + r"[0-9]", + "age: 26", + bytes!(&std::borrow::Cow::<'_, [u8]>::Borrowed(&[b'Z'])), + "age: Z6" +); +replace!( + impl_cow_slice_owned, + replace, + r"[0-9]", + "age: 26", + bytes!(std::borrow::Cow::<'_, [u8]>::Owned(vec![b'Z'])), + "age: Z6" +); +replace!( + impl_cow_slice_owned_ref, + replace, + r"[0-9]", + "age: 26", + bytes!(&std::borrow::Cow::<'_, [u8]>::Owned(vec![b'Z'])), + "age: Z6" +);