pub(crate) mod meta {
pub(crate) const MAX_SEGMENT_EFFS: usize = 96;
pub(crate) const MAX_SEGMENTS: usize = 32;
pub(crate) const MAX_EFF_NODES: usize = MAX_SEGMENTS * MAX_SEGMENT_EFFS;
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct EffIndex(u32);
impl EffIndex {
pub(crate) const ZERO: Self = Self(0);
#[inline(always)]
pub(crate) const fn from_segment_offset(segment: u16, offset: u16) -> Self {
if segment as usize >= meta::MAX_SEGMENTS || offset as usize >= meta::MAX_SEGMENT_EFFS {
crate::invariant();
}
Self(((segment as u32) << 16) | offset as u32)
}
#[inline(always)]
pub(crate) const fn from_dense_ordinal(idx: usize) -> Self {
if idx >= meta::MAX_EFF_NODES {
crate::invariant();
}
let segment = idx / meta::MAX_SEGMENT_EFFS;
let offset = idx % meta::MAX_SEGMENT_EFFS;
Self::from_segment_offset(segment as u16, offset as u16)
}
#[inline(always)]
pub(crate) const fn segment(self) -> u16 {
(self.0 >> 16) as u16
}
#[inline(always)]
pub(crate) const fn offset(self) -> u16 {
self.0 as u16
}
#[inline(always)]
pub(crate) const fn dense_ordinal(self) -> usize {
let segment = self.segment() as usize;
let offset = self.offset() as usize;
if segment >= meta::MAX_SEGMENTS || offset >= meta::MAX_SEGMENT_EFFS {
crate::invariant();
}
segment * meta::MAX_SEGMENT_EFFS + offset
}
}
impl core::fmt::Display for EffIndex {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}:{}", self.segment(), self.offset())
}
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum EffKind {
Pure = 0,
Atom = 1,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum EventOrigin {
User = 0,
Session = 1,
}
impl EventOrigin {
#[inline(always)]
pub(crate) const fn from_packed_bits(bits: u8) -> Self {
match bits {
0 => Self::User,
1 => Self::Session,
_ => crate::invariant(),
}
}
#[inline(always)]
pub(crate) const fn packed_bits(self) -> u8 {
match self {
Self::User => 0,
Self::Session => 1,
}
}
#[inline(always)]
pub(crate) const fn is_session(self) -> bool {
matches!(self, Self::Session)
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct EffAtom {
pub(crate) from: u8,
pub(crate) to: u8,
pub(crate) label: u8,
pub(crate) origin: EventOrigin,
pub(crate) lane: u8,
}
impl EffAtom {
pub(crate) const ZERO: Self = Self {
from: 0,
to: 0,
label: 0,
origin: EventOrigin::User,
lane: 0,
};
}
#[repr(transparent)]
#[derive(Clone, Copy)]
pub(crate) struct EffData {
atom: EffAtom,
}
impl EffData {
pub(crate) const fn empty() -> Self {
Self {
atom: EffAtom::ZERO,
}
}
pub(crate) const fn from_atom(atom: EffAtom) -> Self {
Self { atom }
}
#[inline(always)]
pub(crate) const fn atom(&self) -> EffAtom {
self.atom
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub(crate) struct EffStruct {
pub(crate) kind: EffKind,
pub(crate) data: EffData,
}
impl EffStruct {
pub(crate) const fn pure() -> Self {
Self {
kind: EffKind::Pure,
data: EffData::empty(),
}
}
pub(crate) const fn atom(atom: EffAtom) -> Self {
Self {
kind: EffKind::Atom,
data: EffData::from_atom(atom),
}
}
#[inline(always)]
pub(crate) const fn atom_data(&self) -> EffAtom {
match self.kind {
EffKind::Pure => crate::invariant(),
EffKind::Atom => self.data.atom(),
}
}
}
impl core::fmt::Debug for EffStruct {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.kind {
EffKind::Pure => f.debug_struct("EffStruct::Pure").finish(),
EffKind::Atom => f
.debug_struct("EffStruct::Atom")
.field("atom", &self.atom_data())
.finish(),
}
}
}
impl PartialEq for EffStruct {
fn eq(&self, other: &Self) -> bool {
if self.kind != other.kind {
return false;
}
match self.kind {
EffKind::Pure => true,
EffKind::Atom => self.atom_data() == other.atom_data(),
}
}
}
impl Eq for EffStruct {}
#[cfg(test)]
mod tests {
use super::{EffIndex, EffStruct};
#[test]
fn eff_index_checked_constructor_packs_valid_segment_and_offset() {
let idx = EffIndex::from_segment_offset(2, 42);
assert_eq!(idx.segment(), 2);
assert_eq!(idx.offset(), 42);
assert_eq!(idx, EffIndex((2u32 << 16) | 42));
}
#[test]
#[should_panic]
fn invalid_eff_index_constructor_panics_at_construction() {
let _ = EffIndex::from_segment_offset(super::meta::MAX_SEGMENTS as u16, 0);
}
#[test]
#[should_panic]
fn pure_effect_atom_data_fails_fast() {
let _ = EffStruct::pure().atom_data();
}
#[test]
fn eff_index_from_dense_ordinal_stays_segment_zero() {
let idx = EffIndex::from_dense_ordinal(42);
assert_eq!(idx.segment(), 0);
assert_eq!(idx.offset(), 42);
assert_eq!(idx.dense_ordinal(), 42);
}
#[test]
fn eff_index_display_is_always_segmented() {
let first = EffIndex::from_dense_ordinal(42);
let second = EffIndex::from_dense_ordinal(super::meta::MAX_SEGMENT_EFFS + 7);
assert_eq!(std::format!("{first}"), "0:42");
assert_eq!(std::format!("{second}"), "1:7");
}
#[test]
fn eff_index_from_dense_ordinal_crosses_segment_boundary() {
let idx = EffIndex::from_dense_ordinal(super::meta::MAX_SEGMENT_EFFS + 7);
assert_eq!(idx.segment(), 1);
assert_eq!(idx.offset(), 7);
assert_eq!(idx.dense_ordinal(), super::meta::MAX_SEGMENT_EFFS + 7);
}
}