hibana 0.9.6

Choreography-derived runtime enforcement kernel for no_std Rust multiparty protocols
Documentation
use super::super::*;

impl CompiledProgramImage {
    const fn scan_into<const E: usize>(summary: &mut Self, eff_list: &EffList<E>) {
        let mut scope_count = 0u16;
        let mut max_role = 0u8;
        let has_atom = eff_list.len() != 0;
        if eff_list.len() > u16::MAX as usize {
            panic!("choreography exceeds compact event domain");
        }
        summary.program.lowering_facts.eff_count = eff_list.len() as u16;
        let mut idx = 0usize;
        while idx < eff_list.len() {
            let atom = eff_list.atom_at(idx);
            if atom.from > max_role {
                max_role = atom.from;
            }
            if atom.to > max_role {
                max_role = atom.to;
            }
            idx += 1;
        }

        let src_scope_markers = eff_list.scope_markers();
        let mut scope_idx = 0usize;
        let mut active_scope_depth = 0u16;
        let mut max_active_scope_depth = 0u16;
        let mut active_route_depth = 0u16;
        let mut max_route_depth = 0u16;
        while scope_idx < src_scope_markers.len() {
            let marker = src_scope_markers.at(scope_idx);
            match marker.event {
                ScopeEvent::Enter(_) => {
                    scope_count = increment_compact_count(scope_count);
                    active_scope_depth = increment_compact_count(active_scope_depth);
                    if active_scope_depth > max_active_scope_depth {
                        max_active_scope_depth = active_scope_depth;
                    }
                    if matches!(
                        marker.scope_id.kind(),
                        Some(crate::global::const_dsl::ScopeKind::Parallel)
                    ) {
                        summary.program.lowering_facts.parallel_enter_count =
                            increment_compact_count(
                                summary.program.lowering_facts.parallel_enter_count,
                            );
                    } else if matches!(
                        marker.scope_id.kind(),
                        Some(crate::global::const_dsl::ScopeKind::Route)
                    ) {
                        active_route_depth = increment_compact_count(active_route_depth);
                        if active_route_depth > max_route_depth {
                            max_route_depth = active_route_depth;
                        }
                        if src_scope_markers.is_first_enter(scope_idx) {
                            summary.program.lowering_facts.route_scope_count =
                                increment_compact_count(
                                    summary.program.lowering_facts.route_scope_count,
                                );
                            summary.program.compiled_program_counts.route_resolvers =
                                summary.program.lowering_facts.route_scope_count as usize;
                            if eff_list.resolver_for_scope(marker.scope_id).is_some() {
                                summary
                                    .program
                                    .compiled_program_counts
                                    .dynamic_resolver_sites += 1;
                            }
                        }
                    }
                }
                ScopeEvent::Exit => {
                    if matches!(
                        marker.scope_id.kind(),
                        Some(crate::global::const_dsl::ScopeKind::Route)
                    ) {
                        if active_route_depth == 0 {
                            panic!("route scope depth underflow");
                        }
                        active_route_depth -= 1;
                    }
                    if active_scope_depth == 0 {
                        panic!("scope depth underflow");
                    }
                    active_scope_depth -= 1;
                }
                ScopeEvent::Split => {}
            }
            scope_idx += 1;
        }

        if !has_atom {
            panic!("compiled choreography requires at least one event");
        }

        summary.program.lowering_facts.scope_count = scope_count;
        summary.program.lowering_facts.max_active_scope_depth = max_active_scope_depth;
        summary.program.lowering_facts.max_route_commit_count = max_route_depth;
        summary.max_role = max_role;
    }

    const fn scan_impl<const E: usize>(eff_list: &EffList<E>) -> Self {
        let mut summary = Self {
            program: ProgramImageData {
                compiled_program_counts: CompiledProgramCounts {
                    dynamic_resolver_sites: 0,
                    route_resolvers: 0,
                },
                lowering_facts: ProgramLoweringFacts::EMPTY,
            },
            max_role: 0,
        };
        Self::scan_into(&mut summary, eff_list);
        summary
    }

    #[inline(always)]
    pub(crate) const fn scan_const<const E: usize>(eff_list: &EffList<E>) -> Self {
        Self::scan_impl(eff_list)
    }

    #[inline(always)]
    pub(crate) const fn compiled_program_role_count(&self) -> usize {
        self.max_role as usize + 1
    }

    #[inline(always)]
    pub(crate) const fn contains_role(&self, role: u8) -> bool {
        role <= self.max_role
    }

    #[inline(always)]
    pub(crate) const fn max_role(&self) -> u8 {
        self.max_role
    }

    #[inline(always)]
    pub(crate) const fn role_lowering_counts<const E: usize>(
        &self,
        eff_list: &EffList<E>,
        role: u8,
    ) -> RoleCompiledCounts {
        if !self.contains_role(role) {
            panic!("projected role is outside the choreography role range");
        }
        let role = crate::global::compiled::lowering::seal::exact_role_facts(eff_list, role);
        RoleCompiledCounts {
            max_route_commit_count: self.program.lowering_facts.max_route_commit_count as usize,
            local_step_count: role.local_step_count as usize,
            route_scope_count: self.program.lowering_facts.route_scope_count as usize,
            active_lane_count: role.active_lane_count as usize,
            endpoint_lane_slot_count: role.endpoint_lane_slot_count as usize,
            logical_lane_count: role.logical_lane_count as usize,
        }
    }

    #[inline(always)]
    pub(crate) const fn validate_projection_program(&self) {
        self.program.validate_projection_program();
    }
}