use std::cell::UnsafeCell;
use std::marker::PhantomData;
use std::ops::Index;
use std::slice;
pub(super) struct ScratchVec<T> {
storage: Box<UnsafeCell<Vec<T>>>,
}
impl<T> Default for ScratchVec<T> {
fn default() -> Self {
Self {
storage: Box::new(UnsafeCell::new(Vec::new())),
}
}
}
impl<T> ScratchVec<T> {
pub(super) fn reserve(&mut self, additional: usize) {
unsafe {
(*self.storage.get()).reserve(additional);
}
}
fn as_ptr(&self) -> *mut Vec<T> {
self.storage.get()
}
}
pub(super) struct TempVector<T> {
storage: *mut Vec<T>,
offset: usize,
size: usize,
_marker: PhantomData<*mut Vec<T>>,
}
impl<T> TempVector<T> {
pub(super) fn new(storage: &ScratchVec<T>) -> Self {
let storage = storage.as_ptr();
Self {
storage,
offset: unsafe { (*storage).len() },
size: 0,
_marker: PhantomData,
}
}
pub(super) fn nested(&mut self) -> Self {
let storage = self.storage;
let offset = self.storage().len();
Self {
storage,
offset,
size: 0,
_marker: PhantomData,
}
}
pub(super) fn push_back(&mut self, item: T) {
debug_assert!(self.storage().len() == self.offset + self.size);
self.storage_mut().push(item);
self.size += 1;
}
pub(super) fn len(&self) -> usize {
self.size
}
pub(super) fn as_slice(&self) -> &[T] {
let storage = self.storage();
&storage[self.offset..self.offset + self.size]
}
pub(super) fn as_mut_slice(&mut self) -> &mut [T] {
let offset = self.offset;
let size = self.size;
&mut self.storage_mut()[offset..offset + size]
}
pub(super) fn iter(&self) -> slice::Iter<'_, T> {
self.as_slice().iter()
}
fn storage(&self) -> &Vec<T> {
unsafe { &*self.storage }
}
fn storage_mut(&mut self) -> &mut Vec<T> {
unsafe { &mut *self.storage }
}
}
impl<T> Drop for TempVector<T> {
fn drop(&mut self) {
let offset = self.offset;
let size = self.size;
let storage = self.storage_mut();
debug_assert!(storage.len() == offset + size);
storage.truncate(offset);
}
}
impl<T> Index<usize> for TempVector<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
&self.as_slice()[index]
}
}