server/domain/types/card/
face.rs1use serde::{Deserialize, Serialize};
2use strum::EnumIter;
3
4use super::{rank::Rank, value::Value};
5use crate::domain::CardsError;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, EnumIter)]
9#[rustfmt::skip]
10pub enum Face {
11 #[doc(hidden)] Ace,
12 #[doc(hidden)] Two,
13 #[doc(hidden)] Three,
14 #[doc(hidden)] Four,
15 #[doc(hidden)] Five,
16 #[doc(hidden)] Six,
17 #[doc(hidden)] Seven,
18 #[doc(hidden)] Eight,
19 #[doc(hidden)] Nine,
20 #[doc(hidden)] Ten,
21 #[doc(hidden)] Jack,
22 #[doc(hidden)] Queen,
23 #[doc(hidden)] King,
24}
25
26impl Face {
27 #[must_use]
29 #[inline]
30 pub const fn is_jack(&self) -> bool {
31 matches!(self, Self::Jack)
32 }
33
34 #[must_use]
36 pub fn rank(&self) -> Rank {
37 let rank = match self {
38 Self::Ace => 1,
39 Self::Two => 2,
40 Self::Three => 3,
41 Self::Four => 4,
42 Self::Five => 5,
43 Self::Six => 6,
44 Self::Seven => 7,
45 Self::Eight => 8,
46 Self::Nine => 9,
47 Self::Ten => 10,
48 Self::Jack => 11,
49 Self::Queen => 12,
50 Self::King => 13,
51 };
52
53 Rank::from(rank)
54 }
55
56 #[must_use]
62 pub fn value(&self) -> Value {
63 let value = match self {
64 Self::Ace => 1,
65 Self::Two => 2,
66 Self::Three => 3,
67 Self::Four => 4,
68 Self::Five => 5,
69 Self::Six => 6,
70 Self::Seven => 7,
71 Self::Eight => 8,
72 Self::Nine => 9,
73 Self::Ten | Self::Jack | Self::Queen | Self::King => 10,
74 };
75
76 Value::from(value)
77 }
78}
79
80impl TryFrom<char> for Face {
81 type Error = CardsError;
82
83 fn try_from(value: char) -> Result<Self, Self::Error> {
84 match value {
85 'A' => Ok(Self::Ace),
86 '2' => Ok(Self::Two),
87 '3' => Ok(Self::Three),
88 '4' => Ok(Self::Four),
89 '5' => Ok(Self::Five),
90 '6' => Ok(Self::Six),
91 '7' => Ok(Self::Seven),
92 '8' => Ok(Self::Eight),
93 '9' => Ok(Self::Nine),
94 'T' => Ok(Self::Ten),
95 'J' => Ok(Self::Jack),
96 'Q' => Ok(Self::Queen),
97 'K' => Ok(Self::King),
98 other => Err(CardsError::InvalidCard(format!("Invalid face: {other}"))),
99 }
100 }
101}
102
103impl std::fmt::Display for Face {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 let s = match self {
106 Self::Ace => "A",
107 Self::Two => "2",
108 Self::Three => "3",
109 Self::Four => "4",
110 Self::Five => "5",
111 Self::Six => "6",
112 Self::Seven => "7",
113 Self::Eight => "8",
114 Self::Nine => "9",
115 Self::Ten => "T",
116 Self::Jack => "J",
117 Self::Queen => "Q",
118 Self::King => "K",
119 };
120 s.fmt(f)
121 }
122}
123
124#[cfg(test)]
125#[coverage(off)]
126pub mod test {
127 use super::*;
128
129 #[test]
130 fn face_has_rank_value_display_string_and_name() {
131 let faces = [
132 (Face::Ace, 1, 1, "A"),
133 (Face::Two, 2, 2, "2"),
134 (Face::Three, 3, 3, "3"),
135 (Face::Four, 4, 4, "4"),
136 (Face::Five, 5, 5, "5"),
137 (Face::Six, 6, 6, "6"),
138 (Face::Seven, 7, 7, "7"),
139 (Face::Eight, 8, 8, "8"),
140 (Face::Nine, 9, 9, "9"),
141 (Face::Ten, 10, 10, "T"),
142 (Face::Jack, 11, 10, "J"),
143 (Face::Queen, 12, 10, "Q"),
144 (Face::King, 13, 10, "K"),
145 ];
146
147 for (face, rank, value, display_string) in faces {
148 assert_eq!(face.rank(), Rank::from(rank));
149 assert_eq!(face.value(), Value::from(value));
150 assert_eq!(face.to_string(), display_string);
151 }
152 }
153}