use core::sync::atomic::AtomicUsize;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct ClockId(usize);
impl ClockId {
#[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))
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct LinkId(ClockId, ClockId, usize);
impl LinkId {
pub fn new(a: ClockId, b: ClockId) -> Option<LinkId> {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
if a == b {
None
} else {
Some(LinkId(
a,
b,
COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed),
))
}
}
#[must_use]
pub fn first_clock(self) -> ClockId {
self.0
}
#[must_use]
pub fn second_clock(self) -> ClockId {
self.1
}
#[must_use]
pub fn contains_clock(self, clock: ClockId) -> bool {
self.0 == clock || self.1 == clock
}
#[must_use]
pub fn forward(self) -> DirectedLinkId {
DirectedLinkId(self, Direction::Forward)
}
#[must_use]
pub fn reverse(self) -> DirectedLinkId {
DirectedLinkId(self, Direction::Reverse)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DirectedLinkId(LinkId, Direction);
impl DirectedLinkId {
#[must_use]
pub fn new(link_id: LinkId, direction: Direction) -> DirectedLinkId {
DirectedLinkId(link_id, direction)
}
#[must_use]
pub fn link_id(self) -> LinkId {
self.0
}
#[must_use]
pub fn direction(self) -> Direction {
self.1
}
#[must_use]
pub fn reverse(self) -> DirectedLinkId {
DirectedLinkId::new(self.0, self.1.reverse())
}
#[must_use]
pub fn from_clock(self) -> ClockId {
match self.1 {
Direction::Forward => self.0.first_clock(),
Direction::Reverse => self.0.second_clock(),
}
}
#[must_use]
pub fn to_clock(self) -> ClockId {
match self.1 {
Direction::Forward => self.0.second_clock(),
Direction::Reverse => self.0.first_clock(),
}
}
#[must_use]
pub fn is_reverse_of(self, other: DirectedLinkId) -> bool {
self.0 == other.0 && self.1.is_reverse_of(other.1)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Direction {
Forward,
Reverse,
}
impl Direction {
#[must_use]
pub fn reverse(self) -> Direction {
match self {
Direction::Forward => Direction::Reverse,
Direction::Reverse => Direction::Forward,
}
}
#[must_use]
pub fn is_reverse_of(self, other: Direction) -> bool {
self != other
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SourceType {
Pps,
Sock,
Ntp,
Csptp,
}