fix: parsing a card now returns an option
authorMA Beaudet <ma@beaudet.xyz>
Fri, 5 Nov 2021 14:33:12 +0000 (15:33 +0100)
committerMA Beaudet <ma@beaudet.xyz>
Fri, 5 Nov 2021 14:33:12 +0000 (15:33 +0100)
`card_from_str` is renamed to `parse_card` and now returns an
`Option<u32>` instead of a `u32`. The function does not panic anymore.

src/lib.rs

index fa4fa09..83256ac 100644 (file)
@@ -48,7 +48,7 @@ pub fn init_deck() -> Vec<u32> {
     deck
 }
 
-/// Returns an integer based on the rank and the suit of a card.
+/// Returns an option of integer based on the rank and the suit of a card.
 ///
 /// An integer is made up of four bytes.  The high-order bytes are used to
 /// hold the rank bit pattern, whereas the low-order bytes hold
@@ -73,40 +73,54 @@ pub fn init_deck() -> Vec<u32> {
 /// # Example
 ///
 /// ```
-/// use poker_eval::card_from_str;
+/// use poker_eval::parse_card;
 ///
 /// assert_eq!(
-///     card_from_str("Kd").to_be_bytes(),
+///     parse_card("Kd").unwrap().to_be_bytes(),
 ///     0b00001000_00000000_01001011_00100101_u32.to_be_bytes()
 /// );
 /// ```
-pub fn card_from_str(input: &str) -> u32 {
+pub fn parse_card(input: &str) -> Option<u32> {
     let mut input = input.chars();
     let (r, s) = (input.next(), input.next());
-    let r = match r.unwrap() {
-        '2' => 0,
-        '3' => 1,
-        '4' => 2,
-        '5' => 3,
-        '6' => 4,
-        '7' => 5,
-        '8' => 6,
-        '9' => 7,
-        'T' => 8,
-        'J' => 9,
-        'Q' => 10,
-        'K' => 11,
-        'A' => 12,
-        _ => panic!("{:?} is an invalid rank character", r),
-    };
-    let s = match s.unwrap() {
-        'c' => 0x8000,
-        'd' => 0x4000,
-        'h' => 0x2000,
-        's' => 0x1000,
-        _ => panic!("{:?} is an invalid suit character", s),
-    };
-    PRIMES[r] as u32 | (u32::try_from(r).unwrap() << 8) | s | (1 << (16 + r))
+    match (r, s) {
+        (None, None) => None,
+        (None, Some(_)) => None,
+        (Some(_), None) => None,
+        (Some(r), Some(s)) => {
+            let r = match r {
+                '2' => Some(0),
+                '3' => Some(1),
+                '4' => Some(2),
+                '5' => Some(3),
+                '6' => Some(4),
+                '7' => Some(5),
+                '8' => Some(6),
+                '9' => Some(7),
+                'T' => Some(8),
+                'J' => Some(9),
+                'Q' => Some(10),
+                'K' => Some(11),
+                'A' => Some(12),
+                _ => None,
+            };
+            let s = match s {
+                'c' => Some(0x8000),
+                'd' => Some(0x4000),
+                'h' => Some(0x2000),
+                's' => Some(0x1000),
+                _ => None,
+            };
+            match (r, s) {
+                (None, None) => None,
+                (None, Some(_)) => None,
+                (Some(_), None) => None,
+                (Some(r), Some(s)) => {
+                    Some(PRIMES[r] as u32 | (u32::try_from(r).unwrap() << 8) | s | (1 << (16 + r)))
+                }
+            }
+        }
+    }
 }
 
 /// Performs a perfect hash lookup
@@ -323,7 +337,7 @@ mod tests {
     #[test]
     fn card_from_string() {
         assert_eq!(
-            card_from_str("Kd"),
+            parse_card("Kd").unwrap(),
             0b00001000_00000000_01001011_00100101_u32
         );
     }