hibana 0.8.0

Const-projected Affine Multiparty Session Types for choreography-first Rust protocols
Documentation
use super::{
    Clock, CursorEndpoint, EndpointSlot, EpochTable, FrontierObservationDomain,
    FrontierObservationKey, LabelUniverse, MintConfigMarker, ScopeId, Transport,
};
impl<'r, const ROLE: u8, T, U, C, E, const MAX_RV: usize, Mint, B>
    CursorEndpoint<'r, ROLE, T, U, C, E, MAX_RV, Mint, B>
where
    T: Transport + 'r,
    U: LabelUniverse,
    C: Clock,
    E: EpochTable,
    Mint: MintConfigMarker,
    B: EndpointSlot + 'r,
{
    pub(in crate::endpoint::kernel) fn refresh_frontier_observation_cache_for_scope(
        &mut self,
        scope_id: ScopeId,
    ) {
        let global_active_entries = self.global_active_entries();
        let mut active_entries = global_active_entries.occupancy_mask();
        let mut frontier_scratch = self.frontier_scratch_view();
        let roots = frontier_scratch.root_scopes_mut();
        roots.fill(ScopeId::none());
        let mut root_len = 0usize;
        let mut matches_scope = false;
        while let Some(slot_idx) =
            CursorEndpoint::<ROLE, T, U, C, E, MAX_RV, Mint, B>::next_slot_in_mask(
                &mut active_entries,
            )
        {
            let Some(entry_idx) = global_active_entries.entry_at(slot_idx) else {
                continue;
            };
            let Some(entry_state) = self.offer_entry_state_snapshot(entry_idx) else {
                continue;
            };
            if !self.offer_entry_has_active_lanes(entry_idx)
                || self.offer_entry_scope_id(entry_idx, entry_state) != scope_id
            {
                continue;
            }
            matches_scope = true;
            let Some(parallel_root) =
                self.offer_entry_parallel_root_from_state(entry_idx, entry_state)
            else {
                continue;
            };
            let mut seen_root = false;
            let mut idx = 0usize;
            while idx < root_len {
                if roots[idx] == parallel_root {
                    seen_root = true;
                    break;
                }
                idx += 1;
            }
            if !seen_root && root_len < roots.len() {
                roots[root_len] = parallel_root;
                root_len += 1;
            }
        }
        if !matches_scope {
            return;
        }
        self.refresh_cached_frontier_observation_scope_entries(
            FrontierObservationDomain::global(),
            scope_id,
        );
        let mut idx = 0usize;
        while idx < root_len {
            self.refresh_cached_frontier_observation_scope_entries(
                FrontierObservationDomain::root(roots[idx]),
                scope_id,
            );
            idx += 1;
        }
    }

    pub(in crate::endpoint::kernel) fn refresh_frontier_observation_cache_for_binding_lane(
        &mut self,
        lane_idx: usize,
        previous_nonempty: bool,
    ) {
        if lane_idx >= self.cursor.logical_lane_count() {
            return;
        }
        self.refresh_cached_frontier_observation_binding_lane_entries(
            FrontierObservationDomain::global(),
            lane_idx,
            previous_nonempty,
        );
        let mut slot_idx = 0usize;
        while slot_idx < self.frontier_state.root_frontier_len() {
            let root = self.frontier_state.root_frontier_state[slot_idx].root;
            if Self::frontier_observation_offer_lane_entry_slot_masks(
                self,
                FrontierObservationDomain::root(root),
            )[lane_idx]
                != 0
            {
                self.refresh_cached_frontier_observation_binding_lane_entries(
                    FrontierObservationDomain::root(root),
                    lane_idx,
                    previous_nonempty,
                );
            }
            slot_idx += 1;
        }
    }

    pub(in crate::endpoint::kernel) fn refresh_frontier_observation_cache_for_route_lane(
        &mut self,
        lane_idx: usize,
        previous_change_epoch: u16,
    ) {
        if lane_idx >= self.cursor.logical_lane_count() {
            return;
        }
        self.refresh_cached_frontier_observation_route_lane_entries(
            FrontierObservationDomain::global(),
            lane_idx,
            previous_change_epoch,
        );
        let mut slot_idx = 0usize;
        while slot_idx < self.frontier_state.root_frontier_len() {
            let root = self.frontier_state.root_frontier_state[slot_idx].root;
            self.refresh_cached_frontier_observation_route_lane_entries(
                FrontierObservationDomain::root(root),
                lane_idx,
                previous_change_epoch,
            );
            slot_idx += 1;
        }
    }

    pub(in crate::endpoint::kernel) fn cached_frontier_changed_entry_slot_mask(
        &mut self,
        domain: FrontierObservationDomain,
        observation_key: FrontierObservationKey,
        cached_key: FrontierObservationKey,
    ) -> Option<u8> {
        if cached_key == FrontierObservationKey::EMPTY
            || !cached_key.entries_equal(&observation_key)
        {
            return None;
        }
        let mut changed_slot_mask = 0u8;
        let slot_len = observation_key.len();
        let mut slot_idx = 0usize;
        while slot_idx < slot_len {
            if cached_key.slot(slot_idx) != observation_key.slot(slot_idx) {
                changed_slot_mask |= 1u8 << slot_idx;
            }
            slot_idx += 1;
        }
        let slot_masks = Self::frontier_observation_offer_lane_entry_slot_masks(self, domain);
        let lane_limit = self.cursor.logical_lane_count();
        let mut mark_changed_lane = |lane_idx: usize| {
            if cached_key.offer_lanes().contains(lane_idx)
                != observation_key.offer_lanes().contains(lane_idx)
                || cached_key.binding_nonempty_lanes().contains(lane_idx)
                    != observation_key.binding_nonempty_lanes().contains(lane_idx)
            {
                changed_slot_mask |= slot_masks[lane_idx];
            }
        };
        Self::for_each_set_lane(cached_key.offer_lanes(), lane_limit, &mut mark_changed_lane);
        Self::for_each_set_lane(
            observation_key.offer_lanes(),
            lane_limit,
            &mut mark_changed_lane,
        );
        Self::for_each_set_lane(
            cached_key.binding_nonempty_lanes(),
            lane_limit,
            &mut mark_changed_lane,
        );
        Self::for_each_set_lane(
            observation_key.binding_nonempty_lanes(),
            lane_limit,
            &mut mark_changed_lane,
        );
        Some(changed_slot_mask)
    }
}