hibana 0.9.3

Session-typed choreographic programming for no_std Rust protocols, inspired by affine MPST
Documentation
use super::{CursorEndpoint, RecvError, RecvResult, Transport};

mod candidates;
mod model;
use self::model::{
    CurrentOfferAuthority, CurrentOfferEntry, OfferAlignmentCandidateInput, 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,
    ) -> RecvResult<crate::global::const_dsl::ScopeId> {
        let node_scope = self.cursor.node_scope_id();
        if node_scope.is_none()
            && let Some(entry_idx) = self.cursor.first_pending_step_index(usize::MAX)
            && entry_idx != self.cursor.index()
        {
            self.commit_cursor_realign_index(entry_idx)
                .map_err(|_| RecvError::PhaseInvariant)?;
            self.sync_lane_offer_state();
            return self.align_cursor_to_selected_scope();
        }
        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_cursor_realign_index(entry_idx)
                .map_err(|_| RecvError::PhaseInvariant)?;
            self.sync_lane_offer_state();
            return self.align_cursor_to_selected_scope();
        }
        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);
        if active_entries.contains_only(current_idx) {
            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 = self.compose_frontier_observed_entries(active_entries);
        let reentry_ready_entry_idx =
            self.observed_ready_reentry_entry_idx(observed_entries, 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_frontier_state = candidates.merge_current_observation(current_frontier_state);
        let selection = candidates.select(current_frontier_state);
        let current_entry = candidates.current_entry();
        if let Some((_priority, entry_idx)) = selection {
            if entry_idx != self.cursor.index() {
                self.commit_cursor_realign_index(entry_idx)
                    .map_err(|_| RecvError::PhaseInvariant)?;
                self.sync_lane_offer_state();
                return self.align_cursor_to_selected_scope();
            }
            return Ok(node_scope);
        }
        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
        {
            if entry_idx != self.cursor.index() {
                self.commit_cursor_realign_index(entry_idx)
                    .map_err(|_| RecvError::PhaseInvariant)?;
                self.sync_lane_offer_state();
                return self.align_cursor_to_selected_scope();
            }
            return Ok(node_scope);
        }
        Err(RecvError::PhaseInvariant)
    }
}