use core::{cell::Cell, fmt, marker::PhantomData, ops::Range};
use crate::observe::core::TapEvent;
use crate::runtime::consts::{DefaultLabelUniverse, LabelUniverse, RING_EVENTS};
pub trait Clock {
fn now32(&self) -> u32;
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct OfferProgressPolicy;
pub struct CounterClock {
counter: Cell<u32>,
}
impl CounterClock {
pub const fn new() -> Self {
Self {
counter: Cell::new(0),
}
}
}
impl Default for CounterClock {
fn default() -> Self {
Self::new()
}
}
impl Clock for CounterClock {
fn now32(&self) -> u32 {
let current = self.counter.get();
let next = current.saturating_add(1);
self.counter.set(next);
current
}
}
impl<C: Clock + ?Sized> Clock for &C {
fn now32(&self) -> u32 {
(**self).now32()
}
}
impl fmt::Debug for CounterClock {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CounterClock").finish()
}
}
pub struct RuntimeStorage<'a> {
tap_buf: &'a mut [TapEvent; RING_EVENTS],
slab: &'a mut [u8],
}
impl<'a> RuntimeStorage<'a> {
#[inline]
pub fn from_buffers(tap_buf: &'a mut [TapEvent; RING_EVENTS], slab: &'a mut [u8]) -> Self {
Self { tap_buf, slab }
}
}
impl<'a> From<(&'a mut [TapEvent; RING_EVENTS], &'a mut [u8])> for RuntimeStorage<'a> {
#[inline]
fn from(resources: (&'a mut [TapEvent; RING_EVENTS], &'a mut [u8])) -> Self {
Self::from_buffers(resources.0, resources.1)
}
}
impl<'a, const N: usize> From<(&'a mut [TapEvent; RING_EVENTS], &'a mut [u8; N])>
for RuntimeStorage<'a>
{
#[inline]
fn from(resources: (&'a mut [TapEvent; RING_EVENTS], &'a mut [u8; N])) -> Self {
Self::from_buffers(resources.0, &mut resources.1[..])
}
}
pub struct Config<'a, U: LabelUniverse = DefaultLabelUniverse, C: Clock = CounterClock> {
pub(crate) tap_buf: &'a mut [TapEvent; RING_EVENTS],
pub(crate) slab: &'a mut [u8],
universe_marker: PhantomData<U>,
pub(crate) clock: C,
pub(crate) offer_progress_policy: OfferProgressPolicy,
}
impl<'a, U: LabelUniverse, C: Clock> fmt::Debug for Config<'a, U, C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Config")
.field("initial_lane_range", &Self::initial_lane_range())
.field("universe", &core::any::type_name::<U>())
.field("clock", &core::any::type_name::<C>())
.field("offer_progress_policy", &self.offer_progress_policy)
.finish()
}
}
impl<'a, U: LabelUniverse, C: Clock> Config<'a, U, C> {
pub fn from_resources(resources: impl Into<RuntimeStorage<'a>>, clock: C) -> Self {
let resources = resources.into();
Self {
tap_buf: resources.tap_buf,
slab: resources.slab,
universe_marker: PhantomData,
clock,
offer_progress_policy: OfferProgressPolicy,
}
}
pub(crate) fn initial_lane_range() -> Range<u16> {
0..0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resources_defer_lane_domain_until_projected_descriptor() {
let mut tap_buf = [TapEvent::zero(); RING_EVENTS];
let mut slab = [0u8; 256];
let _: Config<'_, DefaultLabelUniverse, _> =
Config::from_resources((&mut tap_buf, &mut slab), CounterClock::new());
let lane_range = Config::<DefaultLabelUniverse, CounterClock>::initial_lane_range();
assert_eq!(lane_range, 0..0);
}
}