@@ -59,13 +59,8 @@ impl BlockRange {
5959 }
6060
6161 /// Get all [BlockRange] strictly contained in the given interval
62- pub fn all_block_ranges_in ( interval : Range < 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 ( )
62+ pub fn all_block_ranges_in ( interval : Range < BlockNumber > ) -> BlockRangesSequence {
63+ BlockRangesSequence :: new ( interval)
6964 }
7065
7166 /// Create a BlockRange from a block number
@@ -149,6 +144,76 @@ impl From<BlockRange> for MKTreeNode {
149144
150145impl MKMapKey for BlockRange { }
151146
147+ /// A continuous iterable sequence of [block ranges][BlockRange].
148+ ///
149+ /// Yielded block ranges are sized by [BlockRange::LENGTH], and always have
150+ /// bounds that are multiples of [BlockRange::LENGTH].
151+ #[ derive( Debug , Clone , Eq , PartialEq ) ]
152+ pub struct BlockRangesSequence {
153+ start : BlockNumber ,
154+ end : BlockNumber ,
155+ }
156+
157+ impl BlockRangesSequence {
158+ /// Build the [BlockRangesSequence] strictly contained in the given interval.
159+ ///
160+ /// The interval bounds will be corrected to be multiples of [BlockRange::LENGTH].
161+ pub fn new ( interval : Range < BlockNumber > ) -> Self {
162+ let start = if ( interval. start % BlockRange :: LENGTH ) == 0 {
163+ interval. start
164+ } else {
165+ BlockRange :: start ( interval. start ) + BlockRange :: LENGTH
166+ } ;
167+ let end = BlockRange :: start ( interval. end ) ;
168+
169+ Self { start, end }
170+ }
171+
172+ /// Returns the start of the block ranges sequence.
173+ pub fn start ( & self ) -> BlockNumber {
174+ self . start
175+ }
176+
177+ /// Returns the end of the block ranges sequence.
178+ pub fn end ( & self ) -> BlockNumber {
179+ self . end
180+ }
181+
182+ /// Returns `true` if the block ranges sequence contains no elements.
183+ pub fn is_empty ( & self ) -> bool {
184+ self . len ( ) == 0
185+ }
186+
187+ /// Consume `self` into a new Vec
188+ pub fn into_vec ( self ) -> Vec < BlockRange > {
189+ self . into_iter ( ) . collect ( )
190+ }
191+ }
192+
193+ impl Iterator for BlockRangesSequence {
194+ type Item = BlockRange ;
195+
196+ fn next ( & mut self ) -> Option < Self :: Item > {
197+ if self . start >= self . end {
198+ return None ;
199+ }
200+
201+ let block_range = BlockRange :: from_block_number ( self . start ) ;
202+ self . start = block_range. end ;
203+ Some ( block_range)
204+ }
205+
206+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
207+ ( self . start as usize , Some ( self . end as usize ) )
208+ }
209+ }
210+
211+ impl ExactSizeIterator for BlockRangesSequence {
212+ fn len ( & self ) -> usize {
213+ ( ( self . end - self . start ) / BlockRange :: LENGTH ) as usize
214+ }
215+ }
216+
152217#[ cfg( test) ]
153218mod tests {
154219 use std:: ops:: Not ;
@@ -214,28 +279,28 @@ mod tests {
214279
215280 #[ test]
216281 fn test_block_range_all_block_ranges_in ( ) {
217- assert_eq ! ( BlockRange :: all_block_ranges_in( 0 ..0 ) , vec![ ] ) ;
218- assert_eq ! ( BlockRange :: all_block_ranges_in( 0 ..1 ) , vec![ ] ) ;
219- assert_eq ! ( BlockRange :: all_block_ranges_in( 0 ..14 ) , vec![ ] ) ;
220- assert_eq ! ( BlockRange :: all_block_ranges_in( 1 ..15 ) , vec![ ] ) ;
282+ assert_eq ! ( BlockRange :: all_block_ranges_in( 0 ..0 ) . into_vec ( ) , vec![ ] ) ;
283+ assert_eq ! ( BlockRange :: all_block_ranges_in( 0 ..1 ) . into_vec ( ) , vec![ ] ) ;
284+ assert_eq ! ( BlockRange :: all_block_ranges_in( 0 ..14 ) . into_vec ( ) , vec![ ] ) ;
285+ assert_eq ! ( BlockRange :: all_block_ranges_in( 1 ..15 ) . into_vec ( ) , vec![ ] ) ;
221286 assert_eq ! (
222- BlockRange :: all_block_ranges_in( 0 ..15 ) ,
287+ BlockRange :: all_block_ranges_in( 0 ..15 ) . into_vec ( ) ,
223288 vec![ BlockRange :: new( 0 , 15 ) ]
224289 ) ;
225290 assert_eq ! (
226- BlockRange :: all_block_ranges_in( 0 ..16 ) ,
291+ BlockRange :: all_block_ranges_in( 0 ..16 ) . into_vec ( ) ,
227292 vec![ BlockRange :: new( 0 , 15 ) ]
228293 ) ;
229294 assert_eq ! (
230- BlockRange :: all_block_ranges_in( 14 ..30 ) ,
295+ BlockRange :: all_block_ranges_in( 14 ..30 ) . into_vec ( ) ,
231296 vec![ BlockRange :: new( 15 , 30 ) ]
232297 ) ;
233298 assert_eq ! (
234- BlockRange :: all_block_ranges_in( 14 ..31 ) ,
299+ BlockRange :: all_block_ranges_in( 14 ..31 ) . into_vec ( ) ,
235300 vec![ BlockRange :: new( 15 , 30 ) ]
236301 ) ;
237302 assert_eq ! (
238- BlockRange :: all_block_ranges_in( 14 ..61 ) ,
303+ BlockRange :: all_block_ranges_in( 14 ..61 ) . into_vec ( ) ,
239304 vec![
240305 BlockRange :: new( 15 , 30 ) ,
241306 BlockRange :: new( 30 , 45 ) ,
@@ -244,6 +309,35 @@ mod tests {
244309 ) ;
245310 }
246311
312+ #[ test]
313+ fn test_block_ranges_sequence_is_empty ( ) {
314+ assert ! ( BlockRange :: all_block_ranges_in( 0 ..0 ) . is_empty( ) ) ;
315+ assert ! ( BlockRange :: all_block_ranges_in( 0 ..1 ) . is_empty( ) ) ;
316+ assert ! ( BlockRange :: all_block_ranges_in( 0 ..14 ) . is_empty( ) ) ;
317+ assert ! ( BlockRange :: all_block_ranges_in( 1 ..15 ) . is_empty( ) ) ;
318+ assert ! ( BlockRange :: all_block_ranges_in( 0 ..15 ) . is_empty( ) . not( ) ) ;
319+ assert ! ( BlockRange :: all_block_ranges_in( 0 ..16 ) . is_empty( ) . not( ) ) ;
320+ assert ! ( BlockRange :: all_block_ranges_in( 14 ..30 ) . is_empty( ) . not( ) ) ;
321+ assert ! ( BlockRange :: all_block_ranges_in( 14 ..31 ) . is_empty( ) . not( ) ) ;
322+ assert ! ( BlockRange :: all_block_ranges_in( 14 ..61 ) . is_empty( ) . not( ) ) ;
323+ }
324+
325+ #[ test]
326+ fn test_block_ranges_sequence_len ( ) {
327+ assert_eq ! (
328+ BlockRange :: all_block_ranges_in( 0 ..( BlockRange :: LENGTH - 1 ) ) . len( ) ,
329+ 0
330+ ) ;
331+ assert_eq ! (
332+ BlockRange :: all_block_ranges_in( 0 ..( BlockRange :: LENGTH ) ) . len( ) ,
333+ 1
334+ ) ;
335+ assert_eq ! (
336+ BlockRange :: all_block_ranges_in( 0 ..( BlockRange :: LENGTH * 15 ) ) . len( ) ,
337+ 15
338+ ) ;
339+ }
340+
247341 #[ test]
248342 fn test_block_range_from_number ( ) {
249343 assert_eq ! ( BlockRange :: from_block_number( 0 ) , BlockRange :: new( 0 , 15 ) ) ;
0 commit comments