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