add: Fast Stack

This is an implementation of a stack that does minimal bookeeping, has zero heap allocations, and is guaranteed to not panic
This commit is contained in:
Jordan Pittman 2024-10-12 19:15:13 -04:00
parent 045887cd62
commit 191bc824c2
3 changed files with 79 additions and 0 deletions

View file

@ -0,0 +1,60 @@
use super::gurantee;
pub struct FastStack {
storage: [u8; 256],
pos: usize
}
impl FastStack {
#[inline(always)]
pub fn new() -> FastStack {
FastStack {
storage: [0; 256],
pos: 0
}
}
#[inline(always)]
pub fn push(&mut self, value: u8) {
gurantee(!self.overgrown());
self.storage[self.pos] = value;
self.pos += 1;
}
#[inline(always)]
pub fn peek(&self) -> u8 {
gurantee(!self.overgrown());
return self.storage[self.pos - 1];
}
#[inline(always)]
pub fn last(&self) -> Option<u8> {
if self.is_empty() || self.overgrown() {
return None;
}
return Some(self.peek());
}
#[inline(always)]
pub fn pop(&mut self) {
// SAFETY: The buffer does not need to be mutated because the stack is
// only ever read from or written to its current position. Its current
// position is only ever incremented after writing to it. Meaning that
// the buffer can be dirty for the next use and still be correct since
// reading/writing always starts at position `0`.
self.pos = self.pos.saturating_sub(1);
}
#[inline(always)]
pub fn is_empty(&self) -> bool {
return self.pos == 0;
}
#[inline(always)]
pub fn overgrown(&self) -> bool {
self.pos > 256
}
}

View file

@ -0,0 +1,11 @@
#[inline(always)]
pub const fn gurantee(expr: bool) {
#[cfg(debug_assertions)]
if !expr {
panic!("gurantee failed")
}
unsafe {
std::hint::assert_unchecked(expr)
}
}

View file

@ -0,0 +1,8 @@
mod fast_stack;
mod gurantee;
#[allow(unused_imports)]
pub use crate::util::fast_stack::*;
#[allow(unused_imports)]
pub use crate::util::gurantee::*;