Skip to main content

xaeroflux_core/
vector_clock.rs

1use 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}