hibana 0.9.6

Choreography-derived runtime enforcement kernel for no_std Rust multiparty protocols
Documentation
use super::{PRESENT_STATE_INDEX_CAPACITY, ScopeId, StateIndex};
use crate::global::const_dsl::ScopeKind;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(kani, derive(kani::Arbitrary))]
pub(crate) enum FrontierKind {
    Route,
    Reentry,
    Parallel,
    PassiveObserver,
}

impl FrontierKind {
    pub(crate) const ALL_BITS: u8 = (1 << 4) - 1;

    #[inline]
    pub(crate) const fn bit(self) -> u8 {
        match self {
            Self::Route => 1 << 0,
            Self::Reentry => 1 << 1,
            Self::Parallel => 1 << 2,
            Self::PassiveObserver => 1 << 3,
        }
    }
}

#[inline]
pub(crate) fn checked_state_index(idx: usize) -> Option<StateIndex> {
    if idx < PRESENT_STATE_INDEX_CAPACITY {
        Some(StateIndex::new(idx as u16))
    } else {
        None
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct OfferEntryKey {
    scope: ScopeId,
    entry: StateIndex,
}

impl OfferEntryKey {
    pub(crate) const EMPTY: Self = Self {
        scope: ScopeId::none(),
        entry: StateIndex::ABSENT,
    };

    #[inline]
    pub(crate) const fn new(scope: ScopeId, entry: StateIndex) -> Option<Self> {
        if !matches!(scope.kind(), Some(ScopeKind::Route)) || entry.is_absent() {
            None
        } else {
            Some(Self { scope, entry })
        }
    }

    #[inline]
    pub(crate) fn from_index(scope: ScopeId, entry_idx: usize) -> Option<Self> {
        Self::new(scope, checked_state_index(entry_idx)?)
    }

    #[inline]
    pub(crate) const fn is_absent(self) -> bool {
        self.scope.is_none() || self.entry.is_absent()
    }

    #[inline]
    pub(crate) const fn scope(self) -> ScopeId {
        self.scope
    }

    #[inline]
    pub(crate) const fn entry(self) -> StateIndex {
        self.entry
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct LaneOfferState {
    pub(crate) scope: ScopeId,
    pub(crate) entry: StateIndex,
    pub(crate) parallel_root: ScopeId,
    pub(crate) frontier: FrontierKind,
    pub(crate) flags: u8,
}

impl LaneOfferState {
    pub(crate) const FLAG_CONTROLLER: u8 = 1;
    pub(crate) const FLAG_DYNAMIC: u8 = 1 << 1;
    pub(crate) const FLAG_INTRINSIC_READY: u8 = 1 << 2;
    pub(crate) const EMPTY: Self = Self {
        scope: ScopeId::none(),
        entry: StateIndex::ABSENT,
        parallel_root: ScopeId::none(),
        frontier: FrontierKind::Route,
        flags: 0,
    };

    #[inline]
    pub(crate) const fn key(self) -> Option<OfferEntryKey> {
        OfferEntryKey::new(self.scope, self.entry)
    }

    #[inline]
    pub(crate) fn is_controller(self) -> bool {
        (self.flags & Self::FLAG_CONTROLLER) != 0
    }

    #[inline]
    pub(crate) fn is_dynamic(self) -> bool {
        (self.flags & Self::FLAG_DYNAMIC) != 0
    }

    #[inline]
    pub(crate) fn intrinsic_ready(self) -> bool {
        (self.flags & Self::FLAG_INTRINSIC_READY) != 0
    }
}