fuchsia_hash/
iter.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::{Hash, HASH_SIZE};
6
7/// Iterator over all 2^256 possible hash values. Not expected to be useful outside of tests.
8#[derive(Debug)]
9pub struct HashRangeFull(Option<[u8; HASH_SIZE]>);
10
11impl Default for HashRangeFull {
12    fn default() -> Self {
13        Self(Some([0; HASH_SIZE]))
14    }
15}
16
17impl Iterator for HashRangeFull {
18    type Item = Hash;
19
20    fn next(&mut self) -> Option<Self::Item> {
21        fn inc(mut bignum: [u8; HASH_SIZE]) -> Option<[u8; HASH_SIZE]> {
22            let mut bytes = bignum.iter_mut().rev();
23            loop {
24                let n = bytes.next()?;
25                let (next, overflowed) = n.overflowing_add(1);
26                *n = next;
27                if !overflowed {
28                    break;
29                }
30            }
31            Some(bignum)
32        }
33
34        match self.0 {
35            Some(bytes) => {
36                let res = Hash::from(bytes);
37                self.0 = inc(bytes);
38                Some(res)
39            }
40            None => None,
41        }
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn hash_range_full() {
51        let mut iter = HashRangeFull::default();
52        assert_eq!(
53            iter.next(),
54            Some(Hash::from([
55                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56                0, 0, 0, 0
57            ]))
58        );
59        assert_eq!(
60            iter.next(),
61            Some(Hash::from([
62                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63                0, 0, 0, 1
64            ]))
65        );
66
67        assert_eq!(
68            HashRangeFull::default().nth(256),
69            Some(Hash::from([
70                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71                0, 0, 1, 0
72            ]))
73        );
74    }
75
76    #[test]
77    fn hash_range_full_ends() {
78        let mut iter = HashRangeFull(Some([255; HASH_SIZE]));
79        assert_eq!(iter.next(), Some(Hash::from([255; HASH_SIZE])));
80        assert_eq!(iter.next(), None);
81    }
82}