open_pql/base/
hand_iter.rs

1use super::{Card, HandN};
2
3#[derive(Debug, Clone)]
4pub struct HandIter<const SD: bool, const N: usize> {
5    indices: [u8; N],
6    done: bool,
7}
8
9impl<const SD: bool, const N: usize> HandIter<SD, N> {
10    const fn all_cards() -> &'static [Card] {
11        if SD {
12            Card::ARR_ALL_SHORT.as_slice()
13        } else {
14            Card::ARR_ALL.as_slice()
15        }
16    }
17}
18
19#[allow(clippy::cast_possible_truncation)]
20impl<const SD: bool, const N: usize> Default for HandIter<SD, N> {
21    fn default() -> Self {
22        let mut indices = [0; N];
23        for i in 0..N as u8 {
24            indices[i as usize] = i;
25        }
26        Self {
27            indices,
28            done: N == 0,
29        }
30    }
31}
32
33impl<const SD: bool, const N: usize> Iterator for HandIter<SD, N> {
34    type Item = HandN<N>;
35
36    fn next(&mut self) -> Option<Self::Item> {
37        if self.done {
38            return None;
39        }
40
41        let all = Self::all_cards();
42        let max_i = all.len();
43
44        let mut cards = [Card::default(); N];
45        for i in 0..N {
46            cards[i] = all[self.indices[i] as usize];
47        }
48
49        let mut pos = N - 1;
50        self.indices[pos] += 1;
51
52        while self.indices[pos] as usize >= max_i - (N - 1 - pos) {
53            if pos == 0 {
54                self.done = true;
55                return Some(HandN::new(cards));
56            }
57
58            pos -= 1;
59            self.indices[pos] += 1;
60        }
61
62        for i in (pos + 1)..N {
63            self.indices[i] = self.indices[i - 1] + 1;
64        }
65
66        Some(HandN::new(cards))
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn test_hand_iter_empty() {
76        let mut iter = HandIter::<false, 0>::default();
77        assert!(
78            iter.next().is_none(),
79            "Empty hand iterator should return None"
80        );
81    }
82
83    #[test]
84    fn test_hand_iter_single_card() {
85        let mut iter = HandN::<1>::iter_all();
86
87        for i in 0..Card::ARR_ALL.len() {
88            assert_eq!(iter.next(), Some([Card::ARR_ALL[i]].into()));
89        }
90        assert_eq!(iter.next(), None);
91    }
92
93    #[test]
94    fn test_hand_iter_shortdeck() {
95        let iter = HandN::<2>::iter_all_short();
96
97        let expected = 36 * 35 / 2;
98        assert_eq!(iter.count(), expected);
99    }
100}