hibana 0.5.2

Const-projected Affine Multiparty Session Types for choreography-first Rust protocols
Documentation
use crate::control::cluster::effects::ResourceDescriptor;
use crate::eff::EffIndex;
use crate::global::ControlDesc;
use crate::global::compiled::images::program::{
    CompiledProgramCounts, CompiledProgramFacts, DynamicPolicySite, RouteControlRecord,
};
use crate::global::compiled::images::role::{
    CompiledRoleImage, CompiledRoleSegmentHeader, PhaseImageHeader, PhaseLaneEntry,
};
use crate::global::const_dsl::ControlScopeKind;
#[cfg(test)]
use crate::global::role_program::lane_word_count;
use crate::global::role_program::{LaneWord, RoleFootprint};
use crate::global::typestate::{
    LocalNode, RoleTypestateValue, RouteDispatchEntry, RouteDispatchShape, RouteScopeRecord,
    ScopeRecord, StateIndex,
};

#[inline(always)]
const fn align_up(value: usize, align: usize) -> usize {
    let mask = align.saturating_sub(1);
    (value + mask) & !mask
}

#[inline(always)]
const fn max_align(current: usize, candidate: usize) -> usize {
    if candidate > current {
        candidate
    } else {
        current
    }
}

#[inline(always)]
const fn section_bytes<T>(count: usize) -> usize {
    count.saturating_mul(core::mem::size_of::<T>())
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_program_tail_bytes_for_counts(
    counts: CompiledProgramCounts,
) -> usize {
    let mut offset = core::mem::size_of::<CompiledProgramFacts>();
    offset = align_up(offset, core::mem::align_of::<ResourceDescriptor>());
    offset = offset.saturating_add(section_bytes::<ResourceDescriptor>(counts.resources));
    offset = align_up(offset, core::mem::align_of::<DynamicPolicySite>());
    offset = offset.saturating_add(section_bytes::<DynamicPolicySite>(
        counts.dynamic_policy_sites,
    ));
    offset = align_up(offset, core::mem::align_of::<RouteControlRecord>());
    offset.saturating_add(section_bytes::<RouteControlRecord>(counts.route_controls))
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_program_tail_align() -> usize {
    let mut align = core::mem::align_of::<CompiledProgramFacts>();
    align = max_align(align, core::mem::align_of::<ResourceDescriptor>());
    align = max_align(align, core::mem::align_of::<ControlScopeKind>());
    align = max_align(align, core::mem::align_of::<DynamicPolicySite>());
    max_align(align, core::mem::align_of::<RouteControlRecord>())
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_scope_cap(scope_count: usize) -> usize {
    scope_count
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_route_scope_cap(
    route_scope_count: usize,
) -> usize {
    route_scope_count
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_segment_header_cap(
    eff_count: usize,
) -> usize {
    if eff_count == 0 {
        0
    } else {
        eff_count.div_ceil(crate::eff::meta::MAX_SEGMENT_EFFS)
    }
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_step_cap(eff_count: usize) -> usize {
    if eff_count == 0 { 1 } else { eff_count }
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_typestate_node_cap(
    scope_count: usize,
    passive_linger_route_scope_count: usize,
    local_step_count: usize,
) -> usize {
    let capped = local_step_count
        .saturating_add(scope_count)
        .saturating_add(passive_linger_route_scope_count)
        .saturating_add(1);
    if capped == 0 { 1 } else { capped }
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_phase_cap(
    footprint: RoleFootprint,
) -> usize {
    footprint.phase_count
}

#[inline(always)]
const fn compiled_role_phase_lane_entry_cap(footprint: RoleFootprint) -> usize {
    footprint.phase_lane_entry_count
}

#[inline(always)]
const fn compiled_role_phase_lane_word_cap(footprint: RoleFootprint) -> usize {
    footprint.phase_lane_word_count
}

#[inline(always)]
const fn compiled_role_scope_lane_matrix_cap(footprint: RoleFootprint) -> usize {
    compiled_role_scope_cap(footprint.scope_count).saturating_mul(footprint.logical_lane_count)
}

#[inline(always)]
const fn compiled_role_route_scope_lane_word_cap(footprint: RoleFootprint) -> usize {
    compiled_role_route_scope_cap(footprint.route_scope_count)
        .saturating_mul(footprint.logical_lane_word_count)
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_image_bytes_for_layout(
    footprint: RoleFootprint,
) -> usize {
    let scope_cap = compiled_role_scope_cap(footprint.scope_count);
    let route_scope_cap = compiled_role_route_scope_cap(footprint.route_scope_count);
    let segment_header_cap = compiled_role_segment_header_cap(footprint.eff_count);
    let eff_index_cap = compiled_role_step_cap(footprint.eff_count);
    let step_index_cap = compiled_role_step_cap(footprint.local_step_count);
    let typestate_node_cap = compiled_role_typestate_node_cap(
        footprint.scope_count,
        footprint.passive_linger_route_scope_count,
        footprint.local_step_count,
    );
    let phase_header_cap = compiled_role_phase_cap(footprint);
    let phase_lane_entry_cap = compiled_role_phase_lane_entry_cap(footprint);
    let phase_lane_word_cap = compiled_role_phase_lane_word_cap(footprint);
    let scope_lane_matrix_cap = compiled_role_scope_lane_matrix_cap(footprint);
    let route_scope_lane_word_cap = compiled_role_route_scope_lane_word_cap(footprint);
    let route_dispatch_shape_cap = route_scope_cap;
    let route_dispatch_entry_cap =
        route_scope_cap.saturating_mul(crate::global::typestate::MAX_FIRST_RECV_DISPATCH);
    let route_dispatch_target_cap = route_dispatch_entry_cap;
    let header = core::mem::size_of::<CompiledRoleImage>();
    let segment_headers_start =
        align_up(header, core::mem::align_of::<CompiledRoleSegmentHeader>());
    let segment_headers_end = segment_headers_start
        + segment_header_cap.saturating_mul(core::mem::size_of::<CompiledRoleSegmentHeader>());
    let typestate_start = align_up(
        segment_headers_end,
        max_align(
            core::mem::align_of::<RoleTypestateValue>(),
            core::mem::align_of::<CompiledRoleImage>(),
        ),
    );
    let typestate_end = typestate_start + core::mem::size_of::<RoleTypestateValue>();
    let typestate_nodes_start = align_up(typestate_end, core::mem::align_of::<LocalNode>());
    let typestate_nodes_end = typestate_nodes_start
        + typestate_node_cap.saturating_mul(core::mem::size_of::<LocalNode>());
    let phase_headers_start = align_up(
        typestate_nodes_end,
        core::mem::align_of::<PhaseImageHeader>(),
    );
    let phase_headers_end = phase_headers_start
        + phase_header_cap.saturating_mul(core::mem::size_of::<PhaseImageHeader>());
    let phase_lane_entries_start =
        align_up(phase_headers_end, core::mem::align_of::<PhaseLaneEntry>());
    let phase_lane_entries_end = phase_lane_entries_start
        + phase_lane_entry_cap.saturating_mul(core::mem::size_of::<PhaseLaneEntry>());
    let phase_lane_words_start =
        align_up(phase_lane_entries_end, core::mem::align_of::<LaneWord>());
    let phase_lane_words_end = phase_lane_words_start
        + phase_lane_word_cap.saturating_mul(core::mem::size_of::<LaneWord>());
    let records_start = align_up(phase_lane_words_end, core::mem::align_of::<ScopeRecord>());
    let records_end = records_start + scope_cap.saturating_mul(core::mem::size_of::<ScopeRecord>());
    let scope_lane_first_start = align_up(records_end, core::mem::align_of::<EffIndex>());
    let scope_lane_first_end = scope_lane_first_start
        + scope_lane_matrix_cap.saturating_mul(core::mem::size_of::<EffIndex>());
    let scope_lane_last_start = align_up(scope_lane_first_end, core::mem::align_of::<EffIndex>());
    let scope_lane_last_end = scope_lane_last_start
        + scope_lane_matrix_cap.saturating_mul(core::mem::size_of::<EffIndex>());
    let slots_start = align_up(scope_lane_last_end, core::mem::align_of::<u16>());
    let slots_end = slots_start + scope_cap.saturating_mul(core::mem::size_of::<u16>());
    let route_dense_start = align_up(slots_end, core::mem::align_of::<u16>());
    let route_dense_end = route_dense_start + scope_cap.saturating_mul(core::mem::size_of::<u16>());
    let route_records_start = align_up(route_dense_end, core::mem::align_of::<RouteScopeRecord>());
    let route_records_end = route_records_start
        + route_scope_cap.saturating_mul(core::mem::size_of::<RouteScopeRecord>());
    let route_offer_lane_words_start =
        align_up(route_records_end, core::mem::align_of::<LaneWord>());
    let route_offer_lane_words_end = route_offer_lane_words_start
        + route_scope_lane_word_cap.saturating_mul(core::mem::size_of::<LaneWord>());
    let route_arm0_lane_words_start = align_up(
        route_offer_lane_words_end,
        core::mem::align_of::<LaneWord>(),
    );
    let route_arm0_lane_words_end = route_arm0_lane_words_start
        + route_scope_lane_word_cap.saturating_mul(core::mem::size_of::<LaneWord>());
    let route_arm1_lane_words_start =
        align_up(route_arm0_lane_words_end, core::mem::align_of::<LaneWord>());
    let route_arm1_lane_words_end = route_arm1_lane_words_start
        + route_scope_lane_word_cap.saturating_mul(core::mem::size_of::<LaneWord>());
    let route_arm0_lane_last_start =
        align_up(route_arm1_lane_words_end, core::mem::align_of::<EffIndex>());
    let route_arm0_lane_last_end = route_arm0_lane_last_start
        + scope_lane_matrix_cap.saturating_mul(core::mem::size_of::<EffIndex>());
    let route_dispatch_shapes_start = align_up(
        route_arm0_lane_last_end,
        core::mem::align_of::<RouteDispatchShape>(),
    );
    let route_dispatch_shapes_end = route_dispatch_shapes_start
        + route_dispatch_shape_cap.saturating_mul(core::mem::size_of::<RouteDispatchShape>());
    let route_dispatch_entries_start = align_up(
        route_dispatch_shapes_end,
        core::mem::align_of::<RouteDispatchEntry>(),
    );
    let route_dispatch_entries_end = route_dispatch_entries_start
        + route_dispatch_entry_cap.saturating_mul(core::mem::size_of::<RouteDispatchEntry>());
    let route_dispatch_targets_start = align_up(
        route_dispatch_entries_end,
        core::mem::align_of::<StateIndex>(),
    );
    let route_dispatch_targets_end = route_dispatch_targets_start
        + route_dispatch_target_cap.saturating_mul(core::mem::size_of::<StateIndex>());
    let eff_index_start = align_up(route_dispatch_targets_end, core::mem::align_of::<u16>());
    let eff_index_end = eff_index_start + eff_index_cap.saturating_mul(core::mem::size_of::<u16>());
    let step_index_start = align_up(eff_index_end, core::mem::align_of::<StateIndex>());
    let step_index_end =
        step_index_start + step_index_cap.saturating_mul(core::mem::size_of::<StateIndex>());
    let control_by_eff_start = align_up(step_index_end, core::mem::align_of::<ControlDesc>());
    control_by_eff_start + eff_index_cap.saturating_mul(core::mem::size_of::<ControlDesc>())
}

#[cfg(test)]
#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_image_bytes_for_counts(
    scope_count: usize,
    route_scope_count: usize,
    eff_count: usize,
) -> usize {
    let phase_count = if eff_count == 0 {
        0
    } else {
        let derived = scope_count.saturating_mul(2).saturating_add(1);
        if derived < eff_count {
            derived
        } else {
            eff_count
        }
    };
    compiled_role_image_bytes_for_layout(RoleFootprint {
        scope_count,
        max_active_scope_depth: scope_count,
        eff_count,
        phase_count,
        phase_lane_entry_count: eff_count,
        phase_lane_word_count: if eff_count == 0 {
            0
        } else {
            phase_count.saturating_mul(lane_word_count(u8::MAX as usize + 1))
        },
        parallel_enter_count: scope_count,
        route_scope_count,
        local_step_count: eff_count,
        passive_linger_route_scope_count: route_scope_count,
        active_lane_count: u8::MAX as usize + 1,
        endpoint_lane_slot_count: u8::MAX as usize + 1,
        logical_lane_count: u8::MAX as usize + 1,
        logical_lane_word_count: lane_word_count(u8::MAX as usize + 1),
        max_route_stack_depth: 0,
        scope_evidence_count: 0,
        frontier_entry_count: 0,
    })
}

#[inline(always)]
pub(in crate::global::compiled) const fn compiled_role_image_align() -> usize {
    let mut align = core::mem::align_of::<CompiledRoleImage>();
    align = max_align(align, core::mem::align_of::<RoleTypestateValue>());
    align = max_align(align, core::mem::align_of::<LocalNode>());
    align = max_align(align, core::mem::align_of::<PhaseImageHeader>());
    align = max_align(align, core::mem::align_of::<PhaseLaneEntry>());
    align = max_align(align, core::mem::align_of::<LaneWord>());
    align = max_align(align, core::mem::align_of::<ScopeRecord>());
    align = max_align(align, core::mem::align_of::<EffIndex>());
    align = max_align(align, core::mem::align_of::<u16>());
    align = max_align(align, core::mem::align_of::<RouteScopeRecord>());
    align = max_align(align, core::mem::align_of::<RouteDispatchShape>());
    align = max_align(align, core::mem::align_of::<RouteDispatchEntry>());
    align = max_align(align, core::mem::align_of::<StateIndex>());
    max_align(align, core::mem::align_of::<ControlDesc>())
}