Skip to content

Commit a4e3a3a

Browse files
committed
Expose more std::vec::Vec methods
1 parent 402238a commit a4e3a3a

File tree

1 file changed

+123
-9
lines changed

1 file changed

+123
-9
lines changed

lib.rs

Lines changed: 123 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub struct SmallVec<A: Array> {
9090
}
9191

9292
impl<A: Array> SmallVec<A> {
93-
unsafe fn set_len(&mut self, new_len: usize) {
93+
pub unsafe fn set_len(&mut self, new_len: usize) {
9494
self.len = new_len
9595
}
9696

@@ -190,6 +190,82 @@ impl<A: Array> SmallVec<A> {
190190
});
191191
}
192192
}
193+
194+
pub fn reserve(&mut self, additional: usize) {
195+
let len = self.len();
196+
if self.capacity() - len < additional {
197+
match len.checked_add(additional).and_then(usize::checked_next_power_of_two) {
198+
Some(cap) => self.grow(cap),
199+
None => self.grow(usize::max_value()),
200+
}
201+
}
202+
}
203+
204+
pub fn reserve_exact(&mut self, additional: usize) {
205+
let len = self.len();
206+
if self.capacity() - len < additional {
207+
match len.checked_add(additional) {
208+
Some(cap) => self.grow(cap),
209+
None => panic!("reserve_exact overflow"),
210+
}
211+
}
212+
}
213+
214+
pub fn shrink_to_fit(&mut self) {
215+
let len = self.len;
216+
if self.spilled() && self.capacity() > len {
217+
self.grow(len);
218+
}
219+
}
220+
221+
pub fn truncate(&mut self, len: usize) {
222+
let end_ptr = self.as_ptr();
223+
while len < self.len {
224+
unsafe {
225+
let last_index = self.len - 1;
226+
self.set_len(last_index);
227+
ptr::read(end_ptr.offset(last_index as isize));
228+
}
229+
}
230+
}
231+
232+
pub fn swap_remove(&mut self, index: usize) -> A::Item {
233+
let len = self.len;
234+
self.swap(len - 1, index);
235+
self.pop().unwrap()
236+
}
237+
238+
pub fn clear(&mut self) {
239+
self.truncate(0);
240+
}
241+
242+
pub fn remove(&mut self, index: usize) -> A::Item {
243+
let len = self.len();
244+
245+
assert!(index < len);
246+
247+
unsafe {
248+
let ptr = self.as_mut_ptr().offset(index as isize);
249+
let item = ptr::read(ptr);
250+
ptr::copy(ptr.offset(1), ptr, len - index - 1);
251+
self.set_len(len - 1);
252+
item
253+
}
254+
}
255+
256+
pub fn insert(&mut self, index: usize, element: A::Item) {
257+
self.reserve(1);
258+
259+
let len = self.len;
260+
assert!(index <= len);
261+
262+
unsafe {
263+
let ptr = self.as_mut_ptr().offset(index as isize);
264+
ptr::copy(ptr, ptr.offset(1), len - index);
265+
ptr::write(ptr, element);
266+
self.set_len(len + 1);
267+
}
268+
}
193269
}
194270

195271
impl<A: Array> ops::Deref for SmallVec<A> {
@@ -378,20 +454,20 @@ macro_rules! impl_array(
378454
}
379455
);
380456

381-
impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32);
457+
impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32,
458+
0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000,
459+
0x10000, 0x20000, 0x40000, 0x80000, 0x100000);
382460

383461
#[cfg(test)]
384462
pub mod tests {
385463
use SmallVec;
386-
use SmallVec2;
387-
use SmallVec16;
388464
use std::borrow::ToOwned;
389465

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

392468
#[test]
393469
pub fn test_inline() {
394-
let mut v = SmallVec16::new();
470+
let mut v = SmallVec::<[_; 16]>::new();
395471
v.push("hello".to_owned());
396472
v.push("there".to_owned());
397473
assert_eq!(&*v, &[
@@ -402,7 +478,7 @@ pub mod tests {
402478

403479
#[test]
404480
pub fn test_spill() {
405-
let mut v = SmallVec2::new();
481+
let mut v = SmallVec::<[_; 2]>::new();
406482
v.push("hello".to_owned());
407483
assert_eq!(v[0], "hello");
408484
v.push("there".to_owned());
@@ -419,7 +495,7 @@ pub mod tests {
419495

420496
#[test]
421497
pub fn test_double_spill() {
422-
let mut v = SmallVec2::new();
498+
let mut v = SmallVec::<[_; 2]>::new();
423499
v.push("hello".to_owned());
424500
v.push("there".to_owned());
425501
v.push("burma".to_owned());
@@ -443,13 +519,13 @@ pub mod tests {
443519
/// https://github.com/servo/rust-smallvec/issues/4
444520
#[test]
445521
fn issue_4() {
446-
SmallVec2::<Box<u32>>::new();
522+
SmallVec::<[Box<u32>; 2]>::new();
447523
}
448524

449525
/// https://github.com/servo/rust-smallvec/issues/5
450526
#[test]
451527
fn issue_5() {
452-
assert!(Some(SmallVec2::<&u32>::new()).is_some());
528+
assert!(Some(SmallVec::<[&u32; 2]>::new()).is_some());
453529
}
454530

455531
#[test]
@@ -464,4 +540,42 @@ pub mod tests {
464540
v.push(5);
465541
assert_eq!(v.into_iter().collect::<Vec<_>>(), &[3, 4, 5]);
466542
}
543+
544+
#[test]
545+
fn test_capacity() {
546+
let mut v: SmallVec<[u8; 2]> = SmallVec::new();
547+
v.reserve(1);
548+
assert_eq!(v.capacity(), 2);
549+
assert!(!v.spilled());
550+
551+
v.reserve_exact(0x100);
552+
assert!(v.capacity() >= 0x100);
553+
554+
v.push(0);
555+
v.push(1);
556+
v.push(2);
557+
v.push(3);
558+
559+
v.shrink_to_fit();
560+
assert!(v.capacity() < 0x100);
561+
}
562+
563+
#[test]
564+
fn test_truncate() {
565+
let mut v: SmallVec<[Box<u8>; 8]> = SmallVec::new();
566+
567+
for x in 0..8 {
568+
v.push(Box::new(x));
569+
}
570+
v.truncate(4);
571+
572+
assert_eq!(v.len(), 4);
573+
assert!(!v.spilled());
574+
575+
assert_eq!(*v.swap_remove(1), 1);
576+
assert_eq!(*v.remove(1), 3);
577+
v.insert(1, Box::new(3));
578+
579+
assert_eq!(&v.iter().map(|v| **v).collect::<Vec<_>>(), &[0, 3, 2]);
580+
}
467581
}

0 commit comments

Comments
 (0)