Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
members = [
"ntp-proto",
"ntpd"
, "statime-algo", "statime-csptp", "statime-wire", "statime-netptp"]
, "statime-algo", "statime-base", "statime-csptp", "statime-wire", "statime-netptp"]
exclude = [ ]

# Properly take compiler version into account when resolving crates.
Expand Down
20 changes: 20 additions & 0 deletions statime-base/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "statime-base"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
readme.workspace = true
description.workspace = true
publish.workspace = true
rust-version.workspace = true

[lints]
workspace = true

[features]
default = ["std"]
std = []

[dependencies]
73 changes: 73 additions & 0 deletions statime-base/src/clock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use crate::{Duration, TAI, Timestamp};

/// Interface for a controllable clock
/// This needs to be a trait as a single system can have multiple clocks
/// which need different implementation for steering and/or now.
pub trait Clock: Clone + Send + 'static {
/// Error that can occur in operations on the clock.
type Error: core::error::Error + Send + Sync;

/// Get current time
///
/// # Errors
/// Should return an error if the clock is unable to provide a timestamp.
fn now(&self) -> Result<Timestamp<TAI>, Self::Error>;

/// Change the frequency of the clock, returning the time
/// at which the change was applied.
///
/// # Errors
/// Should return an error if the clock is unable to be steered by the requested amount.
fn set_frequency(&self, freq: f64) -> Result<Timestamp<TAI>, Self::Error>;

/// Get the frequency of the clock
///
/// # Errors
/// Should return an error if the clock is unable to provide its current steering frequency.
fn get_frequency(&self) -> Result<f64, Self::Error>;

/// Maximum frequency offset the clock is capable of.
///
/// # Errors
/// Should return an error if the maximum frequency offset could not be determined.
fn max_frequency(&self) -> Result<f64, Self::Error>;

/// Change the current time of the clock by offset. Returns
/// the time at which the change was applied.
///
/// # Errors
/// Should return an error if the clock cannot be stepped by the amount requested.
fn step_clock(&self, offset: Duration) -> Result<Timestamp<TAI>, Self::Error>;

/// Provide the system with our current best estimates for
/// the statistical error of the clock (`est_error`), and
/// the maximum deviation due to frequency error and
/// distance to the root clock.
///
/// # Errors
/// Should return an error if the error estimate update cannot be applied to the clock.
fn error_estimate_update(
&self,
est_error: Duration,
max_error: Duration,
) -> Result<(), Self::Error>;

/// Change the indicators for upcoming leap seconds and
/// the clocks synchronization status. Application should happen at the end of the UTC month.
///
/// # Errors
/// Should return an error if the status update cannot be applied to the clock.
fn status_update(&self, leap_status: LeapStatus) -> Result<(), Self::Error>;
}

/// Information on what the next leap second is going to be.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LeapStatus {
/// There is no leap second at the end of the month.
#[default]
None,
/// A second needs to be removed from the last minute of the month.
Leap59,
/// A second needs to be inserted into the last minute of the month.
Leap61,
}
33 changes: 33 additions & 0 deletions statime-base/src/identifiers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use core::sync::atomic::AtomicUsize;

/// Unique identifier for a clock
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct ClockId(usize);

impl ClockId {
/// Get a new identifier for a clock.
#[expect(
clippy::new_without_default,
reason = "The new value is non-trivial and non-constant, therefore not fitting for default."
)]
pub fn new() -> ClockId {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
ClockId(COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed))
}
}

/// Unique identifier for a clock
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct LinkId(usize);

impl LinkId {
/// Get a new identifier for a clock.
#[expect(
clippy::new_without_default,
reason = "The new value is non-trivial and non-constant, therefore not fitting for default."
)]
pub fn new() -> LinkId {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
LinkId(COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed))
}
}
13 changes: 13 additions & 0 deletions statime-base/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! Base types and traits for time management.
#![no_std]

mod clock;
mod identifiers;
mod time_types;

pub use clock::*;
pub use identifiers::*;
pub use time_types::*;

#[cfg(feature = "std")]
extern crate std;
Loading
Loading