hibana 0.6.2

Const-projected Affine Multiparty Session Types for choreography-first Rust protocols
Documentation
use super::CompiledProgramImage;
use crate::eff::EffIndex;
use crate::global::const_dsl::{ControlScopeKind, ScopeEvent, ScopeId, ScopeKind, ScopeMarker};

use super::super::images::program::RouteControlRecord;

#[inline(always)]
fn compiled_program_route_scope_end(
    scope_markers: &[ScopeMarker],
    enter_idx: usize,
    scope: ScopeId,
    default_end: usize,
) -> usize {
    let mut scope_end = default_end;
    let mut scan_idx = enter_idx + 1;
    let mut nest_depth = 1usize;
    while scan_idx < scope_markers.len() {
        let scan_marker = scope_markers[scan_idx];
        if scan_marker.scope_id.local_ordinal() == scope.local_ordinal() {
            match scan_marker.event {
                ScopeEvent::Enter => nest_depth += 1,
                ScopeEvent::Exit => {
                    nest_depth -= 1;
                    if nest_depth == 0 {
                        scope_end = scan_marker.offset;
                        break;
                    }
                }
            }
        }
        scan_idx += 1;
    }
    scope_end
}

#[inline(always)]
pub(in crate::global::compiled) fn compiled_program_route_control_for_scope(
    summary: &CompiledProgramImage,
    scope_id: ScopeId,
) -> Option<RouteControlRecord> {
    if scope_id.is_none() {
        return None;
    }
    let view = summary.view();
    let scope_markers = view.scope_markers();
    let default_end = view.len();
    let mut marker_idx = 0usize;
    while marker_idx < scope_markers.len() {
        let marker = scope_markers[marker_idx];
        if matches!(marker.event, ScopeEvent::Enter)
            && matches!(marker.scope_kind, ScopeKind::Route)
            && marker.scope_id.canonical().raw() == scope_id.canonical().raw()
        {
            let scope_end = compiled_program_route_scope_end(
                scope_markers,
                marker_idx,
                marker.scope_id,
                default_end,
            );
            let (route_policy_id, route_policy_eff, route_policy_tag, route_policy_op) = match view
                .first_route_head_dynamic_policy_in_range(marker.scope_id, marker_idx, scope_end)
            {
                Some((policy, eff_offset, tag, op)) => (
                    match policy.dynamic_policy_id() {
                        Some(policy_id) => policy_id,
                        None => u16::MAX,
                    },
                    EffIndex::from_dense_ordinal(eff_offset),
                    tag,
                    Some(op),
                ),
                None => (u16::MAX, EffIndex::MAX, 0, None),
            };
            return Some(RouteControlRecord::new(
                marker.scope_id,
                marker.controller_role,
                route_policy_id,
                route_policy_eff,
                route_policy_tag,
                route_policy_op,
            ));
        }
        marker_idx += 1;
    }
    None
}

#[inline(always)]
pub(in crate::global::compiled) const fn control_scope_mask_bit(
    scope_kind: ControlScopeKind,
) -> u8 {
    match scope_kind {
        ControlScopeKind::None => 0,
        ControlScopeKind::Loop => 1 << 0,
        ControlScopeKind::State => 1 << 1,
        ControlScopeKind::Abort => 0,
        ControlScopeKind::Topology => 1 << 3,
        ControlScopeKind::Delegate => 0,
        ControlScopeKind::Policy => 0,
        ControlScopeKind::Route => 0,
    }
}