pub struct RawStack { /* private fields */ }Expand description
A simple raw stack that stores values as raw bytes. Each value is naturally aligned given the base alignment of the stack, which is the maximum alignment of any value stored in the stack. Live values are owned until popped, explicitly released, or destroyed in reverse push order.
Implementations§
Source§impl RawStack
impl RawStack
Sourcepub fn with_base_alignment(base_alignment: usize) -> RawStack
pub fn with_base_alignment(base_alignment: usize) -> RawStack
Creates a new RawStack with base alignment.
§Examples
use cel_runtime::raw_stack::RawStack;
let stack = RawStack::with_base_alignment(align_of::<u32>());Sourcepub fn push<T>(&mut self, value: T) -> boolwhere
T: 'static,
pub fn push<T>(&mut self, value: T) -> boolwhere
T: 'static,
Pushes a value of type T onto the stack.
The stack owns the value until it is popped using the correct type or destroyed.
T: 'static prevents owned destructors from retaining nonstatic borrows;
borrowed inputs must instead use explicitly borrowed adapters.
§Type Parameters
T: The type of the value to push.
§Examples
use cel_runtime::raw_stack::RawStack;
let mut stack = RawStack::with_base_alignment(align_of::<u32>());
let _ = stack.push(42u32);A value whose destructor borrows nonstatic data cannot enter this owning stack:
use cel_runtime::raw_stack::RawStack;
/// Borrows text that must remain live until destruction.
struct BorrowedDrop<'a>(&'a str);
impl Drop for BorrowedDrop<'_> {
/// Reads the borrowed text during destruction.
fn drop(&mut self) {
assert!(!self.0.is_empty());
}
}
let mut stack = RawStack::with_base_alignment(align_of::<BorrowedDrop<'static>>());
{
let text = String::from("borrowed");
stack.push(BorrowedDrop(&text));
}
drop(stack);§Complexity
The function has an amortized O(1) time complexity.
Sourcepub unsafe fn push_raw(
&mut self,
align: usize,
size: usize,
src: *const MaybeUninit<u8>,
) -> bool
pub unsafe fn push_raw( &mut self, align: usize, size: usize, src: *const MaybeUninit<u8>, ) -> bool
Pushes size raw bytes from src, aligned to align, using the same
padding/marker-byte bookkeeping as push.
src is typed as MaybeUninit<u8> rather than u8 because the bytes
being copied may include a source value’s interior padding, which is
itself uninitialized — reading it through a u8 pointer instead would
be undefined behavior even though this function never inspects the
bytes’ values.
- Precondition:
alignis a power of two. - Postcondition: A raw-byte slot is registered; its bytes are not destroyed
as a typed value unless upgraded with
own_top. - Complexity: Amortized O(size) time and space.
§Safety
src must be valid for reads of size bytes, and must not overlap the
stack’s internal buffer.
Sourcepub unsafe fn reserve_and_write(
&mut self,
align: usize,
size: usize,
write: impl FnOnce(*mut u8),
) -> bool
pub unsafe fn reserve_and_write( &mut self, align: usize, size: usize, write: impl FnOnce(*mut u8), ) -> bool
Reserves aligned space for size bytes (using the same padding/marker
bookkeeping as push) and calls write with a pointer
to that space instead of copying from a source buffer.
- Precondition:
alignis a power of two. - Postcondition:
writeis called exactly once, before this method returns, with a pointer tosizefreshly-reserved bytes. - Postcondition: Normal return registers a raw-byte slot; a panicking initializer registers no slot, leaving byte restoration to its caller.
- Complexity: Amortized O(size) plus initializer costs.
§Safety
write must fully initialize all size bytes at the pointer it’s
given before returning, except interior padding. If it panics, the caller
must guard partially initialized resources.
Sourcepub unsafe fn copy_from(
&self,
offset: usize,
size: usize,
dst: *mut MaybeUninit<u8>,
)
pub unsafe fn copy_from( &self, offset: usize, size: usize, dst: *mut MaybeUninit<u8>, )
Copies size bytes starting at absolute buffer offset offset into dst.
dst is typed as MaybeUninit<u8> rather than u8 because the bytes
being copied may be a value’s interior padding, which is itself
uninitialized — reading it through a u8 pointer instead would be
undefined behavior even though this function never inspects the
bytes’ values.
§Safety
offset..offset + size must be within the currently-initialized buffer;
dst must be valid for writes of size bytes and must not overlap the
stack’s internal buffer.
Sourcepub unsafe fn drop_at(&mut self, offset: usize, run_drop: impl FnOnce(*mut u8))
pub unsafe fn drop_at(&mut self, offset: usize, run_drop: impl FnOnce(*mut u8))
Drops a value in place at absolute buffer offset offset, without
altering the stack’s tracked length.
§Safety
offset must point to a live, valid value; run_drop must correctly
run that value’s destructor given a pointer to its start. Its ownership
entry must already have been removed with release_top.
Sourcepub unsafe fn read_at<R>(
&self,
offset: usize,
read: impl FnOnce(*const u8) -> R,
) -> R
pub unsafe fn read_at<R>( &self, offset: usize, read: impl FnOnce(*const u8) -> R, ) -> R
Reads a value at absolute buffer offset offset, given a callback that
receives a pointer to its bytes.
§Safety
offset must point to a live, valid, properly-aligned value for the type the
caller will reinterpret it as; read must not retain the pointer beyond the
call. This byte operation does not transfer ownership; a caller moving out
a value must explicitly release its ownership entry before destruction or
stack cleanup can occur.
Sourcepub unsafe fn truncate_to(&mut self, new_len: usize, padding: bool)
pub unsafe fn truncate_to(&mut self, new_len: usize, padding: bool)
Truncates the stack back to new_len, additionally stripping padding
bytes that preceded the removed region (scanned the same way
pop does).
§Safety
No live (undropped) value may exist at or above new_len; the caller must
explicitly release all removed ownership entries first. This byte operation
does not infer ownership transfer, including for zero-sized values.
Sourcepub unsafe fn drop_sized(
&mut self,
size: usize,
padding: bool,
run_drop: impl FnOnce(*mut u8),
)
pub unsafe fn drop_sized( &mut self, size: usize, padding: bool, run_drop: impl FnOnce(*mut u8), )
Removes the top owner’s bytes and metadata, then destroys its value in place.
§Safety
The top size bytes (plus padding if padding is true) must be a
live, valid value; run_drop must correctly run its destructor given a
pointer to its start. The value must have a registered top ownership entry.
Sourcepub unsafe fn repack(
&mut self,
ambient_start: usize,
dest_base: usize,
total_size: usize,
src_offsets: &[usize],
dest_offsets: &[usize],
sizes: &[usize],
) -> bool
pub unsafe fn repack( &mut self, ambient_start: usize, dest_base: usize, total_size: usize, src_offsets: &[usize], dest_offsets: &[usize], sizes: &[usize], ) -> bool
Repacks sizes.len() already-pushed values (currently at the absolute
byte offsets in src_offsets) into one contiguous, self-contained
region of total_size bytes starting at dest_base, placing element
i at dest_base + dest_offsets[i]. Adjusts the tracked length to
dest_base + total_size and returns whether leading padding was
inserted between ambient_start and dest_base.
-
Precondition:
src_offsets,dest_offsets, andsizeshave equal length;dest_base >= ambient_start; the source ranges are currently valid, initialized bytes. -
Complexity: O(n) in
sizes.len().
§Safety
The offsets and sizes must correctly describe the actual bytes in the
buffer; no two destination ranges may overlap. src_offsets and
dest_offsets must be in the same relative element order (element i’s
source and destination must both be the i-th non-overlapping range in
their respective layouts) — this method does not reorder elements, only
re-pads between them. Given that and dest_base >= ambient_start, each
element’s destination start is guaranteed to be at or after every
earlier element’s source end, which is what makes processing in reverse
index order below safe against clobbering not-yet-read source bytes.
The caller must release ownership entries for every moved value before
repacking, then register the resulting representation separately. This
byte operation never infers ownership transfer.
Sourcepub unsafe fn pop<T>(&mut self, padding: bool) -> T
pub unsafe fn pop<T>(&mut self, padding: bool) -> T
Pops a value of type T from the stack. Does not change the stack capacity.
§Safety
The type T must be the same type as the value on the top of the stack.
padding must match its push result, and the value must have a registered
ownership entry. Incorrect usage can lead to undefined behavior.
§Type Parameters
T: The type of the value to pop.
§Examples
use cel_runtime::raw_stack::RawStack;
let mut stack = RawStack::with_base_alignment(align_of::<u32>());
let padding = stack.push(100u32);
let value: u32 = unsafe { stack.pop(padding) };