hibana 0.9.4

Session-typed choreographic programming for no_std Rust protocols, inspired by affine MPST
Documentation
use super::{
    CommitEventRow, CursorEndpoint, PreparedRouteCommitRows, RelocatableResidentLaneStep,
    SelectedRouteCommitRow, Transport, commit_delta::CommitDeltaApplyPermit,
    commit_delta::CommittedCommitDelta, commit_delta::PreparedCommitDelta, state_index_to_usize,
};
use crate::global::const_dsl::{ReentryMark, ScopeId};

impl<'r, const ROLE: u8, T> CursorEndpoint<'r, ROLE, T>
where
    T: Transport + 'r,
{
    pub(in crate::endpoint::kernel) fn commit_prepared_delta(
        &mut self,
        mut delta: PreparedCommitDelta,
    ) -> CommittedCommitDelta {
        let applies_route_completion =
            delta.event().is_some() || delta.selected_routes().len() != 0;
        let body_reentry_scope = self.prepared_body_reentry_scope(delta.event());
        if let Some(scope) = body_reentry_scope {
            self.clear_reentry_scope_state(scope);
        }
        let route_lane = delta.selected_route_lane();
        let mut idx = 0usize;
        while idx < delta.selected_routes().len() {
            let Some(row) = delta.selected_routes().get(&self.cursor, idx) else {
                crate::invariant();
            };
            let Some(lane) = route_lane else {
                crate::invariant();
            };
            self.apply_prepared_selected_route_commit_row(row, lane);
            idx += 1;
        }
        self.apply_prepared_cursor_index(state_index_to_usize(delta.cursor_after()));
        if let Some(event) = delta.event() {
            self.apply_prepared_lane_advance(event.progress_step());
        }
        if let Some(step) = delta.lane_relocation() {
            self.apply_prepared_lane_relocation(step);
        }
        if applies_route_completion {
            self.apply_prepared_route_completion_cursor(delta.selected_routes());
        }
        CommittedCommitDelta::from_applied(delta.event(), delta.take_selected_routes())
    }

    #[inline]
    fn prepared_body_reentry_scope(&self, event: Option<CommitEventRow>) -> Option<ScopeId> {
        let event = event?;
        let mut selected_arm_for_scope = |scope| self.selected_arm_for_scope(scope);
        self.cursor
            .roll_body_reentry_scope_for_step(event.progress_step(), &mut selected_arm_for_scope)
    }

    fn clear_reentry_scope_state(&mut self, scope: ScopeId) {
        self.cursor.clear_reentry_scope_events(scope);
        let lane_limit = self.cursor.logical_lane_count();
        let mut lane_idx = 0usize;
        while lane_idx < lane_limit {
            if self.decision_state.lane_route_arm_len(lane_idx) != 0 {
                {
                    let cursor = &self.cursor;
                    self.decision_state.clear_lane_route_selections_in_scope(
                        lane_idx,
                        |candidate| cursor.route_scope_contained_in_roll_scope(candidate, scope),
                        |candidate| cursor.route_scope_slot(candidate),
                        |candidate| cursor.route_scope_reentry(candidate),
                        CommitDeltaApplyPermit::new(),
                    );
                }
                self.refresh_lane_offer_state(lane_idx);
            }
            lane_idx += 1;
        }
    }

    #[inline(always)]
    fn apply_prepared_cursor_index(&mut self, idx: usize) {
        self.cursor.set_index(idx);
    }

    #[inline(always)]
    fn apply_prepared_lane_advance(&mut self, target: RelocatableResidentLaneStep) {
        let refresh = self.cursor.advance_lane_to_relocatable_step(target);
        self.refresh_after_cursor_move(refresh);
    }

    #[inline(always)]
    fn apply_prepared_lane_relocation(&mut self, target: RelocatableResidentLaneStep) {
        let refresh = self.cursor.set_lane_cursor_to_relocatable_step(target);
        self.refresh_after_cursor_move(refresh);
    }

    #[inline(always)]
    fn selected_arm_from_prepared_rows(
        rows: &PreparedRouteCommitRows,
        cursor: &super::EventCursor,
        scope: ScopeId,
    ) -> Option<u8> {
        let mut idx = 0usize;
        while idx < rows.len() {
            let row = rows.get(cursor, idx)?;
            if row.scope() == scope {
                return Some(row.selected_arm());
            }
            idx += 1;
        }
        None
    }

    #[inline(always)]
    fn apply_prepared_route_completion_cursor(&mut self, rows: &PreparedRouteCommitRows) {
        let idx = self.cursor.index();
        if self.cursor.enclosing_route_scope_rows_at(idx).is_none() {
            return;
        }
        let cursor = &self.cursor;
        let decision_state = &self.decision_state;
        let Some(end) = cursor.selected_enclosing_route_scope_end_at(idx, |scope| {
            Self::selected_arm_from_prepared_rows(rows, cursor, scope).or_else(|| {
                let scope_slot = cursor.route_scope_slot(scope)?;
                decision_state.selected_arm_for_scope_slot(scope_slot)
            })
        }) else {
            return;
        };
        if end != idx && self.cursor.contains_node_index(end) {
            self.cursor.set_index(end);
        }
    }

    fn apply_prepared_selected_route_commit_row(&mut self, row: SelectedRouteCommitRow, lane: u8) {
        let lane_idx = lane as usize;
        let scope = row.scope();
        let Some(scope_slot) = self.cursor.route_scope_slot(scope) else {
            crate::invariant();
        };
        let reentry = if self.cursor.route_scope_reentry(scope) {
            ReentryMark::Reentrant
        } else {
            ReentryMark::SinglePass
        };
        let completed_iteration_arm = if reentry.is_reentrant() {
            self.selected_arm_for_scope(scope)
                .filter(|&arm| self.reentrant_selected_arm_complete(scope, arm))
        } else {
            None
        };
        if let Some(completed_arm) = completed_iteration_arm {
            let cursor = &self.cursor;
            let lane_limit = cursor.logical_lane_count();
            let mut clear_lane = 0usize;
            while clear_lane < lane_limit {
                if self.decision_state.lane_route_arm_len(clear_lane) != 0 {
                    self.decision_state.replace_route_selection_arm_for_scope(
                        clear_lane,
                        scope,
                        completed_arm,
                        row.selected_arm(),
                    );
                    self.decision_state.clear_lane_route_selections_in_scope(
                        clear_lane,
                        |candidate| {
                            cursor.route_scope_conflict_arm_for_scope(candidate, scope)
                                == Some(completed_arm)
                        },
                        |candidate| cursor.route_scope_slot(candidate),
                        |candidate| cursor.route_scope_reentry(candidate),
                        CommitDeltaApplyPermit::new(),
                    );
                }
                clear_lane += 1;
            }
            self.decision_state.replace_selected_arm_slot(
                scope_slot,
                completed_arm,
                row.selected_arm(),
            );
            self.cursor.clear_reentry_scope_events(scope);
        }
        self.decision_state.apply_prepared_route_selection(
            lane_idx,
            scope_slot,
            reentry,
            row,
            CommitDeltaApplyPermit::new(),
        );
        self.refresh_lane_offer_state(lane_idx);
    }
}