count_enum/
iter.rs

1use crate::Enum;
2use core::iter::FusedIterator;
3
4/// 遍历值域,参见 [`IterEachFrom`]
5pub fn iter_each<T: Enum>() -> IterEachFrom<T> {
6    IterEachFrom(T::first())
7}
8
9/// 从某个值(包含)开始遍历值域,参见 [`IterEachFrom`]
10pub fn iter_each_from<T: Enum>(x: T) -> IterEachFrom<T> {
11    IterEachFrom(Some(x))
12}
13
14/// 遍历值域
15///
16/// 这是单向迭代器。
17/// 实现了 [`ExactSizeIterator`],但其实际长度有可能溢出。
18///
19/// 其内部迭代(如 `fold`、`for_each`)经过优化,性能更高,可代替 `for` 循环。
20///
21/// ```
22/// # use count_enum::{iter_each, iter_each_from};
23/// assert!(iter_each::<Result<_, _>>()
24///     .eq([Err(()), Ok(None), Ok(Some(()))]));
25/// assert!(iter_each_from((false, true))
26///     .eq([(false, true), (true, false), (true, true)]));
27/// ```
28///
29/// ```should_panic
30/// # use count_enum::iter_each;
31/// iter_each::<u128>().count(); // overflow
32/// ```
33#[must_use = "iterators are lazy and do nothing unless consumed"]
34#[derive(Debug, Clone)]
35pub struct IterEachFrom<T>(Option<T>);
36
37impl<T: Enum> Iterator for IterEachFrom<T> {
38    type Item = T;
39
40    #[inline]
41    fn next(&mut self) -> Option<Self::Item> {
42        let this = self.0.take()?;
43        self.0 = this.succ();
44        Some(this)
45    }
46
47    #[inline]
48    fn size_hint(&self) -> (usize, Option<usize>) {
49        let Some(this) = &self.0 else {
50            return (0, Some(0));
51        };
52        match T::count_from(this) {
53            Some(c) => (c.get(), Some(c.get())),
54            None => (usize::MAX, None),
55        }
56    }
57
58    #[inline]
59    fn count(self) -> usize
60    where
61        Self: Sized,
62    {
63        self.0.map_or(0, |this| {
64            T::count_from(&this).expect("count overflow").get()
65        })
66    }
67
68    #[inline]
69    fn last(self) -> Option<Self::Item> {
70        self.0?;
71        T::last()
72    }
73
74    fn fold<B, F>(self, init: B, f: F) -> B
75    where
76        F: FnMut(B, Self::Item) -> B,
77    {
78        match self.0 {
79            Some(this) => T::fold_each_from(&this, init, f),
80            None => init,
81        }
82    }
83}
84
85impl<T: Enum> FusedIterator for IterEachFrom<T> {}