openpql_prelude/card/
hand_n.rs1use super::{Card, Card64, Deref, HandIter, Hash, Index, Into, fmt};
2
3#[derive(
7 Copy,
8 Clone,
9 derive_more::Debug,
10 PartialEq,
11 Eq,
12 Hash,
13 PartialOrd,
14 Ord,
15 Into,
16 Deref,
17 Index,
18)]
19#[debug("Hand<{}>({})", N, self)]
20pub struct HandN<const N: usize>(pub(crate) [Card; N]);
21
22impl<const N: usize> HandN<N> {
23 #[cfg_attr(coverage_nightly, coverage(off))]
24 pub(crate) fn new(array: [Card; N]) -> Self {
25 debug_assert!(N > 1, "HandN should have at least two cards.");
26 debug_assert!(
27 array.is_sorted(),
28 "Hand initialized from unsorted array {array:?}"
29 );
30 Self(array)
31 }
32
33 #[cfg_attr(coverage_nightly, coverage(off))]
35 pub fn from_slice(cs: &[Card]) -> Self {
36 debug_assert!(
37 cs.len() >= N,
38 "from_slice: not enough cards for Hand<{}> slice has {} elements",
39 N,
40 cs.len()
41 );
42
43 let mut cards = [Card::default(); N];
44 cards.copy_from_slice(&cs[..N]);
45 cards.sort_unstable();
46
47 Self(cards)
48 }
49
50 pub fn iter_all<const SD: bool>() -> HandIter<SD, N> {
52 HandIter::default()
53 }
54}
55
56impl<const N: usize> fmt::Display for HandN<N> {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 self.0.iter().try_for_each(|card| write!(f, "{card}"))
59 }
60}
61
62impl<const N: usize> From<HandN<N>> for Card64 {
63 fn from(hand: HandN<N>) -> Self {
64 hand.iter().copied().collect()
65 }
66}
67
68#[cfg(test)]
69#[cfg_attr(coverage_nightly, coverage(off))]
70mod tests {
71 use super::*;
72 use crate::*;
73
74 #[test]
75 #[should_panic(expected = "Hand initialized from unsorted array")]
76 #[cfg(debug_assertions)]
77 fn test_new_err() {
78 let unsorted = [
79 Card::from_str("Ad").unwrap(),
80 Card::from_str("2s").unwrap(),
81 Card::from_str("Kc").unwrap(),
82 ];
83
84 let _hand = HandN::new(unsorted);
85 }
86
87 #[test]
88 #[should_panic(expected = "not enough cards for Hand")]
89 #[cfg(debug_assertions)]
90 fn test_from_slice_err() {
91 let cards = cards!("2s Kc");
92
93 let _hand: HandN<3> = HandN::from_slice(&cards);
94 }
95
96 #[test]
97 fn test_from_slice() {
98 let cards = cards!("2s Kc Ad Kh");
99 let [c1, c2, c3, c4] = cards.clone().try_into().unwrap();
100
101 assert_eq!(HandN::<3>::from_slice(&cards).0, [c1, c2, c3]);
102 assert_eq!(HandN::<4>::from_slice(&cards).0, [c1, c4, c2, c3]);
103 }
104
105 #[test]
106 fn test_display() {
107 let hand: HandN<3> = HandN::<3>::from_slice(&cards!("2s Ad Kc"));
108
109 assert_eq!(format!("{hand}"), "2sKcAd");
110 assert_eq!(format!("{hand:?}"), "Hand<3>(2sKcAd)");
111 }
112
113 #[test]
114 fn test_ord() {
115 let unsorted_cards = cards!("Ad Kc 2s");
116 let hand: HandN<3> = HandN::from_slice(&unsorted_cards);
117
118 assert_eq!(hand[0], cards!("2s")[0]);
119 assert_eq!(hand[1], cards!("Kc")[0]);
120 assert_eq!(hand[2], cards!("Ad")[0]);
121 }
122
123 #[quickcheck]
124 fn test_to_card64(cards: CardN<7>) {
125 let cs: Vec<_> = cards.into_iter().collect();
126 let c64 = Card64::from(cs.as_slice());
127 let hand = HandN::<7>::from_slice(&cs);
128
129 assert_eq!(c64, Card64::from(hand));
130 }
131}