y_octo/doc/codec/
id.rs

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}