From 655e896fb57ede428f889c6c7598f8954784e0dd Mon Sep 17 00:00:00 2001 From: Micha White Date: Thu, 21 Dec 2023 19:31:09 -0500 Subject: Remove some memory allocations --- engine/src/stackvec.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 engine/src/stackvec.rs (limited to 'engine/src/stackvec.rs') diff --git a/engine/src/stackvec.rs b/engine/src/stackvec.rs new file mode 100644 index 0000000..9c00461 --- /dev/null +++ b/engine/src/stackvec.rs @@ -0,0 +1,99 @@ +use std::mem::MaybeUninit; +use std::ops::{Deref, DerefMut}; + +pub struct StackVec { + values: [MaybeUninit; CAPACITY], + len: usize, +} + +impl Deref for StackVec { + type Target = [T]; + + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl DerefMut for StackVec { + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_mut_slice() + } +} + +impl FromIterator for StackVec { + fn from_iter>(iter: I) -> Self { + let mut this = Self::new(); + for item in iter { + this.push(item); + } + + this + } +} + +impl StackVec { + pub fn new() -> Self { + Self { + values: MaybeUninit::uninit_array(), + len: 0, + } + } + + pub fn capcity(&self) -> usize { + CAPACITY + } + + pub fn len(&self) -> usize { + self.len + } + + pub fn is_empty(&self) -> bool { + self.len == 0 + } + + pub fn as_slice(&self) -> &[T] { + // safety: the first `len` elements are guaranteed to be initialized + unsafe { MaybeUninit::slice_assume_init_ref(&self.values[..self.len]) } + } + + pub fn as_mut_slice(&mut self) -> &mut [T] { + // safety: the first `len` elements are guaranteed to be initialized + unsafe { MaybeUninit::slice_assume_init_mut(&mut self.values[..self.len]) } + } + + pub fn as_ptr(&self) -> *const T { + self.values.as_ptr().cast() + } + + pub fn as_mut_ptr(&mut self) -> *mut T { + self.values.as_mut_ptr().cast() + } + + pub fn try_push(&mut self, value: T) -> Option<()> { + self.values.get_mut(self.len)?.write(value); + self.len += 1; + Some(()) + } + + pub fn push(&mut self, value: T) { + self.values[self.len].write(value); + self.len += 1; + } + + pub fn pop(&mut self) -> Option { + if self.is_empty() { + return None; + } + + // safety: this value will no longer be used, and the value is valid + // because it appears in the valid part of the array + unsafe { + self.len -= 1; + Some(std::ptr::read(self.as_ptr().add(self.len()))) + } + } + + pub fn clear(&mut self) { + self.len = 0; + } +} -- cgit v1.2.3