etwin_core 0.12.3

Core crate for Eternal-Twin
Documentation
use crate::core::Instant;
use auto_impl::auto_impl;
use chrono::{Duration, Utc};
use std::sync::atomic::{AtomicI64, Ordering};

#[auto_impl(&, Arc)]
pub trait Clock: Send + Sync {
  fn now(&self) -> Instant;
}

pub struct VirtualClock {
  start: Instant,
  offset: AtomicI64,
}

impl VirtualClock {
  pub fn new(start: Instant) -> Self {
    Self {
      start,
      offset: AtomicI64::new(0),
    }
  }

  pub fn advance_by(&self, d: Duration) {
    let d: i64 = d.num_milliseconds();
    assert!(d >= 0);
    self.offset.fetch_add(d, Ordering::SeqCst);
  }

  /// Updates the clock to the supplied time, if it more recent
  ///
  /// Returns the time after the update.
  pub fn advance_to(&self, t: Instant) -> Instant {
    assert!(t >= self.start);
    let new_duration = t.into_chrono() - self.start.into_chrono();
    let new_offset = new_duration.num_milliseconds();
    let old_offset = self.offset.fetch_max(new_offset, Ordering::SeqCst);
    assert!(new_offset >= old_offset);
    self.to_instant(new_offset)
  }

  fn to_instant(&self, offset: i64) -> Instant {
    Instant::new_round_down(self.start.into_chrono() + Duration::milliseconds(offset))
  }
}

impl Clock for VirtualClock {
  fn now(&self) -> Instant {
    let offset = self.offset.load(Ordering::SeqCst);
    self.to_instant(offset)
  }
}

#[cfg(feature = "neon")]
impl neon::prelude::Finalize for VirtualClock {}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SystemClock;

impl Clock for SystemClock {
  fn now(&self) -> Instant {
    Instant::new_round_down(Utc::now())
  }
}

#[cfg(feature = "neon")]
impl neon::prelude::Finalize for SystemClock {}