Skip to main content

mithril_common/entities/
block_number_offset.rs

1use std::{
2    fmt::{Display, Formatter},
3    num::TryFromIntError,
4    ops::{Deref, DerefMut},
5};
6
7use serde::{Deserialize, Serialize};
8
9use crate::entities::{
10    BlockNumber,
11    arithmetic_operation_wrapper::{
12        impl_add_to_wrapper, impl_partial_eq_to_wrapper, impl_sub_to_wrapper,
13    },
14};
15
16/// BlockNumberOffset represents the offset of a block number
17#[derive(
18    Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash,
19)]
20pub struct BlockNumberOffset(pub u64);
21
22impl Display for BlockNumberOffset {
23    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
24        write!(f, "{}", self.0)
25    }
26}
27
28impl Deref for BlockNumberOffset {
29    type Target = u64;
30
31    fn deref(&self) -> &Self::Target {
32        &self.0
33    }
34}
35
36impl DerefMut for BlockNumberOffset {
37    fn deref_mut(&mut self) -> &mut Self::Target {
38        &mut self.0
39    }
40}
41
42impl TryFrom<i64> for BlockNumberOffset {
43    type Error = TryFromIntError;
44
45    fn try_from(value: i64) -> Result<Self, Self::Error> {
46        Ok(BlockNumberOffset(u64::try_from(value)?))
47    }
48}
49
50impl TryFrom<BlockNumberOffset> for i64 {
51    type Error = TryFromIntError;
52
53    fn try_from(value: BlockNumberOffset) -> Result<Self, Self::Error> {
54        value.0.try_into()
55    }
56}
57
58impl_add_to_wrapper!(BlockNumberOffset, u64);
59impl_sub_to_wrapper!(BlockNumberOffset, u64);
60impl_partial_eq_to_wrapper!(BlockNumberOffset, u64);
61
62impl Add<BlockNumber> for BlockNumberOffset {
63    type Output = Self;
64
65    fn add(self, rhs: BlockNumber) -> Self::Output {
66        self + *rhs
67    }
68}
69
70impl Sub<BlockNumber> for BlockNumberOffset {
71    type Output = Self;
72
73    fn sub(self, rhs: BlockNumber) -> Self::Output {
74        self - *rhs
75    }
76}
77
78impl AddAssign<BlockNumber> for BlockNumberOffset {
79    fn add_assign(&mut self, rhs: BlockNumber) {
80        *self = *self + rhs;
81    }
82}
83
84impl From<BlockNumber> for BlockNumberOffset {
85    fn from(value: BlockNumber) -> Self {
86        BlockNumberOffset(value.0)
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use crate::entities::arithmetic_operation_wrapper::tests::test_op_assign;
93
94    use super::*;
95
96    #[test]
97    fn test_display() {
98        assert_eq!(format!("{}", BlockNumberOffset(72)), "72");
99        assert_eq!(format!("{}", &BlockNumberOffset(13224)), "13224");
100    }
101
102    #[test]
103    fn test_serialize() {
104        assert_eq!(serde_json::to_string(&BlockNumberOffset(72)).unwrap(), "72");
105    }
106
107    #[test]
108    fn test_deserialize() {
109        let kes_period: BlockNumberOffset = serde_json::from_str("13224").unwrap();
110        assert_eq!(kes_period, BlockNumberOffset(13224));
111    }
112
113    #[test]
114    #[allow(clippy::op_ref)]
115    fn test_add() {
116        assert_eq!(
117            BlockNumberOffset(4),
118            BlockNumberOffset(1) + BlockNumberOffset(3)
119        );
120        assert_eq!(BlockNumberOffset(4), BlockNumberOffset(1) + 3_u64);
121        assert_eq!(BlockNumberOffset(4), BlockNumberOffset(1) + &3_u64);
122
123        assert_eq!(BlockNumberOffset(4), 3_u64 + BlockNumberOffset(1));
124        assert_eq!(BlockNumberOffset(4), 3_u64 + &BlockNumberOffset(1));
125        assert_eq!(BlockNumberOffset(4), &3_u64 + BlockNumberOffset(1));
126        assert_eq!(BlockNumberOffset(4), &3_u64 + &BlockNumberOffset(1));
127
128        test_op_assign!(BlockNumberOffset(1), +=, BlockNumberOffset(3) => BlockNumberOffset(4));
129        test_op_assign!(BlockNumberOffset(1), +=, 3_u64 => BlockNumberOffset(4));
130        test_op_assign!(BlockNumberOffset(1), +=, &3_u64 => BlockNumberOffset(4));
131
132        test_op_assign!(1_u64, +=, BlockNumberOffset(3) => 4_u64);
133        test_op_assign!(1_u64, +=, &BlockNumberOffset(3) => 4_u64);
134    }
135
136    #[test]
137    #[allow(clippy::op_ref)]
138    fn test_sub() {
139        assert_eq!(
140            BlockNumberOffset(8),
141            BlockNumberOffset(14) - BlockNumberOffset(6)
142        );
143        assert_eq!(BlockNumberOffset(8), BlockNumberOffset(14) - 6_u64);
144        assert_eq!(BlockNumberOffset(8), BlockNumberOffset(14) - &6_u64);
145
146        assert_eq!(BlockNumberOffset(8), 6_u64 - BlockNumberOffset(14));
147        assert_eq!(BlockNumberOffset(8), 6_u64 - &BlockNumberOffset(14));
148        assert_eq!(BlockNumberOffset(8), &6_u64 - BlockNumberOffset(14));
149        assert_eq!(BlockNumberOffset(8), &6_u64 - &BlockNumberOffset(14));
150
151        test_op_assign!(BlockNumberOffset(14), -=, BlockNumberOffset(6) => BlockNumberOffset(8));
152        test_op_assign!(BlockNumberOffset(14), -=, 6_u64 => BlockNumberOffset(8));
153        test_op_assign!(BlockNumberOffset(14), -=, &6_u64 => BlockNumberOffset(8));
154
155        test_op_assign!(14_u64, -=, BlockNumberOffset(6) => 8_u64);
156        test_op_assign!(14_u64, -=, &BlockNumberOffset(6) => 8_u64);
157    }
158
159    #[test]
160    fn saturating_sub() {
161        assert_eq!(
162            BlockNumberOffset(0),
163            BlockNumberOffset(1) - BlockNumberOffset(5)
164        );
165        assert_eq!(BlockNumberOffset(0), BlockNumberOffset(1) - 5_u64);
166    }
167
168    #[test]
169    fn test_eq() {
170        assert_eq!(BlockNumberOffset(1), BlockNumberOffset(1));
171        assert_eq!(BlockNumberOffset(2), &BlockNumberOffset(2));
172        assert_eq!(&BlockNumberOffset(3), BlockNumberOffset(3));
173        assert_eq!(&BlockNumberOffset(4), &BlockNumberOffset(4));
174
175        assert_eq!(BlockNumberOffset(5), 5);
176        assert_eq!(BlockNumberOffset(6), &6);
177        assert_eq!(&BlockNumberOffset(7), 7);
178        assert_eq!(&BlockNumberOffset(8), &8);
179
180        assert_eq!(9, BlockNumberOffset(9));
181        assert_eq!(10, &BlockNumberOffset(10));
182        assert_eq!(&11, BlockNumberOffset(11));
183        assert_eq!(&12, &BlockNumberOffset(12));
184    }
185
186    #[test]
187    fn test_add_asign_block_number() {
188        test_op_assign!(BlockNumberOffset(1), +=, 3 => BlockNumberOffset(4));
189        test_op_assign!(BlockNumberOffset(1), +=, &3 => BlockNumberOffset(4));
190    }
191
192    #[test]
193    fn test_add_block_number_to_block_number_offset() {
194        assert_eq!(BlockNumberOffset(4), BlockNumberOffset(1) + BlockNumber(3));
195    }
196
197    #[test]
198    fn test_sub_block_number_to_block_number_offset() {
199        assert_eq!(BlockNumberOffset(3), BlockNumberOffset(4) - BlockNumber(1));
200    }
201
202    #[test]
203    fn test_from_block_number() {
204        let block_number = BlockNumber(42);
205        let block_number_offset: BlockNumberOffset = block_number.into();
206        assert_eq!(block_number_offset, BlockNumberOffset(42));
207    }
208}