Skip to content

Commit 3ac0159

Browse files
committed
Make shrink-to-fit use the inline buffer when possible
1 parent e00e2ef commit 3ac0159

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

lib.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,9 +350,24 @@ impl<A: Array> SmallVec<A> {
350350
}
351351

352352
/// Shrink the capacity of the vector as much as possible.
353+
///
354+
/// When possible, this will move data from an external heap buffer to the vector's inline
355+
/// storage.
353356
pub fn shrink_to_fit(&mut self) {
354357
let len = self.len;
355-
if self.spilled() && self.capacity() > len {
358+
if len <= self.inline_size() {
359+
unsafe {
360+
let (ptr, capacity) = match &self.data {
361+
&Inline { .. } => return,
362+
&Heap { ptr, capacity } => (ptr, capacity),
363+
};
364+
ptr::write(&mut self.data, Inline { array: mem::uninitialized() });
365+
ptr::copy_nonoverlapping(ptr, self.as_mut_ptr(), len);
366+
deallocate(ptr, capacity);
367+
}
368+
return;
369+
}
370+
if self.capacity() > len {
356371
self.grow(len);
357372
}
358373
}
@@ -760,6 +775,7 @@ impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32,
760775
pub mod tests {
761776
use SmallVec;
762777
use std::borrow::ToOwned;
778+
use std::iter::FromIterator;
763779

764780
// We heap allocate all these strings so that double frees will show up under valgrind.
765781

@@ -1135,4 +1151,13 @@ pub mod tests {
11351151
let mut vec = SmallVec::<[i32; 2]>::from(&[3, 1, 2][..]);
11361152
test(&mut vec);
11371153
}
1154+
1155+
#[test]
1156+
fn shrink_to_fit_unspill() {
1157+
let mut vec = SmallVec::<[u8; 2]>::from_iter(0..3);
1158+
vec.pop();
1159+
assert!(vec.spilled());
1160+
vec.shrink_to_fit();
1161+
assert!(!vec.spilled(), "shrink_to_fit will un-spill if possible");
1162+
}
11381163
}

0 commit comments

Comments
 (0)