Skip to content

Commit 65fa109

Browse files
committed
Optimize extend and from_elem
1 parent d1a64d4 commit 65fa109

File tree

1 file changed

+40
-5
lines changed

1 file changed

+40
-5
lines changed

lib.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,10 @@ impl<A: Array> SmallVec<A> {
637637
/// back.
638638
pub fn insert_many<I: IntoIterator<Item=A::Item>>(&mut self, index: usize, iterable: I) {
639639
let iter = iterable.into_iter();
640+
if index == self.len() {
641+
return self.extend(iter);
642+
}
643+
640644
let (lower_size_bound, _) = iter.size_hint();
641645
assert!(lower_size_bound <= std::isize::MAX as usize); // Ensure offset is indexable
642646
assert!(index + lower_size_bound >= index); // Protect against overflow
@@ -805,9 +809,23 @@ impl<A: Array> SmallVec<A> where A::Item: Clone {
805809
/// assert_eq!(v, SmallVec::from_buf(['d', 'd']));
806810
/// ```
807811
pub fn from_elem(elem: A::Item, n: usize) -> Self {
808-
let mut v = SmallVec::with_capacity(n);
809-
v.insert_many(0, (0..n).map(|_| elem.clone()));
810-
v
812+
if n > A::size() {
813+
::std::vec::from_elem(elem, n).into()
814+
} else {
815+
unsafe {
816+
let mut arr: A = ::std::mem::uninitialized();
817+
let ptr = arr.ptr_mut();
818+
819+
for i in 0..n as isize {
820+
::std::ptr::write(ptr.offset(i), elem.clone());
821+
}
822+
823+
SmallVec {
824+
data: Inline { array: arr },
825+
len: n,
826+
}
827+
}
828+
}
811829
}
812830
}
813831

@@ -1001,13 +1019,30 @@ impl<A: Array> FromIterator<A::Item> for SmallVec<A> {
10011019

10021020
impl<A: Array> Extend<A::Item> for SmallVec<A> {
10031021
fn extend<I: IntoIterator<Item=A::Item>>(&mut self, iterable: I) {
1004-
let iter = iterable.into_iter();
1022+
let mut iter = iterable.into_iter();
10051023
let (lower_size_bound, _) = iter.size_hint();
10061024

10071025
let target_len = self.len + lower_size_bound;
10081026

10091027
if target_len > self.capacity() {
1010-
self.grow(target_len);
1028+
self.grow(target_len);
1029+
}
1030+
1031+
unsafe {
1032+
let ptr = self.as_mut_ptr().offset(self.len() as isize);
1033+
1034+
let len = self.len();
1035+
let mut count = 0;
1036+
for p in 0..lower_size_bound as isize {
1037+
if let Some(out) = iter.next() {
1038+
::std::ptr::write(ptr.offset(p), out);
1039+
count += 1;
1040+
} else {
1041+
break;
1042+
}
1043+
}
1044+
1045+
self.set_len(len + count);
10111046
}
10121047

10131048
for elem in iter {

0 commit comments

Comments
 (0)