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 cfg_test_tools! {
39 pub fn dummy() -> Self {
41 Self {
42 slot_number: SlotNumber(100),
43 block_number: BlockNumber(0),
44 block_hash: "block_hash-50".to_string(),
45 }
46 }
47 }
48}
49
50impl Display for ChainPoint {
51 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
52 write!(
53 f,
54 "ChainPoint (slot_number: {}, block_number: {}, block_hash: {})",
55 self.slot_number, self.block_number, self.block_hash
56 )
57 }
58}
59
60impl PartialOrd for ChainPoint {
61 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
62 Some(self.cmp(other))
63 }
64}
65
66impl Ord for ChainPoint {
67 fn cmp(&self, other: &Self) -> Ordering {
68 self.block_number
69 .cmp(&other.block_number)
70 .then(self.slot_number.cmp(&other.slot_number))
71 .then(self.block_hash.cmp(&other.block_hash))
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use std::cmp::Ordering;
78
79 use super::*;
80
81 #[test]
82 fn chain_point_ord_cmp_block_number_take_precedence_over_other_fields() {
83 let chain_point1 = ChainPoint {
84 slot_number: SlotNumber(15),
85 block_number: BlockNumber(10),
86 block_hash: "hash2".to_string(),
87 };
88 let chain_point2 = ChainPoint {
89 slot_number: SlotNumber(5),
90 block_number: BlockNumber(20),
91 block_hash: "hash1".to_string(),
92 };
93
94 assert_eq!(Ordering::Less, chain_point1.cmp(&chain_point2));
95 }
96
97 #[test]
98 fn chain_point_ord_cmp_if_block_number_equals_then_compare_slot_numbers() {
99 let chain_point1 = ChainPoint {
100 slot_number: SlotNumber(15),
101 block_number: BlockNumber(0),
102 block_hash: "hash2".to_string(),
103 };
104 let chain_point2 = ChainPoint {
105 slot_number: SlotNumber(5),
106 block_number: BlockNumber(0),
107 block_hash: "hash1".to_string(),
108 };
109
110 assert_eq!(Ordering::Greater, chain_point1.cmp(&chain_point2));
111 }
112
113 #[test]
114 fn chain_point_ord_cmp_if_block_number_and_slot_number_equals_then_compare_block_hash() {
115 let chain_point1 = ChainPoint {
116 slot_number: SlotNumber(5),
117 block_number: BlockNumber(10),
118 block_hash: "hash1".to_string(),
119 };
120 let chain_point2 = ChainPoint {
121 slot_number: SlotNumber(5),
122 block_number: BlockNumber(10),
123 block_hash: "hash2".to_string(),
124 };
125
126 assert_eq!(Ordering::Less, chain_point1.cmp(&chain_point2));
127 }
128}