use alloc::boxed::Box;
use core::cmp::Ordering;
use crate::{daemonic::glass::Glass, DaemonicError, Observation, TopologySegment};
pub mod types {
use alloc::boxed::Box;
use core::fmt::Formatter;
use alloc::fmt;
use core::fmt::Display;
use crate::{const_daemonic_hash, Glass};
use crate::Observation;
use core::ops::{Add, Sub};
use crate::daemonic::daemonic_core::DaemonicClock;
use crate::daemonic::glass::{GlassStable, Severity};
use crate::daemonic::topology::TOPOLOGY_ANCHOR;
use crate::daemonic::TopologySegment;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Timestamp {
pub logical: u64,
pub hardware: Option<u64>,
pub mesh: Option<u64>,
pub wall: Option<u64>,
}
impl Iterator for Timestamp {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
let x = [self.logical, self.hardware?, self.mesh?, self.wall?];
let mut iter = x.iter();
let x = iter.next()?;
Some(*x)
}
}
static DAEMONIC_CLOCK_TOPOLOGY_ANCH0R: TopologySegment = TopologySegment::new("Daemonic::Clock");
impl Glass<Timestamp> for Timestamp {
type Anchor = TopologySegment;
fn position(&self) -> &TopologySegment {
&DAEMONIC_CLOCK_TOPOLOGY_ANCH0R
}
fn severity(&self) -> Severity {
Severity::Unknown
}
fn payload(&self) -> Option<&Timestamp> {
unreachable!("Timestamps should always be owned")
}
fn into_payload(self) -> Option<Timestamp>
where
Self: Sized,
Timestamp: Sized,
{
Some(Timestamp {
logical: self.logical,
hardware: self.hardware,
mesh: self.mesh,
wall: self.wall,
})
}
}
impl Timestamp {
pub const fn new_logical_clock(value: u64) -> Self {
Self {
logical: value,
hardware: None,
mesh: None,
wall: None,
}
}
pub const fn zerol() -> Self {
Self {
logical: 0,
hardware: None,
mesh: None,
wall: None,
}
}
pub const fn zeroh() -> Self {
Self {
logical: 0,
hardware: Some(0u64),
mesh: None,
wall: None,
}
}
pub const fn one() -> Self {
Self {
logical: 1,
hardware: Some(1u64),
mesh: Some(1u64),
wall: Some(1u64),
}
}
pub const fn logical_as_u64(self) -> u64 {
self.logical
}
pub const fn hardware_as_u64(self) -> Option<u64> {
self.hardware
}
pub const fn mesh_as_u64(self) -> Option<u64> {
self.mesh
}
pub const fn wall_as_u64(self) -> Option<u64> {
self.wall
}
pub const fn logical_is_zero(self) -> bool {
self.logical_as_u64() == 0u64
}
pub fn hardware_is_zero(self) -> bool {
self.hardware_as_u64() == Option::from(0u64)
}
pub fn wall_is_zero(self) -> bool {
self.wall_as_u64() == Option::from(0u64)
}
pub fn mesh_is_zero(self) -> bool {
self.mesh_as_u64() == Option::from(0u64)
}
pub fn logical_time_elapsed_since(self, earlier: Timestamp) -> u64 {
assert!(self >= earlier, "earlier must be <= self");
self.logical - earlier.logical
}
pub fn checked_logical_time_elapsed_since(self, earlier: Timestamp) -> Option<u64> {
if self >= earlier {
Some(self.logical - earlier.logical)
} else {
None
}
}
pub fn logical_saturating_sub(self, other: Timestamp) -> u64 {
self.logical.saturating_sub(other.logical)
}
}
impl Add<u64> for Timestamp {
type Output = Timestamp;
fn add(self, rhs: u64) -> Timestamp {
let x = self.logical + rhs;
Timestamp::new_logical_clock(x)
}
}
impl Sub for Timestamp {
type Output = u64;
fn sub(self, rhs: Timestamp) -> u64 {
self.logical - rhs.logical
}
}
impl Sub<u64> for Timestamp {
type Output = Timestamp;
fn sub(self, rhs: u64) -> Timestamp {
Timestamp::new_logical_clock(self.logical - rhs)
}
}
impl From<u64> for Timestamp {
fn from(value: u64) -> Self {
Timestamp::new_logical_clock(value)
}
}
impl From<Timestamp> for u64 {
fn from(ts: Timestamp) -> u64 {
ts.logical
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DaemonicDuration(u64);
impl DaemonicDuration {
pub const fn new(ticks: u64) -> Self {
Self(ticks)
}
pub const fn zero() -> Self {
Self(0)
}
pub const fn as_u64(self) -> u64 {
self.0
}
pub const fn is_zero(self) -> bool {
self.0 == 0
}
pub(crate) fn as_secs_f64(&self) -> f64 {
unimplemented!("Logical Clock ticks cannot be represented as seconds yet")
}
pub(crate) fn from_secs(p0: i32) -> DaemonicDuration {
unimplemented!("Logical Clock ticks cannot be represented as seconds yet")
}
}
impl From<u64> for DaemonicDuration {
fn from(ticks: u64) -> Self {
DaemonicDuration(ticks)
}
}
impl From<DaemonicDuration> for u64 {
fn from(d: DaemonicDuration) -> u64 {
d.0
}
}
impl Display for DaemonicDuration { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{} ticks", self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_timestamp_creation() {
let ts = Timestamp::new_logical_clock(42);
assert_eq!(ts.logical_as_u64(), 42);
let zero = Timestamp::new_logical_clock(0);
assert!(zero.logical_is_zero());
assert_eq!(zero.logical_as_u64(), 0);
}
#[test]
fn test_timestamp_arithmetic() {
let t1 = Timestamp::new_logical_clock(100);
let t2 = Timestamp::new_logical_clock(200);
assert_eq!(t1 + 50, Timestamp::new_logical_clock(150));
assert_eq!(t2 - t1, 100);
assert_eq!(t2 - 50, Timestamp::new_logical_clock(150));
}
#[test]
fn test_timestamp_elapsed() {
let t1 = Timestamp::new_logical_clock(100);
let t2 = Timestamp::new_logical_clock(200);
assert_eq!(t2.logical_time_elapsed_since(t1), 100);
assert_eq!(t2.checked_logical_time_elapsed_since(t1), Some(100));
assert_eq!(t1.checked_logical_time_elapsed_since(t2), None);
}
#[test]
fn test_timestamp_ordering() {
let t1 = Timestamp::new_logical_clock(100);
let t2 = Timestamp::new_logical_clock(200);
assert!(t1 < t2);
assert!(t2 > t1);
assert_eq!(t1, Timestamp::new_logical_clock(100));
}
#[test]
fn test_timestamp_conversions() {
let value: u64 = 42;
let ts: Timestamp = value.into();
let back: u64 = ts.into();
assert_eq!(back, value);
}
}
}
use types::*;
static DAEMONIC_CLOCK_TOPOLOGY_SEGMENT: TopologySegment = TopologySegment::new("Daemonic::Clock");
pub trait DaemonicClock<'clock, GLASS: Glass<GLASS> + Iterator>: Clone + 'clock {
fn new(x: u64) -> Timestamp {
if x == 0u64 {
::daemonic_error::daemonic::observation::Observation::<GLASS>::shattered(&DAEMONIC_CLOCK_TOPOLOGY_SEGMENT).with_note(
"[DAEMONIC ERROR] -> SHATTERED OBSERVATION RETURNED IN CLOCK INPUT\
Note: 0 is reserved for broken_sword() functionality which is not for new()\
This function is designed to be used for instantiating a new clock from callsite,\
not modifying an existing one.\
\
New Daemonic Clock constructs can never be 0, else TEMPORAL STACK UNWIND INITIATES\
Citing: TIME HAS BECOME MEANINGLESS, ALL HELD SYMBOLS TRIGGER DIE IN TRANSIT PREDICATE");
core::intrinsics::abort();
} else {
Timestamp::new_logical_clock(x)
}
}
fn now<C: DaemonicClock<'clock, Timestamp>>(&self) -> Timestamp;
#[inline(always)]
fn tick(&self) -> impl Glass<Timestamp>;
fn sync(&self, external: Timestamp) -> Timestamp;
fn compare(&self, a: Timestamp, b: Timestamp) -> Timestamp;
fn is_zero(&self, ts: Timestamp) -> bool
where
GLASS: Glass<bool>,
{
ts.logical_is_zero() }
fn duration_between(
&self,
a: Timestamp,
b: Timestamp,
) -> dyn Glass<DaemonicDuration, Anchor=Self>;
fn clock_type<'clocktype>(&self) -> &impl DaemonicClock<GLASS>;
fn is_healthy(&self) -> bool;
}
pub trait SteerableClock<GLASS: Glass<GLASS> + Iterator>: for<'steerableclock> DaemonicClock<'steerableclock, GLASS> {
fn set_frequency(&self, freq: f64) -> dyn Glass<Timestamp, Anchor=Self>;
fn get_frequency(&self) -> dyn Glass<f64, Anchor=Self>; }
pub trait SteppableClock<GLASS: Glass<GLASS> + Iterator>: for<'steppableclock> DaemonicClock<'steppableclock, GLASS> {
fn step(&self, offset: DaemonicDuration) -> dyn Glass<Timestamp, Anchor=Self>;
}
pub trait UncertainClock<GLASS: Glass<GLASS> + Iterator>: for<'uncertainclock> DaemonicClock<'uncertainclock, GLASS> {
fn uncertainty(&self) -> dyn Glass<DaemonicDuration, Anchor=Self>;
fn set_uncertainty(&self, uncertainty: DaemonicDuration) -> dyn Glass<(), Anchor=Self>;
}