linearize/
variants.rs

1#[allow(unused_imports)]
2use crate::LinearizeExt;
3use {
4    crate::Linearize,
5    core::{marker::PhantomData, ops::Range},
6};
7
8/// An iterator over all values of `L`.
9///
10/// Construct it with [`L::variants`][LinearizeExt::variants].
11pub struct Variants<L> {
12    iter: Range<usize>,
13    _phantom: PhantomData<fn() -> L>,
14}
15
16impl<L> Variants<L>
17where
18    L: Linearize,
19{
20    pub(super) fn new() -> Self {
21        Self {
22            iter: 0..L::LENGTH,
23            _phantom: Default::default(),
24        }
25    }
26}
27
28impl<L> Clone for Variants<L>
29where
30    L: Linearize,
31{
32    fn clone(&self) -> Self {
33        Self {
34            iter: self.iter.clone(),
35            _phantom: Default::default(),
36        }
37    }
38}
39
40impl<L> Iterator for Variants<L>
41where
42    L: Linearize,
43{
44    type Item = L;
45
46    fn next(&mut self) -> Option<Self::Item> {
47        self.iter.next().map(|v| unsafe {
48            // SAFETY: self.iter only returns values in 0..L::LENGTH
49            L::from_linear_unchecked(v)
50        })
51    }
52
53    fn size_hint(&self) -> (usize, Option<usize>) {
54        self.iter.size_hint()
55    }
56
57    fn count(self) -> usize
58    where
59        Self: Sized,
60    {
61        self.iter.count()
62    }
63
64    fn last(self) -> Option<Self::Item>
65    where
66        Self: Sized,
67    {
68        self.iter.last().map(|v| unsafe {
69            // SAFETY: self.iter only returns values in 0..L::LENGTH
70            L::from_linear_unchecked(v)
71        })
72    }
73
74    fn nth(&mut self, n: usize) -> Option<Self::Item> {
75        self.iter.nth(n).map(|v| unsafe {
76            // SAFETY: self.iter only returns values in 0..L::LENGTH
77            L::from_linear_unchecked(v)
78        })
79    }
80}
81
82impl<L> ExactSizeIterator for Variants<L> where L: Linearize {}
83
84impl<L> DoubleEndedIterator for Variants<L>
85where
86    L: Linearize,
87{
88    fn next_back(&mut self) -> Option<Self::Item> {
89        self.iter.next_back().map(|v| unsafe {
90            // SAFETY: self.iter only returns values in 0..L::LENGTH
91            L::from_linear_unchecked(v)
92        })
93    }
94
95    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
96        self.iter.nth_back(n).map(|v| unsafe {
97            // SAFETY: self.iter only returns values in 0..L::LENGTH
98            L::from_linear_unchecked(v)
99        })
100    }
101}