mithril_common/entities/
time_point.rs

1use std::cmp::Ordering;
2use std::fmt::{Display, Formatter};
3
4use crate::entities::{ChainPoint, Epoch, ImmutableFileNumber};
5
6/// TimePoint aggregates all types of point in the Cardano chain and is used by the state machines
7/// for their computations.
8#[derive(Clone, Debug, PartialEq, Eq)]
9pub struct TimePoint {
10    /// Cardano chain epoch number
11    pub epoch: Epoch,
12
13    /// Number of the last immutable files used for the digest computation
14    pub immutable_file_number: ImmutableFileNumber,
15
16    /// Chain point
17    pub chain_point: ChainPoint,
18}
19
20impl TimePoint {
21    /// [TimePoint] factory
22    pub fn new(
23        epoch: u64,
24        immutable_file_number: ImmutableFileNumber,
25        chain_point: ChainPoint,
26    ) -> TimePoint {
27        TimePoint {
28            epoch: Epoch(epoch),
29            immutable_file_number,
30            chain_point,
31        }
32    }
33}
34
35impl PartialOrd for TimePoint {
36    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
37        Some(self.cmp(other))
38    }
39}
40
41impl Ord for TimePoint {
42    fn cmp(&self, other: &Self) -> Ordering {
43        self.epoch
44            .cmp(&other.epoch)
45            .then(self.immutable_file_number.cmp(&other.immutable_file_number))
46            .then(self.chain_point.cmp(&other.chain_point))
47    }
48}
49
50impl Display for TimePoint {
51    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
52        write!(
53            f,
54            "TimePoint (epoch: {}, immutable_file_number: {}, chain_point: {})",
55            self.epoch, self.immutable_file_number, self.chain_point
56        )
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use std::cmp::Ordering;
63
64    use crate::entities::{BlockNumber, SlotNumber};
65
66    use super::*;
67
68    #[test]
69    fn time_point_ord_cmp_epochs_take_precedence_over_other_fields() {
70        let time_point1 = TimePoint {
71            epoch: Epoch(5),
72            immutable_file_number: 0,
73            chain_point: ChainPoint {
74                slot_number: SlotNumber(10),
75                block_number: BlockNumber(20),
76                block_hash: "hash1".to_string(),
77            },
78        };
79        let time_point2 = TimePoint {
80            epoch: Epoch(0),
81            immutable_file_number: 1,
82            chain_point: ChainPoint {
83                slot_number: SlotNumber(15),
84                block_number: BlockNumber(25),
85                block_hash: "hash2".to_string(),
86            },
87        };
88
89        assert_eq!(Ordering::Greater, time_point1.cmp(&time_point2));
90    }
91
92    #[test]
93    fn time_point_ord_cmp_if_epoch_equals_then_immutable_take_precedence_over_chain_point() {
94        let time_point1 = TimePoint {
95            epoch: Epoch(0),
96            immutable_file_number: 5,
97            chain_point: ChainPoint {
98                slot_number: SlotNumber(10),
99                block_number: BlockNumber(20),
100                block_hash: "hash1".to_string(),
101            },
102        };
103        let time_point2 = TimePoint {
104            epoch: Epoch(0),
105            immutable_file_number: 0,
106            chain_point: ChainPoint {
107                slot_number: SlotNumber(15),
108                block_number: BlockNumber(25),
109                block_hash: "hash2".to_string(),
110            },
111        };
112
113        assert_eq!(Ordering::Greater, time_point1.cmp(&time_point2));
114    }
115
116    #[test]
117    fn time_point_ord_cmp_if_epoch_and_immutables_equals_then_compare_over_chain_points() {
118        let time_point1 = TimePoint {
119            epoch: Epoch(0),
120            immutable_file_number: 0,
121            chain_point: ChainPoint {
122                slot_number: SlotNumber(10),
123                block_number: BlockNumber(20),
124                block_hash: "hash1".to_string(),
125            },
126        };
127        let time_point2 = TimePoint {
128            epoch: Epoch(0),
129            immutable_file_number: 0,
130            chain_point: ChainPoint {
131                slot_number: SlotNumber(15),
132                block_number: BlockNumber(25),
133                block_hash: "hash2".to_string(),
134            },
135        };
136
137        assert_eq!(Ordering::Less, time_point1.cmp(&time_point2));
138    }
139}