multiversx_sc/
non_zero_util.rs

1use core::{iter::Iterator, num::NonZeroUsize};
2
3/// This is safe because 1 != 0.
4#[inline]
5pub const fn non_zero_usize_one() -> NonZeroUsize {
6    unsafe { NonZeroUsize::new_unchecked(1) }
7}
8
9/// This is safe because adding 1 to a positive number makes it greater than one.
10#[inline]
11pub const fn non_zero_usize_from_n_plus_1(n: usize) -> NonZeroUsize {
12    unsafe { NonZeroUsize::new_unchecked(n + 1) }
13}
14
15/// This is safe because adding a non-zero number with a positive one yields a non-zero number.
16#[inline]
17pub const fn non_zero_usize_plus(a: NonZeroUsize, b: usize) -> NonZeroUsize {
18    unsafe { NonZeroUsize::new_unchecked(a.get() + b) }
19}
20
21/// Iterator that can give us a range of NonZeroUsize.
22pub struct NonZeroUsizeIterator {
23    prev_num: usize,
24    limit: usize,
25}
26
27impl NonZeroUsizeIterator {
28    /// Creates an Iterator that runs from 1 to n, inclusively.
29    /// The iterator will produce n numbers,
30    /// e.g. for 3 it will produce [1, 2, 3].
31    pub fn from_1_to_n(n: usize) -> Self {
32        NonZeroUsizeIterator {
33            prev_num: 0,
34            limit: n,
35        }
36    }
37}
38
39impl Iterator for NonZeroUsizeIterator {
40    type Item = NonZeroUsize;
41
42    fn next(&mut self) -> Option<NonZeroUsize> {
43        if self.prev_num >= self.limit {
44            return None;
45        }
46
47        self.prev_num += 1;
48        unsafe { Some(NonZeroUsize::new_unchecked(self.prev_num)) }
49    }
50}
51
52#[cfg(test)]
53pub mod tests {
54    use super::*;
55    use alloc::vec::Vec;
56
57    #[test]
58    fn test_iter_0() {
59        let mut v = Vec::<usize>::new();
60        for nz in NonZeroUsizeIterator::from_1_to_n(0) {
61            v.push(nz.get());
62        }
63
64        assert_eq!(v, [].to_vec());
65    }
66
67    #[test]
68    fn test_iter_1() {
69        let mut v = Vec::<usize>::new();
70        for nz in NonZeroUsizeIterator::from_1_to_n(1) {
71            v.push(nz.get());
72        }
73
74        assert_eq!(v, [1].to_vec());
75    }
76
77    #[test]
78    fn test_iter_3() {
79        let mut v = Vec::<usize>::new();
80        for nz in NonZeroUsizeIterator::from_1_to_n(3) {
81            v.push(nz.get());
82        }
83
84        assert_eq!(v, [1, 2, 3].to_vec());
85    }
86
87    const ONE: NonZeroUsize = non_zero_usize_one();
88    const TWO: NonZeroUsize = non_zero_usize_from_n_plus_1(1);
89    const TEN: NonZeroUsize = non_zero_usize_plus(ONE, 9);
90
91    #[test]
92    fn test_const() {
93        assert_eq!(ONE.get(), 1);
94        assert_eq!(TWO.get(), 2);
95        assert_eq!(TEN.get(), 10);
96    }
97}