hibana 0.9.6

Choreography-derived runtime enforcement kernel for no_std Rust multiparty protocols
Documentation
use super::{
    EndpointLeaseId, EndpointLeaseSlot, EndpointLeaseState, EndpointResidentBudget, Rendezvous,
    Transport,
};
use crate::{session::cluster::error::ResourceScope, session::types::SessionId};
mod placement;
mod session_binding;
#[cfg(kani)]
pub(in crate::rendezvous::core) use placement::endpoint_offset_in_gap;

impl<'rv, 'cfg, T: Transport> Rendezvous<'rv, 'cfg, T>
where
    'cfg: 'rv,
{
    #[inline]
    pub(crate) fn allocate_endpoint_lease(
        &self,
        sid: SessionId,
        role: u8,
        bytes: usize,
        align: usize,
        resident_budget: EndpointResidentBudget,
    ) -> Result<(EndpointLeaseId, u32, usize, usize), ResourceScope> {
        if bytes > u32::MAX as usize || self.endpoint_lease_generation.get() == u32::MAX {
            return Err(ResourceScope::EndpointLease);
        }
        let slot_count = self.endpoint_lease_slot_count();
        let mut slot_idx = 0usize;
        while slot_idx < slot_count {
            let slot = crate::invariant_some(self.endpoint_lease_slot_by_index(slot_idx));
            if !slot.is_occupied() {
                self.require_empty_endpoint_waiter_slot(slot_idx);
                break;
            }
            slot_idx += 1;
        }
        let required_slots = if slot_idx == slot_count {
            slot_count
                .checked_add(1)
                .ok_or(ResourceScope::EndpointLease)?
        } else {
            slot_count
        };
        let capacity_plan = self.plan_endpoint_lease_capacity(required_slots)?;
        let endpoint_floor = self.endpoint_lease_floor_after_capacity_plan(&capacity_plan)?;
        let (slab_ptr, slab_len) = self.slab_ptr_and_len();
        let slab_base = slab_ptr as usize;
        let slab_end = crate::invariant_some(slab_base.checked_add(slab_len));
        let lease_storage = self.endpoint_lease_storage.get();
        if !lease_storage.is_empty() {
            let lease_base = lease_storage.ptr() as usize;
            let lease_end = crate::invariant_some(lease_base.checked_add(lease_storage.bytes()));
            if lease_base < slab_base || lease_end > slab_end {
                crate::invariant();
            }
        }
        let offset = self.plan_endpoint_lease_offset(bytes, align, endpoint_floor)?;
        let lease_len = u32::try_from(bytes).map_err(|_| ResourceScope::EndpointLease)?;
        let lease_offset = u32::try_from(offset).map_err(|_| ResourceScope::EndpointLease)?;
        let lease_id =
            EndpointLeaseId::try_from(slot_idx).map_err(|_| ResourceScope::EndpointLease)?;

        self.commit_endpoint_lease_capacity(capacity_plan);
        let slot = crate::invariant_some(self.endpoint_lease_slot_by_index(slot_idx));
        if slot.is_occupied() {
            crate::invariant();
        }
        self.require_empty_endpoint_waiter_slot(slot_idx);
        let generation = crate::invariant_some(self.next_endpoint_lease_generation());
        self.write_endpoint_lease_slot(
            slot_idx,
            EndpointLeaseSlot {
                generation,
                sid,
                role,
                offset: lease_offset,
                len: lease_len,
                resident_budget,
                state: EndpointLeaseState::Reserved,
            },
        );
        Ok((lease_id, generation, offset, bytes))
    }
    #[inline]
    pub(crate) fn has_endpoint_session_role(&self, sid: SessionId, role: u8) -> bool {
        let slot_count = self.endpoint_lease_slot_count();
        let mut idx = 0usize;
        while idx < slot_count {
            let slot = crate::invariant_some(self.endpoint_lease_slot_by_index(idx));
            if slot.is_occupied() && slot.sid == sid && slot.role == role {
                return true;
            }
            idx += 1;
        }
        false
    }

    #[inline]
    pub(crate) fn publish_endpoint_lease(&self, lease_slot: EndpointLeaseId, generation: u32) {
        let idx = usize::from(lease_slot);
        let slot = crate::invariant_some(self.endpoint_lease_slot_by_index(idx));
        if slot.generation != generation || slot.state != EndpointLeaseState::Reserved {
            crate::invariant();
        }
        self.write_endpoint_lease_slot(
            idx,
            EndpointLeaseSlot {
                state: EndpointLeaseState::Published,
                ..slot
            },
        );
    }

    #[inline]
    pub(crate) fn release_endpoint_lease(&self, lease_slot: EndpointLeaseId, generation: u32) {
        let idx = usize::from(lease_slot);
        let slot_count = self.endpoint_lease_slot_count();
        if idx >= slot_count {
            crate::invariant();
        }
        let slot = crate::invariant_some(self.endpoint_lease_slot_by_index(idx));
        if !slot.is_occupied() || slot.generation != generation {
            crate::invariant();
        }
        self.require_empty_endpoint_waiter_slot(idx);
        self.write_endpoint_lease_slot(
            idx,
            EndpointLeaseSlot {
                generation: slot.generation,
                ..EndpointLeaseSlot::EMPTY
            },
        );
        self.shrink_assoc_table_capacity(self.active_lane_attachment_count());
        self.shrink_lane_range(self.assoc.active_lane_slots());
        self.shrink_endpoint_lease_capacity();
        self.recompute_frontier_workspace_bytes();
    }

    #[inline]
    pub(crate) fn abort_endpoint_lease_reservation(
        &self,
        lease_slot: EndpointLeaseId,
        generation: u32,
    ) {
        let slot =
            crate::invariant_some(self.endpoint_lease_slot_by_index(usize::from(lease_slot)));
        if slot.state != EndpointLeaseState::Reserved
            || slot.generation != generation
            || self.endpoint_lease_generation.get() != generation
        {
            crate::invariant();
        }
        let previous_generation = crate::invariant_some(generation.checked_sub(1));
        self.release_endpoint_lease(lease_slot, generation);
        self.endpoint_lease_generation.set(previous_generation);
    }
}