I read from the book Programming Rust that you can't have:
// waves is a Vec
waves.extend(&wave);
But this is perfectly fine as long as you preallocate enough capacity since it's not violating the mutation xor aliasing rule: you are mutating [len.. capacity] part of the vector but only aliasing [..len] part. So, I wrote this as a PoC.
use core::slice::from_raw_parts;
use core::marker::PhantomData;
pub struct Reserved<'item: 'collection, 'collection, T: 'item, C: 'collection + ExtLen> {
ptr: *mut T,
capacity: usize,
len: usize,
c: &'collection mut C,
_marker: std::marker::PhantomData<&'item T>,
}
pub trait ExtLen {
unsafe fn ext_len(&mut self, len: usize);
}
impl<'item, 'collection, T: 'item, C: 'collection + ExtLen> Reserved<'item, 'collection, T, C>
where
'item: 'collection,
{
pub fn push(&mut self, t: T) -> Result<(), ()> {
if self.capacity > 0 {
unsafe {
self.ptr.add(self.len).write(t);
}
self.capacity -= 1;
self.len += 1;
Ok(())
} else {
Err(())
}
}
pub fn done(self) {
drop(self)
}
}
impl<'item, 'collection, T: 'item, C: 'collection + ExtLen> Drop
for Reserved<'item, 'collection, T, C>
where
'item: 'collection,
{
fn drop(&mut self) {
unsafe {
self.c.ext_len(self.len);
}
}
}
pub trait VecExt: Sized + ExtLen {
type Item;
fn reserve_and_write(&mut self, n: usize) -> (&[Self::Item], Reserved<Self::Item, Self>);
}
impl<T> ExtLen for Vec<T> {
unsafe fn ext_len(&mut self, len: usize) {
self.set_len(self.len() + len);
}
}
impl<T> VecExt for Vec<T> {
type Item = T;
fn reserve_and_write(&mut self, n: usize) -> (&[T], Reserved<Self::Item, Self>) {
self.reserve_exact(n);
let ptr = unsafe { self.as_mut_ptr().add(self.len()) };
(
unsafe { from_raw_parts(self.as_ptr(), self.len()) },
Reserved {
ptr,
capacity: n,
len: 0,
c: self,
_marker: PhantomData,
},
)
}
}
fn main() {
let mut v: Vec<_> = (0..10).collect();
let (old, mut new) = v.reserve_and_write(v.len());
for value in old {
new.push(*value).unwrap();
}
new.done();
println!("{:?}", v);
}
Since this involves unsafe code, are there any existing established crates that offers similar functionalities?