mirror of
https://github.com/openharmony/third_party_rust_rust-smallvec.git
synced 2026-07-21 01:55:25 -04:00
Auto merge of #28 - nipunn1313:insert_slice, r=jdm
Implement insert_many<IntoIterator> for SmallVec This doesn't work as is, but I wanted to put it up for feedback. According to these docs: https://doc.rust-lang.org/std/ptr/fn.copy_nonoverlapping.html The copy_nonoverlapping function copies memory as intended, but the ownership of the values copied are not copied over to dest, so when the box is consumed, the SmallVec does not maintain ownership. Not sure how to do this with unsafe code. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/28) <!-- Reviewable:end -->
This commit is contained in:
@@ -38,6 +38,22 @@ fn bench_insert(b: &mut Bencher) {
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_insert_many(b: &mut Bencher) {
|
||||
#[inline(never)]
|
||||
fn insert_many_noinline<I: IntoIterator<Item=u64>>(
|
||||
vec: &mut SmallVec<[u64; 16]>, index: usize, iterable: I) {
|
||||
vec.insert_many(index, iterable)
|
||||
}
|
||||
|
||||
b.iter(|| {
|
||||
let mut vec: SmallVec<[u64; 16]> = SmallVec::new();
|
||||
insert_many_noinline(&mut vec, 0, 0..100);
|
||||
insert_many_noinline(&mut vec, 0, 0..100);
|
||||
vec
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_extend(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
|
||||
@@ -445,6 +445,36 @@ impl<A: Array> SmallVec<A> {
|
||||
self.set_len(len + 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_many<I: IntoIterator<Item=A::Item>>(&mut self, index: usize, iterable: I) {
|
||||
let iter = iterable.into_iter();
|
||||
let (lower_size_bound, _) = iter.size_hint();
|
||||
assert!(lower_size_bound <= std::isize::MAX as usize); // Ensure offset is indexable
|
||||
assert!(index + lower_size_bound >= index); // Protect against overflow
|
||||
self.reserve(lower_size_bound);
|
||||
|
||||
unsafe {
|
||||
let old_len = self.len;
|
||||
assert!(index <= old_len);
|
||||
let ptr = self.as_mut_ptr().offset(index as isize);
|
||||
ptr::copy(ptr, ptr.offset(lower_size_bound as isize), old_len - index);
|
||||
for (off, element) in iter.enumerate() {
|
||||
if off < lower_size_bound {
|
||||
ptr::write(ptr.offset(off as isize), element);
|
||||
self.len = self.len + 1;
|
||||
} else {
|
||||
// Iterator provided more elements than the hint.
|
||||
assert!(index + off >= index); // Protect against overflow.
|
||||
self.insert(index + off, element);
|
||||
}
|
||||
}
|
||||
let num_added = self.len - old_len;
|
||||
if num_added < lower_size_bound {
|
||||
// Iterator provided fewer elements than the hint
|
||||
ptr::copy(ptr.offset(lower_size_bound as isize), ptr.offset(num_added as isize), old_len - index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> ops::Deref for SmallVec<A> {
|
||||
@@ -990,6 +1020,46 @@ pub mod tests {
|
||||
assert_eq!(&v.iter().map(|v| **v).collect::<Vec<_>>(), &[0, 3, 2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_many() {
|
||||
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
|
||||
for x in 0..4 {
|
||||
v.push(x);
|
||||
}
|
||||
assert_eq!(v.len(), 4);
|
||||
v.insert_many(1, [5, 6].iter().cloned());
|
||||
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
|
||||
}
|
||||
|
||||
struct MockHintIter<T: Iterator>{x: T, hint: usize}
|
||||
impl<T: Iterator> Iterator for MockHintIter<T> {
|
||||
type Item = T::Item;
|
||||
fn next(&mut self) -> Option<Self::Item> {self.x.next()}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {(self.hint, None)}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_many_short_hint() {
|
||||
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
|
||||
for x in 0..4 {
|
||||
v.push(x);
|
||||
}
|
||||
assert_eq!(v.len(), 4);
|
||||
v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 5});
|
||||
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_many_long_hint() {
|
||||
let mut v: SmallVec<[u8; 8]> = SmallVec::new();
|
||||
for x in 0..4 {
|
||||
v.push(x);
|
||||
}
|
||||
assert_eq!(v.len(), 4);
|
||||
v.insert_many(1, MockHintIter{x: [5, 6].iter().cloned(), hint: 1});
|
||||
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_invalid_grow() {
|
||||
|
||||
Reference in New Issue
Block a user