Skip to content

Commit 33ea2a9

Browse files
committed
Add support for allocating multiple items at the same time.
1 parent bb6f7b8 commit 33ea2a9

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

src/vec.rs

+41
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
use {alloc::vec::Vec, core::ptr};
23

34
/// A typesafe helper that separates new value construction from
@@ -22,6 +23,26 @@ impl<'a, T> VecAllocation<'a, T> {
2223
}
2324
}
2425

26+
pub struct VecArrayAllocation<'a, T: 'a, const N: usize > {
27+
vec: &'a mut Vec<T>,
28+
index: usize,
29+
}
30+
31+
impl<'a, T, const N: usize> VecArrayAllocation<'a, T, N> {
32+
/// Consumes self and writes the given value into the allocation.
33+
// writing is safe because alloc() ensured enough capacity
34+
// and `Allocation` holds a mutable borrow to prevent anyone else
35+
// from breaking this invariant.
36+
#[inline(always)]
37+
pub fn init(self, value: [T; N]) -> usize {
38+
unsafe {
39+
ptr::write(self.vec.as_mut_ptr().add(self.index) as *mut [T; N], value);
40+
self.vec.set_len(self.index + N);
41+
}
42+
self.index
43+
}
44+
}
45+
2546
/// An entry into a vector, similar to `std::collections::hash_map::Entry`.
2647
pub enum VecEntry<'a, T: 'a> {
2748
/// Entry has just been freshly allocated.
@@ -52,6 +73,8 @@ pub trait VecHelper<T> {
5273
/// Either returns an existing element, or grows the vector by one.
5374
/// Doesn't expect indices to be higher than the current length.
5475
fn entry(&mut self, index: usize) -> VecEntry<T>;
76+
77+
fn alloc_multiple<const N: usize>(&mut self) -> VecArrayAllocation<T, N>;
5578
}
5679

5780
impl<T> VecHelper<T> for Vec<T> {
@@ -63,6 +86,12 @@ impl<T> VecHelper<T> for Vec<T> {
6386
VecAllocation { vec: self, index }
6487
}
6588

89+
fn alloc_multiple<const N: usize>(&mut self) -> VecArrayAllocation<T, N> {
90+
self.reserve(N);
91+
let index = self.len();
92+
VecArrayAllocation { vec: self, index }
93+
}
94+
6695
fn entry(&mut self, index: usize) -> VecEntry<T> {
6796
if index < self.len() {
6897
VecEntry::Occupied(unsafe { self.get_unchecked_mut(index) })
@@ -94,3 +123,15 @@ fn test_zero_copy() {
94123
//TODO: make the expected value to be concrete
95124
assert_ne!(unsafe { vec[0].big[1] }, 1.0);
96125
}
126+
127+
#[test]
128+
fn test_add_multiple() {
129+
use alloc::vec;
130+
let mut vec = vec![1, 2, 3];
131+
132+
// check that the new helper is not overwriting
133+
vec.remove(0);
134+
vec.alloc_multiple().init([4, 5]);
135+
assert_eq!(vec, [2, 3, 4, 5])
136+
137+
}

0 commit comments

Comments
 (0)