open_pql/base/
hand_iter.rs1use super::{Card, HandN};
2
3#[derive(Debug, Clone)]
19pub struct HandIter<const SD: bool, const N: usize> {
20 indices: [u8; N],
21 done: bool,
22}
23
24impl<const SD: bool, const N: usize> HandIter<SD, N> {
25 const fn all_cards() -> &'static [Card] {
30 if SD {
31 Card::ARR_ALL_SHORT.as_slice()
32 } else {
33 Card::ARR_ALL.as_slice()
34 }
35 }
36}
37
38#[allow(clippy::cast_possible_truncation)]
39impl<const SD: bool, const N: usize> Default for HandIter<SD, N> {
40 fn default() -> Self {
42 let mut indices = [0; N];
43 for i in 0..N as u8 {
44 indices[i as usize] = i;
45 }
46 Self {
47 indices,
48 done: N == 0,
49 }
50 }
51}
52
53impl<const SD: bool, const N: usize> Iterator for HandIter<SD, N> {
54 type Item = HandN<N>;
55
56 fn next(&mut self) -> Option<Self::Item> {
62 if self.done {
63 return None;
64 }
65
66 let all = Self::all_cards();
67 let max_i = all.len();
68
69 let mut cards = [Card::default(); N];
70 for i in 0..N {
71 cards[i] = all[self.indices[i] as usize];
72 }
73
74 let mut pos = N - 1;
75 self.indices[pos] += 1;
76
77 while self.indices[pos] as usize >= max_i - (N - 1 - pos) {
78 if pos == 0 {
79 self.done = true;
80 return Some(HandN::new(cards));
81 }
82
83 pos -= 1;
84 self.indices[pos] += 1;
85 }
86
87 for i in (pos + 1)..N {
88 self.indices[i] = self.indices[i - 1] + 1;
89 }
90
91 Some(HandN::new(cards))
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use crate::*;
99
100 #[test]
102 fn test_hand_iter_empty() {
103 let mut iter = HandIter::<false, 0>::default();
104 assert!(
105 iter.next().is_none(),
106 "Empty hand iterator should return None"
107 );
108 }
109
110 #[test]
111 fn test_hand_iter_single_card() {
112 let mut iter = HandN::<1>::iter_all();
113
114 for i in 0..Card::ARR_ALL.len() {
115 assert_eq!(iter.next(), Some([Card::ARR_ALL[i]].into()));
116 }
117 assert_eq!(iter.next(), None);
118 }
119
120 #[test]
121 fn test_hand_iter_shortdeck() {
122 let iter = HandN::<2>::iter_all_short();
123
124 let expected = 36 * 35 / 2;
125 assert_eq!(iter.count(), expected);
126 }
127}