hibana 0.9.6

Choreography-derived runtime enforcement kernel for no_std Rust multiparty protocols
Documentation
use core::marker::PhantomData;

use super::{ProgramProjection, ProgramShape};
use crate::global::compiled::images::COMPACT_DESCRIPTOR_BYTE_CAPACITY;

struct RoleProjection<const ROLE: u8, Steps, const CAPACITY: usize>(PhantomData<Steps>);
struct ProgramProjectionBlob<Steps, const CAPACITY: usize, const N: usize>(PhantomData<Steps>);
struct RoleProjectionBlob<const ROLE: u8, Steps, const CAPACITY: usize, const N: usize>(
    PhantomData<Steps>,
);

impl<Steps, const CAPACITY: usize, const N: usize> ProgramProjectionBlob<Steps, CAPACITY, N>
where
    Steps: ProgramShape,
{
    const BYTES: Option<crate::global::compiled::images::ProgramImageBytes<N>> =
        crate::global::compiled::images::ProgramImageBytes::<N>::from_image_if_fits(
            ProgramProjection::<Steps, CAPACITY>::SOURCE_EFF_LIST,
            ProgramProjection::<Steps, CAPACITY>::PROGRAM_COLUMNS,
        );
}

impl<Steps, const CAPACITY: usize> ProgramProjection<Steps, CAPACITY>
where
    Steps: ProgramShape,
{
    const PROGRAM_PLAN: crate::global::compiled::images::ProgramImagePlan =
        crate::global::compiled::images::ProgramImagePlan::from_program(Self::SOURCE_EFF_LIST);
    const PROGRAM_COLUMNS: crate::global::compiled::images::ProgramImageColumns =
        Self::PROGRAM_PLAN.columns();
    const PROGRAM_BLOB_LEN: usize = Self::PROGRAM_PLAN.blob_len();
    const SOURCE_COUNTS_COVERED: () = {
        if !Self::PROGRAM_COLUMNS.covers_source_counts(
            Steps::EVENT_COUNT,
            Steps::SCOPE_MARKER_COUNT,
            Steps::RESOLVER_MARKER_COUNT,
        ) {
            crate::invariant();
        }
    };

    const fn program_ref<const N: usize>() -> crate::global::compiled::images::CompiledProgramRef {
        let bytes = match &ProgramProjectionBlob::<Steps, CAPACITY, N>::BYTES {
            Some(bytes) => bytes,
            None => panic!("program bucket selection"),
        };
        bytes.compiled_ref(&Self::IMAGE, Self::PROGRAM_COLUMNS)
    }

    const PROGRAM_REF: crate::global::compiled::images::CompiledProgramRef = {
        let () = Self::SOURCE_COUNTS_COVERED;
        let () = Self::VALIDATION;
        if Self::PROGRAM_BLOB_LEN <= 32 {
            Self::program_ref::<32>()
        } else if Self::PROGRAM_BLOB_LEN <= 64 {
            Self::program_ref::<64>()
        } else if Self::PROGRAM_BLOB_LEN <= 96 {
            Self::program_ref::<96>()
        } else if Self::PROGRAM_BLOB_LEN <= 128 {
            Self::program_ref::<128>()
        } else if Self::PROGRAM_BLOB_LEN <= 192 {
            Self::program_ref::<192>()
        } else if Self::PROGRAM_BLOB_LEN <= 256 {
            Self::program_ref::<256>()
        } else if Self::PROGRAM_BLOB_LEN <= 384 {
            Self::program_ref::<384>()
        } else if Self::PROGRAM_BLOB_LEN <= 512 {
            Self::program_ref::<512>()
        } else if Self::PROGRAM_BLOB_LEN <= 1024 {
            Self::program_ref::<1024>()
        } else if Self::PROGRAM_BLOB_LEN <= 2048 {
            Self::program_ref::<2048>()
        } else if Self::PROGRAM_BLOB_LEN <= 4096 {
            Self::program_ref::<4096>()
        } else if Self::PROGRAM_BLOB_LEN <= 8192 {
            Self::program_ref::<8192>()
        } else if Self::PROGRAM_BLOB_LEN <= 16384 {
            Self::program_ref::<16384>()
        } else if Self::PROGRAM_BLOB_LEN <= 32768 {
            Self::program_ref::<32768>()
        } else if Self::PROGRAM_BLOB_LEN <= COMPACT_DESCRIPTOR_BYTE_CAPACITY {
            Self::program_ref::<{ COMPACT_DESCRIPTOR_BYTE_CAPACITY }>()
        } else {
            panic!("program image exceeds compact offset domain")
        }
    };
}

impl<const ROLE: u8, Steps, const CAPACITY: usize> RoleProjection<ROLE, Steps, CAPACITY>
where
    Steps: ProgramShape,
{
    const COUNTS: crate::global::compiled::lowering::RoleCompiledCounts =
        ProgramProjection::<Steps, CAPACITY>::IMAGE
            .role_lowering_counts(ProgramProjection::<Steps, CAPACITY>::SOURCE_EFF_LIST, ROLE);
    const FACTS: crate::global::role_program::RuntimeRoleFacts =
        crate::global::role_program::RuntimeRoleFacts::from_counts(Self::COUNTS);
    const PLAN: crate::global::role_program::RoleImagePlan =
        crate::global::role_program::RoleImagePlan::from_program(
            ProgramProjection::<Steps, CAPACITY>::SOURCE_EFF_LIST,
            Self::FACTS,
            ROLE,
        );
    const BLOB_LEN: usize = Self::PLAN.blob_len();

    const fn image_ref<const N: usize>() -> crate::global::role_program::RoleImageRef {
        let build = match &RoleProjectionBlob::<ROLE, Steps, CAPACITY, N>::BUILD {
            Some(build) => build,
            None => panic!("role bucket selection"),
        };
        build.image_ref(
            &ProgramProjection::<Steps, CAPACITY>::PROGRAM_REF,
            ROLE,
            Self::FACTS,
        )
    }

    const IMAGE_REF: crate::global::role_program::RoleImageRef = if Self::BLOB_LEN <= 32 {
        Self::image_ref::<32>()
    } else if Self::BLOB_LEN <= 64 {
        Self::image_ref::<64>()
    } else if Self::BLOB_LEN <= 96 {
        Self::image_ref::<96>()
    } else if Self::BLOB_LEN <= 128 {
        Self::image_ref::<128>()
    } else if Self::BLOB_LEN <= 192 {
        Self::image_ref::<192>()
    } else if Self::BLOB_LEN <= 256 {
        Self::image_ref::<256>()
    } else if Self::BLOB_LEN <= 384 {
        Self::image_ref::<384>()
    } else if Self::BLOB_LEN <= 512 {
        Self::image_ref::<512>()
    } else if Self::BLOB_LEN <= 1024 {
        Self::image_ref::<1024>()
    } else if Self::BLOB_LEN <= 2048 {
        Self::image_ref::<2048>()
    } else if Self::BLOB_LEN <= 4096 {
        Self::image_ref::<4096>()
    } else if Self::BLOB_LEN <= 8192 {
        Self::image_ref::<8192>()
    } else if Self::BLOB_LEN <= 16384 {
        Self::image_ref::<16384>()
    } else if Self::BLOB_LEN <= 32768 {
        Self::image_ref::<32768>()
    } else if Self::BLOB_LEN <= COMPACT_DESCRIPTOR_BYTE_CAPACITY {
        Self::image_ref::<{ COMPACT_DESCRIPTOR_BYTE_CAPACITY }>()
    } else {
        panic!("role image exceeds compact offset domain")
    };
}

impl<const ROLE: u8, Steps, const CAPACITY: usize, const N: usize>
    RoleProjectionBlob<ROLE, Steps, CAPACITY, N>
where
    Steps: ProgramShape,
{
    const BUILD: Option<crate::global::role_program::RoleImageBuild<N>> =
        RoleProjection::<ROLE, Steps, CAPACITY>::PLAN.build_if_fits(
            ProgramProjection::<Steps, CAPACITY>::SOURCE_EFF_LIST,
            RoleProjection::<ROLE, Steps, CAPACITY>::FACTS,
            ROLE,
        );
}

#[inline(always)]
pub(super) const fn role_projection_image_for<const ROLE: u8, Steps, const CAPACITY: usize>()
-> &'static crate::global::role_program::RoleImageRef
where
    Steps: ProgramShape,
{
    if !ProgramProjection::<Steps, CAPACITY>::IMAGE.contains_role(ROLE) {
        panic!("projected role is outside the choreography role range");
    }
    &RoleProjection::<ROLE, Steps, CAPACITY>::IMAGE_REF
}