Skip to content

Commit 15c41c8

Browse files
committed
Implement insert_slice for SmallVec
Add benchmark for insert_many
1 parent 3232d37 commit 15c41c8

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

benches/bench.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ fn bench_insert(b: &mut Bencher) {
3838
});
3939
}
4040

41+
#[bench]
42+
fn bench_insert_many(b: &mut Bencher) {
43+
#[inline(never)]
44+
fn insert_many_noinline<I: IntoIterator<Item=u64>>(
45+
vec: &mut SmallVec<[u64; 16]>, index: usize, iterable: I) {
46+
vec.insert_many(index, iterable)
47+
}
48+
49+
b.iter(|| {
50+
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
51+
insert_many_noinline(&mut vec, 0, 0..100);
52+
insert_many_noinline(&mut vec, 0, 0..100);
53+
vec
54+
});
55+
}
56+
4157
#[bench]
4258
fn bench_extend(b: &mut Bencher) {
4359
b.iter(|| {

lib.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,32 @@ impl<A: Array> SmallVec<A> {
313313
self.set_len(len + 1);
314314
}
315315
}
316+
317+
pub fn insert_many<I: IntoIterator<Item=A::Item>>(&mut self, index: usize, iterable: I) {
318+
let iter = iterable.into_iter();
319+
let (lower_size_bound, _) = iter.size_hint();
320+
self.reserve(lower_size_bound);
321+
322+
unsafe {
323+
let ptr = self.as_mut_ptr().offset(index as isize);
324+
let old_len = self.len;
325+
ptr::copy(ptr, ptr.offset(lower_size_bound as isize), old_len - index);
326+
for (off, element) in iter.enumerate() {
327+
if off < lower_size_bound {
328+
ptr::write(ptr.offset(off as isize), element);
329+
self.len = self.len + 1;
330+
} else {
331+
// Iterator provided more elements than the hint.
332+
self.insert(index + off, element);
333+
}
334+
}
335+
let num_added = self.len - old_len;
336+
if num_added < lower_size_bound {
337+
// Iterator provided less elements than the hint
338+
ptr::copy(ptr.offset(lower_size_bound as isize), ptr.offset(num_added as isize), old_len - index);
339+
}
340+
}
341+
}
316342
}
317343

318344
impl<A: Array> ops::Deref for SmallVec<A> {
@@ -867,6 +893,46 @@ pub mod tests {
867893
assert_eq!(&v.iter().map(|v| **v).collect::<Vec<_>>(), &[0, 3, 2]);
868894
}
869895

896+
#[test]
897+
fn test_insert_many() {
898+
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
899+
for x in 0..4 {
900+
v.push(x);
901+
}
902+
assert_eq!(v.len(), 4);
903+
v.insert_many(1, [5, 6].iter().cloned());
904+
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
905+
}
906+
907+
struct MockHintIter<T: Iterator>{x: T, hint: usize}
908+
impl<T: Iterator> Iterator for MockHintIter<T> {
909+
type Item = T::Item;
910+
fn next(&mut self) -> Option<Self::Item> {self.x.next()}
911+
fn size_hint(&self) -> (usize, Option<usize>) {(self.hint, None)}
912+
}
913+
914+
#[test]
915+
fn test_insert_many_short_hint() {
916+
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
917+
for x in 0..4 {
918+
v.push(x);
919+
}
920+
assert_eq!(v.len(), 4);
921+
v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 5});
922+
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
923+
}
924+
925+
#[test]
926+
fn test_insert_many_long_hint() {
927+
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
928+
for x in 0..4 {
929+
v.push(x);
930+
}
931+
assert_eq!(v.len(), 4);
932+
v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 1});
933+
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
934+
}
935+
870936
#[test]
871937
#[should_panic]
872938
fn test_drop_panic_smallvec() {

0 commit comments

Comments
 (0)