Skip to content

Commit

Permalink
api: Replacer for more string types
Browse files Browse the repository at this point in the history
And do the same for the bytes oriented APIs.

This results in some small quality of life improvements
when using the Replacer trait with a string type that
isn't &str.

PR #728
  • Loading branch information
nooberfsh authored Jan 12, 2021
1 parent 373d5ca commit 2bab987
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 15 deletions.
59 changes: 52 additions & 7 deletions src/re_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,9 +1105,9 @@ impl<'c, 't> FusedIterator 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<u8>` (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<u8>` (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.
///
Expand Down Expand Up @@ -1176,10 +1176,55 @@ impl<'a> Replacer for &'a [u8] {
}

fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
match find_byte(b'$', *self) {
Some(_) => None,
None => Some(Cow::Borrowed(*self)),
}
no_expansion(self)
}
}

impl<'a> Replacer for &'a Vec<u8> {
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
caps.expand(*self, dst);
}

fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
no_expansion(self)
}
}

impl Replacer for Vec<u8> {
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
caps.expand(self, dst);
}

fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
no_expansion(self)
}
}

impl<'a> Replacer for Cow<'a, [u8]> {
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
caps.expand(self.as_ref(), dst);
}

fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
no_expansion(self)
}
}

impl<'a> Replacer for &'a Cow<'a, [u8]> {
fn replace_append(&mut self, caps: &Captures, dst: &mut Vec<u8>) {
caps.expand(self.as_ref(), dst);
}

fn no_expansion(&mut self) -> Option<Cow<[u8]>> {
no_expansion(self)
}
}

fn no_expansion<T: AsRef<[u8]>>(t: &T) -> Option<Cow<[u8]>> {
let s = t.as_ref();
match find_byte(b'$', s) {
Some(_) => None,
None => Some(Cow::Borrowed(s)),
}
}

Expand Down
59 changes: 52 additions & 7 deletions src/re_unicode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1147,9 +1147,9 @@ impl<'r, 't> FusedIterator 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<str>`), 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<str>`), which covers most use cases.
pub trait Replacer {
/// Appends text to `dst` to replace the current match.
///
Expand Down Expand Up @@ -1218,10 +1218,55 @@ impl<'a> Replacer for &'a str {
}

fn no_expansion(&mut self) -> Option<Cow<str>> {
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<Cow<str>> {
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<Cow<str>> {
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<Cow<str>> {
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<Cow<str>> {
no_expansion(self)
}
}

fn no_expansion<T: AsRef<str>>(t: &T) -> Option<Cow<str>> {
let s = t.as_ref();
match find_byte(b'$', s.as_bytes()) {
Some(_) => None,
None => Some(Cow::Borrowed(s)),
}
}

Expand Down
1 change: 0 additions & 1 deletion tests/macros_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 { () => { <Vec<&[u8]>>::new() } }

macro_rules! bytes { ($text:expr) => { $text } }

macro_rules! no_expand {
Expand Down
1 change: 1 addition & 0 deletions tests/macros_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 { () => { <Vec<&str>>::new() } }
macro_rules! bytes { ($text:expr) => { std::str::from_utf8($text.as_ref()).unwrap() } }

macro_rules! no_expand {
($text:expr) => {{
Expand Down
98 changes: 98 additions & 0 deletions tests/replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
);

0 comments on commit 2bab987

Please sign in to comment.