Skip to content

Commit dcbb337

Browse files
committed
Add start and all_ranges_in to BlockRange
1 parent 61c817f commit dcbb337

File tree

1 file changed

+79
-4
lines changed

1 file changed

+79
-4
lines changed

mithril-common/src/entities/block_range.rs

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
33
use std::{
44
cmp::Ordering,
55
fmt::{Display, Formatter, Result},
6-
ops::{Deref, Range},
6+
ops::{Deref, Range, RangeInclusive},
77
};
88

99
use crate::{
@@ -53,6 +53,21 @@ impl BlockRange {
5353
}
5454
}
5555

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+
5671
/// Create a BlockRange from a block number
5772
pub fn from_block_number(number: BlockNumber) -> Self {
5873
// Unwrap is safe as the length is always strictly greater than 0
@@ -69,14 +84,19 @@ impl BlockRange {
6984
"BlockRange cannot be be computed with a length of 0"
7085
));
7186
}
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);
7588
let block_range_end = block_range_start + length;
7689
Ok(Self {
7790
inner_range: block_range_start..block_range_end,
7891
})
7992
}
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+
}
80100
}
81101

82102
impl Display for BlockRange {
@@ -131,8 +151,23 @@ impl MKMapKey for BlockRange {}
131151

132152
#[cfg(test)]
133153
mod tests {
154+
use std::ops::Not;
155+
134156
use super::*;
135157

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+
136171
#[test]
137172
fn test_block_range_cmp() {
138173
assert_eq!(BlockRange::new(1, 10), BlockRange::new(1, 10));
@@ -167,6 +202,46 @@ mod tests {
167202
);
168203
}
169204

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+
170245
#[test]
171246
fn test_block_range_from_number() {
172247
assert_eq!(BlockRange::from_block_number(0), BlockRange::new(0, 15));

0 commit comments

Comments
 (0)