diff --git a/benches/bench.rs b/benches/bench.rs index c571b85..661b0d9 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -63,6 +63,27 @@ fn bench_extend(b: &mut Bencher) { }); } +#[bench] +fn bench_extend_from_slice(b: &mut Bencher) { + let v: Vec = (0..100).collect(); + b.iter(|| { + let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); + vec.extend_from_slice(&v); + vec + }); +} + +#[bench] +fn bench_insert_from_slice(b: &mut Bencher) { + let v: Vec = (0..100).collect(); + b.iter(|| { + let mut vec: SmallVec<[u64; 16]> = SmallVec::new(); + vec.insert_from_slice(0, &v); + vec.insert_from_slice(0, &v); + vec + }); +} + #[bench] fn bench_pushpop(b: &mut Bencher) { #[inline(never)] diff --git a/lib.rs b/lib.rs index e44c1f7..762b838 100644 --- a/lib.rs +++ b/lib.rs @@ -477,6 +477,29 @@ impl SmallVec { } } +impl SmallVec where A::Item: Copy { + pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) { + self.reserve(slice.len()); + + let len = self.len; + assert!(index <= len); + + unsafe { + let slice_ptr = slice.as_ptr(); + let ptr = self.as_mut_ptr().offset(index as isize); + ptr::copy(ptr, ptr.offset(slice.len() as isize), len - index); + ptr::copy(slice_ptr, ptr, slice.len()); + self.set_len(len + slice.len()); + } + } + + #[inline] + pub fn extend_from_slice(&mut self, slice: &[A::Item]) { + let len = self.len(); + self.insert_from_slice(len, slice); + } +} + impl ops::Deref for SmallVec { type Target = [A::Item]; #[inline] @@ -1068,6 +1091,28 @@ pub mod tests { v.grow(5); } + #[test] + fn test_insert_from_slice() { + let mut v: SmallVec<[u8; 8]> = SmallVec::new(); + for x in 0..4 { + v.push(x); + } + assert_eq!(v.len(), 4); + v.insert_from_slice(1, &[5, 6]); + assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 5, 6, 1, 2, 3]); + } + + #[test] + fn test_extend_from_slice() { + let mut v: SmallVec<[u8; 8]> = SmallVec::new(); + for x in 0..4 { + v.push(x); + } + assert_eq!(v.len(), 4); + v.extend_from_slice(&[5, 6]); + assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 1, 2, 3, 5, 6]); + } + #[test] #[should_panic] fn test_drop_panic_smallvec() {