From 29e310a470238b289a153d2b11b47e7a9d5a3643 Mon Sep 17 00:00:00 2001 From: Aryadev Chavali Date: Sun, 5 Apr 2026 05:04:00 +0100 Subject: [PATCH] card:mod: split implementations of methods into impls.rs --- src/card/impls.rs | 150 ++++++++++++++++++++++++++++++++++++++++++++++ src/card/mod.rs | 150 +--------------------------------------------- 2 files changed, 151 insertions(+), 149 deletions(-) create mode 100644 src/card/impls.rs diff --git a/src/card/impls.rs b/src/card/impls.rs new file mode 100644 index 0000000..78b86bc --- /dev/null +++ b/src/card/impls.rs @@ -0,0 +1,150 @@ +use crate::card::{Card, PlayingCard, Rank, Suit}; + +impl Rank { + pub fn ordinary_order(&self) -> i32 { + ((*self as i32) + 2) % 13 + } + + /** Generate an iterator over all ranks. */ + pub fn iter_all() -> impl ExactSizeIterator { + (0i32..13).map(|n| Rank::try_from(n as i64).unwrap()) + } + + /** Generate an iterator over all cards within a rank, ordered by Suit. */ + pub fn cards(self) -> impl Iterator { + let n = self as i64; + ((n * 4)..((n + 1) * 4)).map(Card::from) + } +} + +impl Suit { + /** Generate an iterator over all suits. */ + pub fn iter_all() -> impl Iterator { + (0..4).filter_map(|x| Suit::try_from(x).ok()) + } + + /** Generate an iterator over all cards within a suit, ordered by Suit. */ + pub fn cards(self) -> impl Iterator { + Rank::iter_all().map(move |rank| Card::make_playing_card(rank, self)) + } +} + +impl PlayingCard { + pub fn new(deck: i64, rank: Rank, suit: Suit) -> Self { + Self { deck, rank, suit } + } + + pub fn abs(&self) -> i64 { + let rank = self.rank as i64; + let suit = self.suit as i64; + (rank * 4) + suit + } + + /** Generate an iterator over all Playing Cards in a fixed deck. By + construction this is in ascending order. */ + pub fn iter_all(deck: usize) -> impl Iterator { + let deck = deck as i64; + ((deck * 52)..((deck + 1) * 52)) + .filter_map(|x| PlayingCard::try_from(x).ok()) + } + + /** Return the Playing Card after the current one in terms of ordering. + + Returns None if self is 2 of Spades (the highest possible Playing Card). + Respects deck of self. */ + pub fn next(&self) -> Option { + match *self { + PlayingCard { + rank: Rank::Two, + suit: Suit::Spade, + .. + } => None, + card => PlayingCard::try_from(i64::from(card) + 1).ok(), + } + } + + /** Return the Playing Card before the current one in terms of ordering. + + Returns None if self is 3 of Diamonds (the lowest possible Playing Card). + Respects deck of self. */ + pub fn prev(&self) -> Option { + match *self { + PlayingCard { + rank: Rank::Three, + suit: Suit::Diamond, + .. + } => None, + card => PlayingCard::try_from(i64::from(card) - 1).ok(), + } + } +} + +impl Card { + pub fn make_joker() -> Self { + Self::Joker(-1) + } + + pub fn make_playing_card(rank: Rank, suit: Suit) -> Self { + Self::PlayingCard(PlayingCard::new(0, rank, suit)) + } + + pub fn deck_abs(&self) -> i64 { + match *self { + Self::Joker(x) => x, + Self::PlayingCard(card) => card.abs(), + } + } + + /** Generate an iterator over a `n` decks of Cards. Each deck is + concatenated together. By construction, each "deck" of the iterator is in + ascending order. + + Note that each deck gets two jokers. + */ + pub fn iter_all(n: usize) -> impl Iterator { + (-((n as i64) * 2)..0).map(Card::from).chain( + (0..n) + .flat_map(PlayingCard::iter_all) + .map(Card::PlayingCard), + ) + } + + /** Return the Card after the current one in terms of ordering. + + Returns None if self is a joker, or based on PlayingCard::next.*/ + pub fn next(&self) -> Option { + match *self { + Card::Joker(_) => None, + Card::PlayingCard(card) => card.next().map(Card::PlayingCard), + } + } + + /** Return the Card before the current one in terms of ordering. + + Returns None if self is a joker, or based on PlayingCard::prev.*/ + pub fn prev(&self) -> Option { + match *self { + Card::Joker(_) => None, + Card::PlayingCard(card) => card.prev().map(Card::PlayingCard), + } + } + + pub fn is_joker(&self) -> bool { + matches!(self, Self::Joker(_)) + } + + pub fn playing_card(&self) -> Option { + match *self { + Self::Joker(_) => None, + Self::PlayingCard(card) => Some(card), + } + } + + pub fn rank(&self) -> Option { + self.playing_card().map(|pc| pc.rank) + } + + pub fn suit(&self) -> Option { + self.playing_card().map(|pc| pc.suit) + } +} diff --git a/src/card/mod.rs b/src/card/mod.rs index 625ec93..4f99568 100644 --- a/src/card/mod.rs +++ b/src/card/mod.rs @@ -1,5 +1,6 @@ mod display; mod hash; +mod impls; mod numerics; mod ord; @@ -41,155 +42,6 @@ pub enum Card { PlayingCard(PlayingCard), } -impl Rank { - pub fn ordinary_order(&self) -> i32 { - ((*self as i32) + 2) % 13 - } - - /** Generate an iterator over all ranks. */ - pub fn iter_all() -> impl ExactSizeIterator { - (0i32..13).map(|n| Rank::try_from(n as i64).unwrap()) - } - - /** Generate an iterator over all cards within a rank, ordered by Suit. */ - pub fn cards(self) -> impl Iterator { - let n = self as i64; - ((n * 4)..((n + 1) * 4)).map(Card::from) - } -} - -impl Suit { - /** Generate an iterator over all suits. */ - pub fn iter_all() -> impl Iterator { - (0..4).filter_map(|x| Suit::try_from(x).ok()) - } - - /** Generate an iterator over all cards within a suit, ordered by Suit. */ - pub fn cards(self) -> impl Iterator { - Rank::iter_all().map(move |rank| Card::make_playing_card(rank, self)) - } -} - -impl PlayingCard { - pub fn new(deck: i64, rank: Rank, suit: Suit) -> Self { - Self { deck, rank, suit } - } - - pub fn abs(&self) -> i64 { - let rank = self.rank as i64; - let suit = self.suit as i64; - (rank * 4) + suit - } - - /** Generate an iterator over all Playing Cards in a fixed deck. By - construction this is in ascending order. */ - pub fn iter_all(deck: usize) -> impl Iterator { - let deck = deck as i64; - ((deck * 52)..((deck + 1) * 52)) - .filter_map(|x| PlayingCard::try_from(x).ok()) - } - - /** Return the Playing Card after the current one in terms of ordering. - - Returns None if self is 2 of Spades (the highest possible Playing Card). - Respects deck of self. */ - pub fn next(&self) -> Option { - match *self { - PlayingCard { - rank: Rank::Two, - suit: Suit::Spade, - .. - } => None, - card => PlayingCard::try_from(i64::from(card) + 1).ok(), - } - } - - /** Return the Playing Card before the current one in terms of ordering. - - Returns None if self is 3 of Diamonds (the lowest possible Playing Card). - Respects deck of self. */ - pub fn prev(&self) -> Option { - match *self { - PlayingCard { - rank: Rank::Three, - suit: Suit::Diamond, - .. - } => None, - card => PlayingCard::try_from(i64::from(card) - 1).ok(), - } - } -} - -impl Card { - pub fn make_joker() -> Self { - Self::Joker(-1) - } - - pub fn make_playing_card(rank: Rank, suit: Suit) -> Self { - Self::PlayingCard(PlayingCard::new(0, rank, suit)) - } - - pub fn deck_abs(&self) -> i64 { - match *self { - Self::Joker(x) => x, - Self::PlayingCard(card) => card.abs(), - } - } - - /** Generate an iterator over a `n` decks of Cards. Each deck is - concatenated together. By construction, each "deck" of the iterator is in - ascending order. - - Note that each deck gets two jokers. - */ - pub fn iter_all(n: usize) -> impl Iterator { - (-((n as i64) * 2)..0).map(Card::from).chain( - (0..n) - .flat_map(PlayingCard::iter_all) - .map(Card::PlayingCard), - ) - } - - /** Return the Card after the current one in terms of ordering. - - Returns None if self is a joker, or based on PlayingCard::next.*/ - pub fn next(&self) -> Option { - match *self { - Card::Joker(_) => None, - Card::PlayingCard(card) => card.next().map(Card::PlayingCard), - } - } - - /** Return the Card before the current one in terms of ordering. - - Returns None if self is a joker, or based on PlayingCard::prev.*/ - pub fn prev(&self) -> Option { - match *self { - Card::Joker(_) => None, - Card::PlayingCard(card) => card.prev().map(Card::PlayingCard), - } - } - - pub fn is_joker(&self) -> bool { - matches!(self, Self::Joker(_)) - } - - pub fn playing_card(&self) -> Option { - match *self { - Self::Joker(_) => None, - Self::PlayingCard(card) => Some(card), - } - } - - pub fn rank(&self) -> Option { - self.playing_card().map(|pc| pc.rank) - } - - pub fn suit(&self) -> Option { - self.playing_card().map(|pc| pc.suit) - } -} - /** Given a sequence of Playing Cards, check if they are all of the same rank. */ pub fn all_same_rank(cards: &[PlayingCard]) -> bool {