hibana 0.9.6

Choreography-derived runtime enforcement kernel for no_std Rust multiparty protocols
Documentation
use super::{
    CursorEndpoint, FrontierScratchWorkspace, FrontierVisitSet, OfferEntryKey, RecvError,
    RecvResult, Transport,
};

mod candidates;
mod model;
use self::model::{
    CurrentOfferAuthority, CurrentOfferEntry, CurrentOfferObservation,
    OfferAlignmentCandidateInput, OfferAlignmentDecision, ProgressSiblingPresence,
};

impl<'r, const ROLE: u8, T> CursorEndpoint<'r, ROLE, T>
where
    T: Transport + 'r,
{
    pub(in crate::endpoint::kernel) fn align_cursor_to_selected_scope(
        &mut self,
        visited: &mut FrontierVisitSet,
        scratch: &mut FrontierScratchWorkspace<'_>,
    ) -> RecvResult<crate::global::const_dsl::ScopeId> {
        loop {
            let node_scope = self.cursor.node_scope_id();
            if node_scope.is_none()
                && let Some(entry_idx) = self.cursor.first_pending_step_index()
                && entry_idx != self.cursor.index()
            {
                self.commit_offer_alignment_realign(entry_idx, visited)?;
                continue;
            }
            let current_scope = self.current_offer_scope_id();
            if current_scope != node_scope
                && let Some(entry_idx) = self.route_scope_offer_entry_index(current_scope)
                && entry_idx != self.cursor.index()
            {
                self.commit_offer_alignment_realign(entry_idx, visited)?;
                continue;
            }
            let node_scope = current_scope;
            let current_idx = self.cursor.index();
            let mut current_frontier_state =
                self.current_frontier_selection_state(node_scope, current_idx);
            let current_frontier = current_frontier_state.frontier;
            let current_parallel = current_frontier_state.parallel();
            let current_scope_meta =
                self.current_scope_selection_meta(node_scope, current_idx, current_frontier_state);
            let current_scope_selected = self.selected_arm_for_scope(node_scope).is_some();
            if current_scope_selected
                && current_scope_meta.is_some_and(|meta| meta.is_route_entry())
            {
                return Ok(node_scope);
            }
            let active_entries =
                self.active_frontier_entries(current_parallel, &mut scratch.global_active_entries);
            let current_key = OfferEntryKey::from_index(node_scope, current_idx);
            if current_key.is_some_and(|key| active_entries.contains_only(key)) {
                let Some(meta) = current_scope_meta else {
                    return Ok(node_scope);
                };
                if meta.is_route_entry() && meta.has_offer_lanes() {
                    return Ok(node_scope);
                }
            }
            let (observed_entries, exact_current_observation) = self
                .compose_frontier_observed_entries(
                    active_entries,
                    current_key,
                    &mut scratch.observed_entries,
                );
            let reentry_ready_entry_idx =
                observed_entries.first_selectable_ready_entry_except(current_idx);
            let reentry_controller_evidence = current_frontier_state.reentry_controller_evidence();
            let progress_sibling_presence = ProgressSiblingPresence::from_observed_progress_sibling(
                self.observed_frontier_progress_sibling_exists(
                    observed_entries,
                    current_idx,
                    current_frontier,
                    reentry_controller_evidence,
                ),
            );
            let Some(current_scope_meta) = current_scope_meta else {
                return Ok(node_scope);
            };
            let current_entry = if current_scope_meta.is_route_entry() {
                if current_scope_meta.has_offer_lanes() {
                    CurrentOfferEntry::RouteWithOfferLanes
                } else {
                    CurrentOfferEntry::RouteWithoutOfferLanes
                }
            } else {
                CurrentOfferEntry::NonRoute
            };
            let current_authority = if current_scope_meta.is_controller() {
                CurrentOfferAuthority::Controller
            } else {
                CurrentOfferAuthority::Passive
            };
            let candidates = self.offer_alignment_candidates(
                observed_entries,
                OfferAlignmentCandidateInput {
                    current_idx,
                    current_entry,
                    current_authority,
                    progress_sibling_presence,
                    current_observation: CurrentOfferObservation::from_exact(
                        exact_current_observation,
                    ),
                },
            );
            current_frontier_state = candidates.merge_current_observation(current_frontier_state);
            let selection = candidates.select(current_frontier_state);
            let current_entry = candidates.current_entry();
            match selection {
                Some(OfferAlignmentDecision::KeepCurrent) => return Ok(node_scope),
                Some(OfferAlignmentDecision::Realign(entry_idx)) => {
                    self.commit_offer_alignment_realign(entry_idx, visited)?;
                    continue;
                }
                None => {}
            }
            if self.current_route_arm_authorized()? {
                return Ok(node_scope);
            }
            if candidates.current_can_remain_after_alignment(current_frontier_state) {
                return Ok(node_scope);
            }
            if !current_entry.is_route_entry()
                && let Some(entry_idx) = reentry_ready_entry_idx
            {
                self.commit_offer_alignment_realign(entry_idx, visited)?;
                continue;
            }
            return Err(RecvError::PhaseInvariant);
        }
    }

    fn commit_offer_alignment_realign(
        &mut self,
        entry_idx: usize,
        visited: &mut FrontierVisitSet,
    ) -> RecvResult<()> {
        let current_idx = self.cursor.index();
        if entry_idx == current_idx || visited.contains(current_idx) {
            return Err(RecvError::PhaseInvariant);
        }
        visited.record(current_idx);
        self.commit_cursor_realign_index(entry_idx)
            .map_err(|_| RecvError::PhaseInvariant)?;
        self.sync_lane_offer_state();
        Ok(())
    }
}