hibana 0.9.2

Session-typed choreographic programming for no_std Rust protocols, inspired by affine MPST
Documentation
use core::marker::PhantomData;

use super::{AssocTable, EndpointLeaseId, EndpointLeaseSlot, Rendezvous, RouteTable, Transport};
mod capacity;

// # Unsafe Owner Contract
//
// This file owns rendezvous slab layout, sidecar allocation, migration, and
// resident table ingress. The slab pointer and endpoint-lease table are created
// by the rendezvous constructor and remain pinned for the rendezvous lifetime.
// Every raw allocation returned here is aligned, range-checked against the
// current slab frontier, and recorded by advancing the rendezvous image frontier
// before typed owners bind to it. Migration paths copy initialized table entries
// into freshly allocated sidecar storage before rebinding.

pub(crate) struct Sidecar<T> {
    ptr: *mut T,
    bytes: usize,
    _marker: PhantomData<T>,
}

impl<T> Clone for Sidecar<T> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }
}

impl<T> Copy for Sidecar<T> {}

impl<T> Sidecar<T> {
    pub(crate) const EMPTY: Self = Self {
        ptr: core::ptr::null_mut(),
        bytes: 0,
        _marker: PhantomData,
    };

    #[inline]
    pub(crate) const fn from_raw_parts(ptr: *mut T, bytes: usize) -> Self {
        Self {
            ptr,
            bytes,
            _marker: PhantomData,
        }
    }

    #[inline]
    pub(crate) const fn ptr(self) -> *mut T {
        self.ptr
    }

    #[inline]
    pub(crate) const fn bytes(self) -> usize {
        self.bytes
    }

    #[inline]
    pub(crate) fn is_empty(self) -> bool {
        self.ptr.is_null() || self.bytes == 0
    }

    #[inline]
    pub(crate) const fn cast<U>(self) -> Sidecar<U> {
        Sidecar {
            ptr: self.ptr.cast::<U>(),
            bytes: self.bytes,
            _marker: PhantomData,
        }
    }
}

impl<'rv, 'cfg, T: Transport> Rendezvous<'rv, 'cfg, T>
where
    'cfg: 'rv,
{
    #[inline(always)]
    pub(crate) const fn align_up(value: usize, align: usize) -> usize {
        if align == 0 {
            crate::invariant();
        }
        let mask = align - 1;
        if value > usize::MAX - mask {
            crate::invariant();
        }
        (value + mask) & !mask
    }

    #[inline(always)]
    pub(crate) const fn align_down(value: usize, align: usize) -> usize {
        if align == 0 {
            crate::invariant();
        }
        let mask = align - 1;
        value & !mask
    }

    #[inline(always)]
    pub(crate) const fn frontier_workspace_guard_bytes(
        layout: crate::endpoint::kernel::FrontierScratchLayout,
    ) -> usize {
        let align = layout.total_align();
        if align == 0 {
            crate::invariant();
        }
        let pad = align - 1;
        if layout.total_bytes() > usize::MAX - pad {
            crate::invariant();
        }
        layout.total_bytes() + pad
    }

    #[inline]
    pub(crate) fn slab_ptr_and_len(&self) -> (*mut u8, usize) {
        /* SAFETY: `Rendezvous` owns the installed resident slab pointer; this
        returns base/len without a slice borrow aliasing endpoint leases. */
        unsafe {
            let slab = &mut *self.slab;
            (slab.as_mut_ptr(), slab.len())
        }
    }

    #[inline]
    pub(crate) fn endpoint_storage_floor(&self) -> usize {
        let (_, slab_len) = self.slab_ptr_and_len();
        let mut floor = slab_len;
        let mut idx = 0usize;
        while idx < usize::from(self.endpoint_lease_capacity) {
            let slot = crate::invariant_some(self.endpoint_lease_slot_by_index(idx));
            if slot.is_live() && slot.len != 0 && (slot.offset as usize) < floor {
                floor = slot.offset as usize;
            }
            idx += 1;
        }
        floor
    }

    #[inline]
    pub(crate) fn endpoint_lease_floor(&self) -> usize {
        crate::invariant_some(
            (self.image_frontier as usize).checked_add(self.frontier_workspace_bytes as usize),
        )
    }

    #[inline]
    pub(crate) fn endpoint_leases_ptr(&self) -> *mut EndpointLeaseSlot {
        self.endpoint_lease_storage.ptr()
    }

    #[inline]
    fn set_image_frontier(&mut self, frontier: u32) {
        self.image_frontier = frontier;
    }

    #[inline]
    fn set_frontier_workspace_bytes(&mut self, bytes: u32) {
        self.frontier_workspace_bytes = bytes;
    }
}