Implement insert for tinyvec

This commit is contained in:
Quentin Boyer 2024-12-10 16:38:43 +01:00
parent 25a5c7e4e3
commit 1e029b4adb
2 changed files with 81 additions and 1 deletions

View file

@ -22,7 +22,15 @@
inherit system;
overlays = [ (import rust-overlay) ];
};
rust = pkgs.rust-bin.stable.latest.default.override { extensions = [ "rust-src" ]; };
rust = pkgs.rust-bin.selectLatestNightlyWith (
toolchain:
toolchain.default.override {
extensions = [
"rust-src"
"miri"
];
}
);
naersk' = pkgs.callPackage naersk {
cargo = rust;
rustc = rust;

View file

@ -63,6 +63,37 @@ impl<T: Copy> TinyVec<T> {
Layout::from_size_align(127 * size_of::<T>(), 1).unwrap()
}
pub fn insert_at(&mut self, at: usize, v: T) {
if at > self.len() {
panic!("Out of bound access")
}
if at == self.len() {
return self.push(v);
}
let ptr = match self.is_stack() {
true => {
let new_stack_len = (self.len() + 1) * size_of::<T>();
if new_stack_len > STACK_LEN {
self.spill();
self.insert_at(at, v);
return;
} else {
unsafe { self.inner.stack.data.as_mut_ptr() }
}
}
false => unsafe { self.inner.heap.data },
};
unsafe {
let place = ptr.cast::<T>().add(at);
place.add(1).copy_from(place, self.len() - at);
place.write(v);
self.inner.len.len += 1
}
}
pub fn extend_from_slice(&mut self, slice: &[T]) {
let old_len = self.len();
let new_len = old_len + slice.len();
@ -134,6 +165,12 @@ impl<T: Copy> TinyVec<T> {
}
}
impl<T: Copy + std::fmt::Debug> std::fmt::Debug for TinyVec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self).finish()
}
}
impl<T: Copy> std::ops::Deref for TinyVec<T> {
type Target = [T];
@ -327,6 +364,41 @@ mod test {
assert_eq!(&*a, values);
}
#[test]
pub fn insert_stack() {
let mut a = TinyVec::<[u8; 2]>::new();
a.push([1, 2]);
a.push([3, 4]);
a.insert_at(1, [5, 6]);
assert_eq!(&*a, &[[1, 2], [5, 6], [3, 4]]);
}
#[test]
pub fn insert_heap() {
let mut values = vec![[0, 0]; 16];
let mut a = TinyVec::<[u8; 2]>::new();
a.extend_from_slice(&values);
values.insert(1, [5, 6]);
a.insert_at(1, [5, 6]);
assert_eq!(&*a, &values);
}
#[test]
pub fn insert_spill() {
let mut values = vec![[0, 0]; 7];
let mut a = TinyVec::<[u8; 2]>::new();
a.extend_from_slice(&values);
values.insert(1, [5, 6]);
a.insert_at(1, [5, 6]);
assert_eq!(&*a, &values);
}
#[test]
pub fn push_spill() {
let values = (0..STACK_LEN as u8 + 1).collect_vec();