use alloc::boxed::Box;
use core::cmp::Ordering;
use crate::{DaemonicError, daemonic::glass::Glass};
pub(crate) 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(crate) logical: u64,
pub(crate) hardware: Option<u64>,
pub(crate) mesh: Option<u64>,
pub(crate) 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 {
label: "Daemonic::Clock",
hash: const_daemonic_hash(
"Daemonic::Clock".as_bytes(),
crate::AXIOM_OFFSET,
),
crypto_id: const_daemonic_hash("Daemonic::Clock".as_bytes(), TOPOLOGY_ANCHOR),
depth: 2u16,
};
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 {
todo!()
}
pub(crate) fn from_secs(p0: i32) -> DaemonicDuration {
todo!()
}
}
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::*;
pub trait DaemonicClock<'clock, GLASS: Glass<GLASS> + Iterator>:
Clone
+ 'clock {
fn now<C: DaemonicClock<'clock, Timestamp>>(&self) -> Timestamp {
todo!()
}
fn tick(&self) -> Timestamp;
fn sync(&self, external: Timestamp) -> Timestamp;
fn compare(&self, a: Timestamp, b: Timestamp) -> Timestamp {
todo!()
}
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>;
}