@@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
3
3
use std:: {
4
4
cmp:: Ordering ,
5
5
fmt:: { Display , Formatter , Result } ,
6
- ops:: { Deref , Range } ,
6
+ ops:: { Deref , Range , RangeInclusive } ,
7
7
} ;
8
8
9
9
use crate :: {
@@ -53,6 +53,21 @@ impl BlockRange {
53
53
}
54
54
}
55
55
56
+ /// Get the start of the block range that contains the given block number
57
+ pub fn start ( number : BlockNumber ) -> BlockNumber {
58
+ Self :: start_with_length ( number, Self :: LENGTH )
59
+ }
60
+
61
+ /// Get all [BlockRange] contained in the given interval
62
+ pub fn all_ranges_in ( interval : RangeInclusive < BlockNumber > ) -> Vec < BlockRange > {
63
+ let all_numbers: Vec < BlockNumber > =
64
+ interval. skip_while ( |i| i % Self :: LENGTH != 0 ) . collect ( ) ;
65
+ all_numbers
66
+ . chunks_exact ( Self :: LENGTH as usize )
67
+ . map ( |chunk| Self :: from_block_number ( chunk[ 0 ] ) )
68
+ . collect ( )
69
+ }
70
+
56
71
/// Create a BlockRange from a block number
57
72
pub fn from_block_number ( number : BlockNumber ) -> Self {
58
73
// Unwrap is safe as the length is always strictly greater than 0
@@ -69,14 +84,19 @@ impl BlockRange {
69
84
"BlockRange cannot be be computed with a length of 0"
70
85
) ) ;
71
86
}
72
- // The formula used to compute the lower bound of the block range is `⌊number / length⌋ * length`
73
- // The computation of the floor is done with the integer division `/` of Rust
74
- let block_range_start = ( number / length) * length;
87
+ let block_range_start = Self :: start_with_length ( number, length) ;
75
88
let block_range_end = block_range_start + length;
76
89
Ok ( Self {
77
90
inner_range : block_range_start..block_range_end,
78
91
} )
79
92
}
93
+
94
+ /// Get the start of the block range of given length that contains the given block number
95
+ fn start_with_length ( number : BlockNumber , length : BlockRangeLength ) -> BlockNumber {
96
+ // the formula used to compute the lower bound of the block range is `⌊number / length⌋ * length`
97
+ // the computation of the floor is done with the integer division `/` of rust
98
+ ( number / length) * length
99
+ }
80
100
}
81
101
82
102
impl Display for BlockRange {
@@ -131,8 +151,23 @@ impl MKMapKey for BlockRange {}
131
151
132
152
#[ cfg( test) ]
133
153
mod tests {
154
+ use std:: ops:: Not ;
155
+
134
156
use super :: * ;
135
157
158
+ #[ test]
159
+ fn test_block_range_contains ( ) {
160
+ let block_range = BlockRange :: new ( 1 , 10 ) ;
161
+
162
+ assert ! ( block_range. contains( & 1 ) ) ;
163
+ assert ! ( block_range. contains( & 6 ) ) ;
164
+ assert ! ( block_range. contains( & 9 ) ) ;
165
+
166
+ assert ! ( block_range. contains( & 0 ) . not( ) ) ;
167
+ // The end of the range is exclusive
168
+ assert ! ( block_range. contains( & 10 ) . not( ) ) ;
169
+ }
170
+
136
171
#[ test]
137
172
fn test_block_range_cmp ( ) {
138
173
assert_eq ! ( BlockRange :: new( 1 , 10 ) , BlockRange :: new( 1 , 10 ) ) ;
@@ -167,6 +202,46 @@ mod tests {
167
202
) ;
168
203
}
169
204
205
+ #[ test]
206
+ fn test_block_range_start ( ) {
207
+ assert_eq ! ( BlockRange :: start( 0 ) , 0 ) ;
208
+ assert_eq ! ( BlockRange :: start( 1 ) , 0 ) ;
209
+ assert_eq ! ( BlockRange :: start( 14 ) , 0 ) ;
210
+ assert_eq ! ( BlockRange :: start( 15 ) , 15 ) ;
211
+ assert_eq ! ( BlockRange :: start( 16 ) , 15 ) ;
212
+ assert_eq ! ( BlockRange :: start( 29 ) , 15 ) ;
213
+ }
214
+
215
+ #[ test]
216
+ fn test_block_range_all_ranges_in ( ) {
217
+ assert_eq ! ( BlockRange :: all_ranges_in( 0 ..=0 ) , vec![ ] ) ;
218
+ assert_eq ! ( BlockRange :: all_ranges_in( 1 ..=16 ) , vec![ ] ) ;
219
+ assert_eq ! (
220
+ BlockRange :: all_ranges_in( 0 ..=15 ) ,
221
+ vec![ BlockRange :: new( 0 , 15 ) ]
222
+ ) ;
223
+ assert_eq ! (
224
+ BlockRange :: all_ranges_in( 0 ..=16 ) ,
225
+ vec![ BlockRange :: new( 0 , 15 ) ]
226
+ ) ;
227
+ assert_eq ! (
228
+ BlockRange :: all_ranges_in( 14 ..=29 ) ,
229
+ vec![ BlockRange :: new( 15 , 30 ) ]
230
+ ) ;
231
+ assert_eq ! (
232
+ BlockRange :: all_ranges_in( 14 ..=30 ) ,
233
+ vec![ BlockRange :: new( 15 , 30 ) ]
234
+ ) ;
235
+ assert_eq ! (
236
+ BlockRange :: all_ranges_in( 14 ..=61 ) ,
237
+ vec![
238
+ BlockRange :: new( 15 , 30 ) ,
239
+ BlockRange :: new( 30 , 45 ) ,
240
+ BlockRange :: new( 45 , 60 )
241
+ ]
242
+ ) ;
243
+ }
244
+
170
245
#[ test]
171
246
fn test_block_range_from_number ( ) {
172
247
assert_eq ! ( BlockRange :: from_block_number( 0 ) , BlockRange :: new( 0 , 15 ) ) ;
0 commit comments