use std::ops::{Deref, DerefMut};
use wide::u8x16;
pub trait BulkVecExtender<T> {
fn bulk_extend_guard(&mut self, elements_to_write: usize) -> BulkExtendGuard<'_, T>;
}
pub struct BulkExtendGuard<'a, T> {
vec: &'a mut Vec<T>,
original_len: usize,
extended_by: usize,
written: usize,
}
impl<'a, T> BulkExtendGuard<'a, T> {
#[inline(always)]
fn new(vec: &'a mut Vec<T>, elements_to_write: usize) -> Self {
let original_len = vec.len();
let new_len = original_len + elements_to_write;
vec.reserve(elements_to_write);
unsafe {
vec.set_len(new_len);
}
Self {
vec,
original_len,
extended_by: elements_to_write,
written: elements_to_write, }
}
#[inline(always)]
pub fn set_written(&mut self, count: usize) {
self.written = count.min(self.extended_by);
}
#[inline(always)]
pub fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.vec[self.original_len..]
}
}
impl<T> Deref for BulkExtendGuard<'_, T> {
type Target = [T];
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.vec[self.original_len..]
}
}
impl<T> DerefMut for BulkExtendGuard<'_, T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.vec[self.original_len..]
}
}
impl<T> Drop for BulkExtendGuard<'_, T> {
#[inline(always)]
fn drop(&mut self) {
self.vec.truncate(self.original_len + self.written);
}
}
impl<T> BulkVecExtender<T> for Vec<T> {
#[inline(always)]
fn bulk_extend_guard(&mut self, elements_to_write: usize) -> BulkExtendGuard<'_, T> {
BulkExtendGuard::new(self, elements_to_write)
}
}
pub trait SliceU8SIMDExtender {
fn write_u8x16(&mut self, index: usize, value: u8x16, slice_len: usize);
}
impl SliceU8SIMDExtender for &mut [u8] {
#[inline(always)]
fn write_u8x16(&mut self, index: usize, value: u8x16, slice_len: usize) {
self[index..index + slice_len].copy_from_slice(&value.to_array()[..slice_len]);
}
}