@leudz This is related to Shipyard scripting support
I've got a use-case where I want to be able to store byte "arrays" in a Vec
where the byte arrays might be of any length that can only be determined at runtime. This playground shows my attempt at a wrapper around Vec
that for this use pattern.
#[derive(Debug)]
struct DynamicVec<T> {
storage: Vec<T>,
element_size: usize
}
impl<T: Copy> DynamicVec<T> {
fn new(element_size: usize) -> Self {
Self {
storage: Vec::new(),
element_size,
}
}
fn push(&mut self, data: &[T]) {
debug_assert!(data.len() == self.element_size);
self.storage.extend_from_slice(data);
}
// TODO: Implement other functions: pop, etc.
}
impl<T: Copy> std::ops::Index<usize> for DynamicVec<T> {
type Output = [T];
fn index(&self, index: usize) -> &Self::Output {
&self.storage[index*self.element_size..index*self.element_size+self.element_size]
}
}
What I'm trying to avoid, though is the Copy
bound, which is required to do extend_from_slice
.
I found an unsafe way around the copying, but the problem is that it is unsafe because fills data
with uninitialized memory:
unsafe fn push(&mut self, mut data: &mut [T]) {
debug_assert!(data.len() == self.element_size);
let old_len = self.storage.len();
self.storage.reserve(self.element_size);
self.storage.set_len(old_len + self.element_size);
let (left, right) = self.storage.split_at_mut(old_len);
right.swap_with_slice(&mut data);
}
The data
argument needs to be a slice because I can't know the size of it at compile time, but logically I want to take ownership of data
so that the user can't attempt to use it after push
ing it. Is there any way to do that?