1use std::{
2 fmt::Display,
3 hash::Hash,
4 ops::{Add, Sub},
5};
6
7pub type Client = u64;
8pub type Clock = u64;
9
10#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default)]
11#[cfg_attr(fuzzing, derive(arbitrary::Arbitrary))]
12#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
13pub struct Id {
14 pub client: Client,
15 pub clock: Clock,
16}
17
18impl Id {
19 pub fn new(client: Client, clock: Clock) -> Self {
20 Self { client, clock }
21 }
22}
23
24impl From<(Client, Clock)> for Id {
25 fn from((client, clock): (Client, Clock)) -> Self {
26 Id::new(client, clock)
27 }
28}
29
30impl Sub<Clock> for Id {
31 type Output = Id;
32
33 fn sub(self, rhs: Clock) -> Self::Output {
34 (self.client, self.clock - rhs).into()
35 }
36}
37
38impl Add<Clock> for Id {
39 type Output = Id;
40
41 fn add(self, rhs: Clock) -> Self::Output {
42 (self.client, self.clock + rhs).into()
43 }
44}
45
46impl Display for Id {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 write!(f, "({}, {})", self.client, self.clock)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn basic_id_operation() {
58 let id_with_different_client_1 = Id::new(1, 1);
59 let id_with_different_client_2 = Id::new(2, 1);
60
61 assert_ne!(id_with_different_client_1, id_with_different_client_2);
62 assert_eq!(Id::new(1, 1), Id::new(1, 1));
63
64 let clock = 2;
65 assert_eq!(Id::new(1, 1) + clock, (1, 3).into());
66 assert_eq!(Id::new(1, 3) - clock, (1, 1).into());
67 }
68}