1use super::{
2 Card, Card64, CardCount, From, HandIter, Hash, Index, Into, Rank, Vec, fmt,
3 iter, mem, slice,
4};
5
6#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, From, Into)]
26pub struct HandN<const N: usize>(pub(crate) [Card; N]);
27
28impl<const N: usize> HandN<N> {
29 pub(crate) fn new(array: [Card; N]) -> Self {
31 debug_assert!(
32 array.is_sorted(),
33 "Hand initialized from unsorted array {array:?}"
34 );
35 Self(array)
36 }
37
38 pub fn from_slice(cs: &[Card]) -> Self {
40 debug_assert!(
41 cs.len() >= N,
42 "from_slice: not enough cards for Hand<{}> slice has {} elements",
43 N,
44 cs.len()
45 );
46
47 let mut cards = [Card::default(); N];
48 cards.copy_from_slice(&cs[..N]);
49 cards.sort_unstable();
50
51 Self(cards)
52 }
53
54 pub const fn as_slice(&self) -> &[Card] {
56 &self.0
57 }
58
59 pub fn to_vec(&self) -> Vec<Card> {
60 self.0.to_vec()
61 }
62
63 pub fn iter(&self) -> impl Iterator<Item = Card> + '_ {
65 self.0.iter().copied()
66 }
67
68 pub const fn len(&self) -> usize {
70 N
71 }
72
73 pub const fn is_empty(&self) -> bool {
75 N == 0
76 }
77
78 pub fn iter_all_short() -> HandIter<true, N> {
79 HandIter::default()
80 }
81
82 pub fn iter_all() -> HandIter<false, N> {
83 HandIter::default()
84 }
85}
86
87#[allow(unused)]
88impl HandN<2> {
89 pub(crate) const fn to_u16(&self) -> u16 {
90 (self.0[0].to_u8() as u16) | (self.0[1].to_u8() as u16) << 8
91 }
92
93 pub(crate) fn from_u16(v: u16) -> Self {
94 let [c0, c1] = v.to_le_bytes();
95 Self::from_slice(&[Card::from_u8(c0), Card::from_u8(c1)])
96 }
97}
98
99impl HandN<3> {
100 pub(crate) fn count_by_rank(self, rank: Rank) -> CardCount {
101 CardCount::from(self[0].rank == rank)
102 + CardCount::from(self[1].rank == rank)
103 + CardCount::from(self[2].rank == rank)
104 }
105
106 pub(crate) fn sorted_ranks(self) -> (Rank, Rank, Rank) {
107 let (mut x, mut y, mut z) = (self[0].rank, self[1].rank, self[2].rank);
108
109 if x < y {
110 mem::swap(&mut x, &mut y);
111 }
112
113 if y < z {
114 mem::swap(&mut y, &mut z);
115 }
116
117 if x < y {
118 mem::swap(&mut x, &mut y);
119 }
120
121 (x, y, z)
122 }
123}
124
125impl<const N: usize> Index<usize> for HandN<N> {
126 type Output = Card;
127
128 fn index(&self, index: usize) -> &Self::Output {
129 &self.0[index]
130 }
131}
132
133impl<'a, const N: usize> IntoIterator for &'a HandN<N> {
134 type Item = Card;
135 type IntoIter = iter::Copied<slice::Iter<'a, Card>>;
136
137 fn into_iter(self) -> Self::IntoIter {
138 self.0.iter().copied()
139 }
140}
141
142impl<const N: usize> fmt::Debug for HandN<N> {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 write!(f, "Hand<")?;
145 for c in &self.0 {
146 write!(f, "{c}")?;
147 }
148 write!(f, ">")
149 }
150}
151
152impl<const N: usize> fmt::Display for HandN<N> {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 for card in &self.0 {
155 write!(f, "{card}")?;
156 }
157
158 Ok(())
159 }
160}
161
162impl<const N: usize> From<HandN<N>> for Card64 {
163 fn from(hand: HandN<N>) -> Self {
164 let mut card64 = Self::default();
165 for card in hand.iter() {
166 card64 |= Self::from(card);
167 }
168 card64
169 }
170}
171
172impl From<(Card, Card, Card)> for HandN<3> {
173 fn from(cs: (Card, Card, Card)) -> Self {
174 Self::from_slice(&[cs.0, cs.1, cs.2])
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181 use crate::*;
182
183 #[test]
184 fn test_hand() {
185 let cards = cards!("2s Kc Ad Kh");
186 let [c1, c2, c3, c4] = cards.clone().try_into().unwrap();
187
188 let hand: HandN<3> = HandN::from_slice(&cards);
189
190 assert_eq!(hand.as_slice(), &[c1, c2, c3]);
191
192 let hand: HandN<4> = HandN::from_slice(&cards);
193
194 assert_eq!(hand.as_slice(), &[c1, c4, c2, c3]);
195 }
196
197 #[test]
198 #[should_panic(expected = "not enough")]
199 fn test_hand_n3_not_enough_cards() {
200 let cards = cards!("2s Kc");
201
202 let _hand: HandN<3> = HandN::from_slice(&cards);
203 }
204
205 #[test]
206 fn test_hand_iter() {
207 let cards = cards!("2s Kc Ad");
208 let hand: HandN<3> = HandN::from_slice(&cards);
209
210 let collected: Vec<Card> = hand.iter().collect();
211 assert_eq!(collected, cards!("2s Kc Ad"));
212 }
213
214 #[test]
215 fn test_hand_into_iter() {
216 let cards = cards!("2s Kc Ad");
217 let hand: HandN<3> = HandN::from_slice(&cards);
218
219 let collected: Vec<Card> = (&hand).into_iter().collect();
220 assert_eq!(collected, cards!("2s Kc Ad"));
221 }
222
223 #[test]
224 fn test_hand_index() {
225 let cards = cards!("2s Kc Ad");
226 let hand: HandN<3> = HandN::from_slice(&cards);
227
228 assert_eq!(hand[0], cards!("2s")[0]);
229 assert_eq!(hand[1], cards!("Kc")[0]);
230 assert_eq!(hand[2], cards!("Ad")[0]);
231 }
232
233 #[test]
234 fn test_hand_len_and_is_empty() {
235 let cards = cards!("2s Kc Ad");
236 let hand3: HandN<3> = HandN::from_slice(&cards);
237 assert_eq!(hand3.len(), 3);
238 assert!(!hand3.is_empty());
239
240 let empty_cards = cards!("2s Kc Ad");
241 let hand0: HandN<0> = HandN::from_slice(&empty_cards);
242 assert_eq!(hand0.len(), 0);
243 assert!(hand0.is_empty());
244 }
245
246 #[test]
247 fn test_hand_debug_and_display() {
248 let cards = cards!("2s Kc Ad");
249 let hand: HandN<3> = HandN::from_slice(&cards);
250
251 let debug_str = format!("{hand:?}");
253 assert_eq!(debug_str, "Hand<2sKcAd>");
254 }
255
256 #[test]
257 fn test_hand_sorting() {
258 let unsorted_cards = cards!("Ad Kc 2s");
260 let hand: HandN<3> = HandN::from_slice(&unsorted_cards);
261
262 assert_eq!(hand[0], cards!("2s")[0]);
264 assert_eq!(hand[1], cards!("Kc")[0]);
265 assert_eq!(hand[2], cards!("Ad")[0]);
266 }
267
268 #[test]
269 fn test_hand_equality() {
270 let cards1 = cards!("2s Kc Ad");
271 let cards2 = cards!("Ad Kc 2s"); let hand1: HandN<3> = HandN::from_slice(&cards1);
274 let hand2: HandN<3> = HandN::from_slice(&cards2);
275
276 assert_eq!(hand1, hand2);
279
280 let cards3 = cards!("2s Kc Ah");
282 let hand3: HandN<3> = HandN::from_slice(&cards3);
283 assert_ne!(hand1, hand3);
284 }
285
286 #[quickcheck]
287 fn test_hand2_to_u16((c0, c1): (Card, Card)) {
288 if c0 != c1 {
289 let hand = HandN::<2>::from_slice(&<[Card; 2]>::from((c0, c1)));
290 assert_eq!(hand, HandN::<2>::from_u16(hand.to_u16()));
291 }
292 }
293
294 #[test]
295 #[should_panic(expected = "Hand initialized from unsorted array")]
296 #[cfg(debug_assertions)]
297 fn test_new_unsorted_array_debug_assert() {
298 let unsorted = [
300 Card::from_str("Ad").unwrap(),
301 Card::from_str("2s").unwrap(),
302 Card::from_str("Kc").unwrap(),
303 ];
304
305 let _hand = HandN::new(unsorted);
307 }
308
309 #[test]
310 #[should_panic(expected = "not enough cards for Hand")]
311 #[cfg(debug_assertions)]
312 fn test_from_slice_not_enough_cards_debug_assert() {
313 let cards = cards!("2s Kc"); let _hand: HandN<3> = HandN::from_slice(&cards);
317 }
318
319 #[test]
320 fn test_from_slice_sorts_cards() {
321 let unsorted_cards = cards!("Ad Kc 2s");
322 let hand: HandN<3> = HandN::from_slice(&unsorted_cards);
323
324 let expected_order = cards!("2s Kc Ad");
326 for (i, card) in expected_order.iter().enumerate() {
327 assert_eq!(hand[i], *card);
328 }
329 }
330
331 #[quickcheck]
332 fn test_hand_to_card64(cards: CardN<7>) {
333 let cs: Vec<_> = cards.into_iter().collect();
334 let c64 = Card64::from(cs.as_slice());
335 let hand = HandN::<7>::from_slice(&cs);
336
337 assert_eq!(c64, Card64::from(hand));
338 }
339
340 #[test]
341 fn test_hand_to_vec() {
342 let cs = cards!("AsKhQd");
343 assert_eq!(HandN::<3>::from_slice(&cs).to_vec(), cards!("QdKhAs"));
344 }
345
346 #[test]
347 fn test_hand_display() {
348 let hand = HandN::<2>::from_slice(&cards!("AsKh"));
349 assert_eq!(format!("{hand}"), "KhAs");
350 }
351}