hibana 0.9.6

Choreography-derived runtime enforcement kernel for no_std Rust multiparty protocols
Documentation
use super::super::frontier::{
    ActiveEntrySlot, FrontierKind, FrontierObservationSlot, FrontierScratchSectionLease,
    frontier_global_active_entries_view, frontier_observed_entries_view,
};
use super::{ActiveEntrySet, CursorEndpoint, ObservedEntrySet, ObservedEntrySetBuilder, Transport};
use crate::endpoint::kernel::offer::CurrentReentryControllerEvidence;

#[inline]
fn is_selectable_progress_sibling(
    slot: crate::endpoint::kernel::frontier::FrontierObservationSlot,
    entry_idx: Option<usize>,
    current_entry_idx: usize,
    current_frontier: FrontierKind,
    reentry_controller_evidence: CurrentReentryControllerEvidence,
) -> bool {
    entry_idx != Some(current_entry_idx)
        && slot.is_selectable()
        && slot.has_progress()
        && (reentry_controller_evidence.allows_cross_frontier_progress_sibling()
            || slot.is_in_frontier(current_frontier))
}

impl<'r, const ROLE: u8, T> CursorEndpoint<'r, ROLE, T>
where
    T: Transport + 'r,
{
    #[inline]
    pub(in crate::endpoint::kernel) fn global_active_entries<'a>(
        &self,
        scratch: &'a mut FrontierScratchSectionLease<'_, ActiveEntrySlot>,
    ) -> ActiveEntrySet<'a> {
        let mut active_entries = frontier_global_active_entries_view(scratch);
        active_entries.clear();
        let active_offer_lanes = self.decision_state.active_offer_lanes();
        let lane_limit = self.cursor.logical_lane_count();
        let mut next = active_offer_lanes.first_set(lane_limit);
        while let Some(lane_idx) = next {
            let info = self.decision_state.lane_offer_state(lane_idx);
            if info.entry.is_absent() || info.scope.is_none() {
                crate::invariant();
            }
            let key = crate::invariant_some(info.key());
            active_entries.insert_key(key, lane_idx as u8);
            next = active_offer_lanes.next_set_from(lane_idx + 1, lane_limit);
        }
        active_entries.seal()
    }

    #[inline]
    pub(in crate::endpoint::kernel) fn empty_observed_entries_scratch<'a>(
        &self,
        scratch: &'a mut FrontierScratchSectionLease<'_, FrontierObservationSlot>,
    ) -> ObservedEntrySetBuilder<'a> {
        let mut observed = frontier_observed_entries_view(scratch);
        observed.clear();
        observed
    }

    #[inline]
    pub(in crate::endpoint::kernel) fn observed_frontier_progress_sibling_exists(
        &self,
        observed_entries: ObservedEntrySet<'_>,
        current_entry_idx: usize,
        current_frontier: FrontierKind,
        reentry_controller_evidence: CurrentReentryControllerEvidence,
    ) -> bool {
        let mut slot_idx = 0usize;
        while slot_idx < observed_entries.len() {
            let Some(slot) = observed_entries.slot(slot_idx) else {
                crate::invariant();
            };
            if is_selectable_progress_sibling(
                slot,
                observed_entries.entry_idx(slot_idx),
                current_entry_idx,
                current_frontier,
                reentry_controller_evidence,
            ) {
                return true;
            }
            slot_idx += 1;
        }
        false
    }
}

#[cfg(any(kani, all(test, hibana_repo_tests)))]
mod tests {
    use super::*;
    use crate::endpoint::kernel::frontier::{
        FrontierObservationSlot, OfferEntryAdmission, OfferEntryKey, OfferEntryObservedState,
    };
    use crate::global::{const_dsl::ScopeId, typestate::StateIndex};

    fn excluded_progress() -> FrontierObservationSlot {
        FrontierObservationSlot::from_exact_observation(
            OfferEntryObservedState {
                key: OfferEntryKey::new(ScopeId::route(1), StateIndex::new(7))
                    .expect("exact route key"),
                frontier_mask: FrontierKind::Reentry.bit(),
                flags: OfferEntryObservedState::FLAG_PROGRESS,
            },
            OfferEntryAdmission::Excluded,
        )
    }

    #[cfg(all(test, hibana_repo_tests))]
    #[test]
    fn excluded_scope_cannot_supply_progress_sibling_authority() {
        assert!(!is_selectable_progress_sibling(
            excluded_progress(),
            Some(7),
            9,
            FrontierKind::Reentry,
            CurrentReentryControllerEvidence::ProgressEvidenceAbsent,
        ));
    }

    #[cfg(kani)]
    #[kani::proof]
    fn excluded_scope_never_supplies_progress_sibling_authority() {
        let current_entry: usize = kani::any();
        let observed_entry: usize = kani::any();
        let frontier = if kani::any() {
            FrontierKind::Route
        } else {
            FrontierKind::Reentry
        };
        let controller_evidence = if kani::any() {
            CurrentReentryControllerEvidence::ProgressSatisfiedOrNotController
        } else {
            CurrentReentryControllerEvidence::ProgressEvidenceAbsent
        };
        assert!(!is_selectable_progress_sibling(
            excluded_progress(),
            Some(observed_entry),
            current_entry,
            frontier,
            controller_evidence,
        ));
    }
}