nakamoto_common/block/iter.rs
1//! Double-ended iterator over a `NonEmpty` blockchain.
2use nonempty::NonEmpty;
3
4use super::Height;
5
6/// An iterator over a chain.
7#[derive(Debug)]
8pub struct Iter<'a, T> {
9 chain: &'a NonEmpty<T>,
10 next: usize,
11 next_back: usize,
12}
13
14impl<'a, T> Iter<'a, T> {
15 /// Create a new iterator.
16 pub fn new(chain: &'a NonEmpty<T>) -> Self {
17 Self {
18 chain,
19 next: 0,
20 next_back: chain.len(),
21 }
22 }
23}
24
25impl<'a, T> Iterator for Iter<'a, T> {
26 type Item = (Height, &'a T);
27
28 fn next(&mut self) -> Option<Self::Item> {
29 if self.next == self.next_back {
30 return None;
31 }
32 let height = self.next;
33 self.next += 1;
34
35 self.chain.get(height).map(|item| (height as Height, item))
36 }
37}
38
39impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
40 ///```
41 /// use nonempty::NonEmpty;
42 /// use nakamoto_common::block::iter::Iter;
43 ///
44 /// let chain = NonEmpty::from_vec(vec![1, 2, 3, 4, 5]).unwrap();
45 /// let mut iter = Iter::new(&chain);
46 ///
47 /// assert_eq!(Some((4, &5)), iter.next_back());
48 /// assert_eq!(Some((3, &4)), iter.next_back());
49 /// assert_eq!(Some((2, &3)), iter.next_back());
50 /// assert_eq!(Some((1, &2)), iter.next_back());
51 /// assert_eq!(Some((0, &1)), iter.next_back());
52 ///
53 /// let mut iter = Iter::new(&chain);
54 ///
55 /// assert_eq!(Some((4, &5)), iter.next_back());
56 /// assert_eq!(Some((0, &1)), iter.next());
57 /// assert_eq!(Some((3, &4)), iter.next_back());
58 /// assert_eq!(Some((1, &2)), iter.next());
59 /// assert_eq!(Some((2, &3)), iter.next_back());
60 /// assert_eq!(None, iter.next());
61 /// assert_eq!(None, iter.next_back());
62 ///```
63 fn next_back(&mut self) -> Option<Self::Item> {
64 if self.next_back == self.next {
65 return None;
66 }
67
68 self.next_back -= 1;
69 let height = self.next_back;
70
71 self.chain.get(height).map(|item| (height as Height, item))
72 }
73}