1use super::*;
2
3#[derive(Copy, Clone, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Display)]
5pub enum Suit {
6 #[display("s")]
8 S = 0,
9 #[display("h")]
11 H,
12 #[display("d")]
14 D,
15 #[display("c")]
17 C,
18}
19
20impl Suit {
21 pub const ARR_ALL: [Self; N_SUITS as usize] =
23 [Self::S, Self::H, Self::D, Self::C];
24}
25
26impl TryFrom<char> for Suit {
27 type Error = ParseError;
28
29 fn try_from(c: char) -> Result<Self, Self::Error> {
30 match c {
31 'S' | 's' => Ok(Self::S),
32 'H' | 'h' => Ok(Self::H),
33 'D' | 'd' => Ok(Self::D),
34 'C' | 'c' => Ok(Self::C),
35
36 _ => Err(ParseError::InvalidSuit(c.into())),
37 }
38 }
39}
40
41impl FromStr for Suit {
42 type Err = ParseError;
43
44 fn from_str(s: &str) -> Result<Self, Self::Err> {
45 let mut cs = s.chars().filter(|c| !c.is_whitespace());
46
47 if let Some(c) = cs.next() {
48 if let Ok(s) = Self::try_from(c) {
49 if cs.next().is_none() {
50 return Ok(s);
51 }
52 }
53 }
54
55 Err(ParseError::InvalidSuit(s.into()))
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 impl Arbitrary for Suit {
64 fn arbitrary(g: &mut quickcheck::Gen) -> Self {
65 *g.choose(&Self::ARR_ALL).unwrap()
66 }
67 }
68
69 #[test]
70 fn test_consts() {
71 assert_eq!(Suit::ARR_ALL, [Suit::S, Suit::H, Suit::D, Suit::C]);
72 }
73
74 #[test]
75 fn test_as_int() {
76 assert_eq!(Suit::S as i8, 0);
77 assert_eq!(Suit::H as i8, 1);
78 assert_eq!(Suit::D as i8, 2);
79 assert_eq!(Suit::C as i8, 3);
80 }
81
82 #[test]
83 fn test_from_char() {
84 assert_eq!(Ok(Suit::S), 's'.try_into());
85 assert_eq!(Ok(Suit::H), 'h'.try_into());
86 assert_eq!(Ok(Suit::D), 'd'.try_into());
87 assert_eq!(Ok(Suit::C), 'c'.try_into());
88
89 assert_eq!(Ok(Suit::S), 'S'.try_into());
90 assert_eq!(Ok(Suit::H), 'H'.try_into());
91 assert_eq!(Ok(Suit::D), 'D'.try_into());
92 assert_eq!(Ok(Suit::C), 'C'.try_into());
93
94 assert_eq!(
95 Err(ParseError::InvalidSuit("?".into())),
96 Suit::try_from('?')
97 );
98 }
99
100 #[test]
101 fn test_from_str() {
102 assert_eq!(Ok(Suit::S), " s ".parse());
103 assert_eq!(
104 Err(ParseError::InvalidSuit("sS".into())),
105 "sS".parse::<Suit>()
106 );
107 assert!("".parse::<Suit>().is_err());
108 assert!("?".parse::<Suit>().is_err());
109 }
110
111 #[test]
112 fn test_to_string() {
113 assert_eq!("s", &Suit::S.to_string());
114 assert_eq!("h", &Suit::H.to_string());
115 assert_eq!("d", &Suit::D.to_string());
116 assert_eq!("c", &Suit::C.to_string());
117 }
118}