diff --git a/examples/shootout-regex-dna-bytes.rs b/examples/shootout-regex-dna-bytes.rs index 7bd0bf1bfe..3b120260c0 100644 --- a/examples/shootout-regex-dna-bytes.rs +++ b/examples/shootout-regex-dna-bytes.rs @@ -14,7 +14,7 @@ use std::thread; macro_rules! regex { ($re:expr) => { ::regex::bytes::Regex::new($re).unwrap() } } fn main() { - let mut seq = Vec::with_capacity(50 * (1 << 20)); + let mut seq = Vec::with_capacity(51 * (1 << 20)); io::stdin().read_to_end(&mut seq).unwrap(); let ilen = seq.len(); diff --git a/examples/shootout-regex-dna.rs b/examples/shootout-regex-dna.rs index 2cd0b65bb1..d66b4fdf06 100644 --- a/examples/shootout-regex-dna.rs +++ b/examples/shootout-regex-dna.rs @@ -14,7 +14,7 @@ use std::thread; macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } } fn main() { - let mut seq = String::with_capacity(50 * (1 << 20)); + let mut seq = String::with_capacity(51 * (1 << 20)); io::stdin().read_to_string(&mut seq).unwrap(); let ilen = seq.len(); diff --git a/src/re_bytes.rs b/src/re_bytes.rs index 7d2d33f437..0e3fc777b7 100644 --- a/src/re_bytes.rs +++ b/src/re_bytes.rs @@ -445,11 +445,11 @@ impl Regex { if limit > 0 && i >= limit { break } - new.extend(&text[last_match..s]); - new.extend(&*rep); + extend_from_slice(&mut new, &text[last_match..s]); + extend_from_slice(&mut new, &*rep); last_match = e; } - new.extend(&text[last_match..]); + extend_from_slice(&mut new, &text[last_match..]); return new; } @@ -463,11 +463,11 @@ impl Regex { } // unwrap on 0 is OK because captures only reports matches let (s, e) = cap.pos(0).unwrap(); - new.extend(&text[last_match..s]); + extend_from_slice(&mut new, &text[last_match..s]); rep.replace_append(&cap, &mut new); last_match = e; } - new.extend(&text[last_match..]); + extend_from_slice(&mut new, &text[last_match..]); new } @@ -928,7 +928,7 @@ impl<'a> Replacer for &'a [u8] { impl Replacer for F where F: FnMut(&Captures) -> Vec { fn replace_append(&mut self, caps: &Captures, dst: &mut Vec) { - dst.extend((*self)(caps)) + extend_from_slice(dst, &(*self)(caps)); } } @@ -944,10 +944,26 @@ pub struct NoExpand<'r>(pub &'r [u8]); impl<'a> Replacer for NoExpand<'a> { fn replace_append(&mut self, _: &Captures, dst: &mut Vec) { - dst.extend(self.0) + extend_from_slice(dst, self.0); } fn no_expansion<'r>(&'r mut self) -> Option> { Some(Cow::Borrowed(self.0)) } } + +/// This hopefully has the same performance characteristics as +/// Vec::extend_from_slice (which was introduced in Rust 1.6), but works on +/// Rust 1.3. +/// +/// N.B. Remove this once we do a semver bump. At that point, we'll bump +/// required Rust version to at least 1.6. +fn extend_from_slice(dst: &mut Vec, src: &[u8]) { + dst.reserve(src.len()); + let dst_len = dst.len(); + unsafe { dst.set_len(dst_len + src.len()); } + let mut dst = &mut dst[dst_len..dst_len + src.len()]; + for i in 0..src.len() { + dst[i] = src[i]; + } +}