mithril_common/entities/
cardano_chain_point.rs1use std::cmp::Ordering;
2use std::fmt::{Display, Formatter};
3
4use serde::{Deserialize, Serialize};
5
6use crate::entities::{BlockNumber, SlotNumber};
7
8pub type BlockHash = String;
10
11#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
13pub struct ChainPoint {
14 pub slot_number: SlotNumber,
16
17 pub block_number: BlockNumber,
19
20 pub block_hash: BlockHash,
22}
23
24impl ChainPoint {
25 pub fn new<T: Into<BlockHash>>(
27 slot_number: SlotNumber,
28 block_number: BlockNumber,
29 block_hash: T,
30 ) -> ChainPoint {
31 ChainPoint {
32 slot_number,
33 block_number,
34 block_hash: block_hash.into(),
35 }
36 }
37}
38
39impl Display for ChainPoint {
40 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
41 write!(
42 f,
43 "ChainPoint (slot_number: {}, block_number: {}, block_hash: {})",
44 self.slot_number, self.block_number, self.block_hash
45 )
46 }
47}
48
49impl PartialOrd for ChainPoint {
50 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
51 Some(self.cmp(other))
52 }
53}
54
55impl Ord for ChainPoint {
56 fn cmp(&self, other: &Self) -> Ordering {
57 self.block_number
58 .cmp(&other.block_number)
59 .then(self.slot_number.cmp(&other.slot_number))
60 .then(self.block_hash.cmp(&other.block_hash))
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use std::cmp::Ordering;
67
68 use super::*;
69
70 #[test]
71 fn chain_point_ord_cmp_block_number_take_precedence_over_other_fields() {
72 let chain_point1 = ChainPoint {
73 slot_number: SlotNumber(15),
74 block_number: BlockNumber(10),
75 block_hash: "hash2".to_string(),
76 };
77 let chain_point2 = ChainPoint {
78 slot_number: SlotNumber(5),
79 block_number: BlockNumber(20),
80 block_hash: "hash1".to_string(),
81 };
82
83 assert_eq!(Ordering::Less, chain_point1.cmp(&chain_point2));
84 }
85
86 #[test]
87 fn chain_point_ord_cmp_if_block_number_equals_then_compare_slot_numbers() {
88 let chain_point1 = ChainPoint {
89 slot_number: SlotNumber(15),
90 block_number: BlockNumber(0),
91 block_hash: "hash2".to_string(),
92 };
93 let chain_point2 = ChainPoint {
94 slot_number: SlotNumber(5),
95 block_number: BlockNumber(0),
96 block_hash: "hash1".to_string(),
97 };
98
99 assert_eq!(Ordering::Greater, chain_point1.cmp(&chain_point2));
100 }
101
102 #[test]
103 fn chain_point_ord_cmp_if_block_number_and_slot_number_equals_then_compare_block_hash() {
104 let chain_point1 = ChainPoint {
105 slot_number: SlotNumber(5),
106 block_number: BlockNumber(10),
107 block_hash: "hash1".to_string(),
108 };
109 let chain_point2 = ChainPoint {
110 slot_number: SlotNumber(5),
111 block_number: BlockNumber(10),
112 block_hash: "hash2".to_string(),
113 };
114
115 assert_eq!(Ordering::Less, chain_point1.cmp(&chain_point2));
116 }
117}