xaeroflux_core/
vector_clock.rs1use std::{cmp::Ordering, collections::HashMap};
2
3use bytemuck::{Pod, Zeroable};
4use rkyv::{Archive, Deserialize, Serialize};
5use xaeroid::XaeroID;
6
7#[repr(C)]
8#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
9pub struct VectorClock {
10 pub latest_timestamp: u64,
11 pub neighbor_clocks: HashMap<XaeroID, u64>,
12}
13
14#[repr(C)]
15#[derive(Clone, Copy)]
16pub struct VectorClockEntry {
17 pub timestamp: u64,
18 pub xaero_id: XaeroID,
19}
20unsafe impl Zeroable for VectorClockEntry {}
21unsafe impl Pod for VectorClockEntry {}
22
23impl VectorClock {
24 pub fn new(latest_timestamp: u64, neighbor_clocks: HashMap<XaeroID, u64>) -> Self {
25 VectorClock {
26 latest_timestamp: latest_timestamp.max(
27 neighbor_clocks
28 .values()
29 .max()
30 .unwrap_or(&latest_timestamp)
31 .wrapping_add(1),
32 ),
33 neighbor_clocks,
34 }
35 }
36
37 pub fn tick(&mut self, xaero_id: XaeroID) {
38 self.latest_timestamp = self.latest_timestamp.wrapping_add(1);
39 self.neighbor_clocks.insert(xaero_id, self.latest_timestamp);
40 self.neighbor_clocks.retain(|_, v| *v > 0);
41 }
42
43 pub fn resync(&mut self, neighbor_clocks: HashMap<XaeroID, u64>) -> Self {
44 VectorClock {
45 latest_timestamp: self.latest_timestamp.max(
46 neighbor_clocks
47 .values()
48 .max()
49 .unwrap_or(&self.latest_timestamp)
50 .wrapping_add(1),
51 ),
52 neighbor_clocks,
53 }
54 }
55
56 pub fn update(&mut self, neighbor_clock: VectorClockEntry) -> bool {
57 self.neighbor_clocks
58 .insert(neighbor_clock.xaero_id, neighbor_clock.timestamp);
59 self.latest_timestamp = self
60 .latest_timestamp
61 .max(neighbor_clock.timestamp)
62 .wrapping_add(1);
63 true
64 }
65}
66
67impl Eq for VectorClock {}
68
69impl PartialEq<Self> for VectorClock {
70 fn eq(&self, other: &Self) -> bool {
71 self.latest_timestamp == other.latest_timestamp
72 && self.neighbor_clocks == other.neighbor_clocks
73 }
74}
75
76#[allow(clippy::non_canonical_partial_ord_impl)]
77impl PartialOrd<Self> for VectorClock {
78 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
79 self.latest_timestamp.partial_cmp(&other.latest_timestamp)
80 }
81}
82
83impl Ord for VectorClock {
84 fn cmp(&self, other: &Self) -> Ordering {
85 self.latest_timestamp.cmp(&other.latest_timestamp)
86 }
87}