mithril_common/entities/
slot_number.rs

1use std::fmt::{Display, Formatter};
2use std::num::TryFromIntError;
3use std::ops::{Deref, DerefMut};
4
5use serde::{Deserialize, Serialize};
6
7use crate::entities::arithmetic_operation_wrapper::{
8    impl_add_to_wrapper, impl_partial_eq_to_wrapper, impl_sub_to_wrapper,
9};
10
11/// [Cardano Slot number](https://docs.cardano.org/learn/cardano-node/#slotsandepochs)
12#[derive(
13    Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash,
14)]
15pub struct SlotNumber(pub u64);
16
17impl Display for SlotNumber {
18    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
19        write!(f, "{}", self.0)
20    }
21}
22
23impl Deref for SlotNumber {
24    type Target = u64;
25
26    fn deref(&self) -> &Self::Target {
27        &self.0
28    }
29}
30
31impl DerefMut for SlotNumber {
32    fn deref_mut(&mut self) -> &mut Self::Target {
33        &mut self.0
34    }
35}
36
37// Useful for conversion to sqlite number (that use i64)
38impl TryFrom<SlotNumber> for i64 {
39    type Error = TryFromIntError;
40
41    fn try_from(value: SlotNumber) -> Result<Self, Self::Error> {
42        value.0.try_into()
43    }
44}
45
46impl_add_to_wrapper!(SlotNumber, u64);
47impl_sub_to_wrapper!(SlotNumber, u64);
48impl_partial_eq_to_wrapper!(SlotNumber, u64);
49
50#[cfg(test)]
51mod tests {
52    use crate::entities::arithmetic_operation_wrapper::tests::test_op_assign;
53
54    use super::*;
55
56    #[test]
57    fn test_display() {
58        assert_eq!(format!("{}", SlotNumber(72)), "72");
59        assert_eq!(format!("{}", &SlotNumber(13224)), "13224");
60    }
61
62    #[test]
63    fn test_serialize() {
64        assert_eq!(serde_json::to_string(&SlotNumber(72)).unwrap(), "72");
65    }
66
67    #[test]
68    fn test_deserialize() {
69        let slot_number: SlotNumber = serde_json::from_str("13224").unwrap();
70        assert_eq!(slot_number, SlotNumber(13224));
71    }
72
73    #[test]
74    #[allow(clippy::op_ref)]
75    fn test_add() {
76        assert_eq!(SlotNumber(4), SlotNumber(1) + SlotNumber(3));
77        assert_eq!(SlotNumber(4), SlotNumber(1) + 3_u64);
78        assert_eq!(SlotNumber(4), SlotNumber(1) + &3_u64);
79
80        assert_eq!(SlotNumber(4), 3_u64 + SlotNumber(1));
81        assert_eq!(SlotNumber(4), 3_u64 + &SlotNumber(1));
82        assert_eq!(SlotNumber(4), &3_u64 + SlotNumber(1));
83        assert_eq!(SlotNumber(4), &3_u64 + &SlotNumber(1));
84
85        test_op_assign!(SlotNumber(1), +=, SlotNumber(3) => SlotNumber(4));
86        test_op_assign!(SlotNumber(1), +=, 3_u64 => SlotNumber(4));
87        test_op_assign!(SlotNumber(1), +=, &3_u64 => SlotNumber(4));
88
89        test_op_assign!(1_u64, +=, SlotNumber(3) => 4_u64);
90        test_op_assign!(1_u64, +=, &SlotNumber(3) => 4_u64);
91    }
92
93    #[test]
94    #[allow(clippy::op_ref)]
95    fn test_sub() {
96        assert_eq!(SlotNumber(8), SlotNumber(14) - SlotNumber(6));
97        assert_eq!(SlotNumber(8), SlotNumber(14) - 6_u64);
98        assert_eq!(SlotNumber(8), SlotNumber(14) - &6_u64);
99
100        assert_eq!(SlotNumber(8), 6_u64 - SlotNumber(14));
101        assert_eq!(SlotNumber(8), 6_u64 - &SlotNumber(14));
102        assert_eq!(SlotNumber(8), &6_u64 - SlotNumber(14));
103        assert_eq!(SlotNumber(8), &6_u64 - &SlotNumber(14));
104
105        test_op_assign!(SlotNumber(14), -=, SlotNumber(6) => SlotNumber(8));
106        test_op_assign!(SlotNumber(14), -=, 6_u64 => SlotNumber(8));
107        test_op_assign!(SlotNumber(14), -=, &6_u64 => SlotNumber(8));
108
109        test_op_assign!(14_u64, -=, SlotNumber(6) => 8_u64);
110        test_op_assign!(14_u64, -=, &SlotNumber(6) => 8_u64);
111    }
112
113    #[test]
114    fn saturating_sub() {
115        assert_eq!(SlotNumber(0), SlotNumber(1) - SlotNumber(5));
116        assert_eq!(SlotNumber(0), SlotNumber(1) - 5_u64);
117    }
118
119    #[test]
120    fn test_eq() {
121        assert_eq!(SlotNumber(1), SlotNumber(1));
122        assert_eq!(SlotNumber(2), &SlotNumber(2));
123        assert_eq!(&SlotNumber(3), SlotNumber(3));
124        assert_eq!(&SlotNumber(4), &SlotNumber(4));
125
126        assert_eq!(SlotNumber(5), 5);
127        assert_eq!(SlotNumber(6), &6);
128        assert_eq!(&SlotNumber(7), 7);
129        assert_eq!(&SlotNumber(8), &8);
130
131        assert_eq!(9, SlotNumber(9));
132        assert_eq!(10, &SlotNumber(10));
133        assert_eq!(&11, SlotNumber(11));
134        assert_eq!(&12, &SlotNumber(12));
135    }
136
137    #[test]
138    fn test_try_into_i64() {
139        let slot_number = SlotNumber(42);
140        let number: i64 = slot_number.try_into().unwrap();
141        assert_eq!(42, number);
142    }
143}