use super::rank::Rank;
use super::suit::Suit;
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Card(u8);
impl Card {
pub fn rank(&self) -> Rank {
Rank::from(self.0 / 4)
}
pub fn suit(&self) -> Suit {
Suit::from(self.0 % 4)
}
pub fn draw() -> Card {
use rand::Rng;
let ref mut rng = rand::thread_rng();
Card::from(rng.gen_range(0..52) as u8)
}
}
impl From<(Rank, Suit)> for Card {
fn from((r, s): (Rank, Suit)) -> Self {
Self(u8::from(r) * 4 + u8::from(s))
}
}
impl From<Card> for u8 {
fn from(c: Card) -> u8 {
c.0
}
}
impl From<u8> for Card {
fn from(n: u8) -> Self {
Self(n)
}
}
impl From<Card> for u32 {
fn from(c: Card) -> u32 {
let suit = (1 << 13) << u8::from(c.suit());
let rank = u16::from(c.rank()) as u32;
rank | suit
}
}
impl From<u32> for Card {
fn from(n: u32) -> Self {
let rank = Rank::from(n as u16);
let suit = Suit::from((n >> 13).trailing_zeros() as u8);
Self::from((rank, suit))
}
}
impl From<u64> for Card {
fn from(n: u64) -> Self {
Self(n.trailing_zeros() as u8)
}
}
impl From<Card> for u64 {
fn from(c: Card) -> u64 {
1 << u8::from(c)
}
}
impl std::fmt::Display for Card {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}{}", self.rank(), self.suit())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bijective_rank_suit() {
let card = Card::draw();
let suit = card.suit();
let rank = card.rank();
assert!(card == Card::from((rank, suit)));
}
#[test]
fn bijective_u8() {
let card = Card::draw();
assert!(card == Card::from(u8::from(card)));
}
#[test]
fn bijective_u32() {
let card = Card::draw();
assert!(card == Card::from(u32::from(card)));
}
#[test]
fn bijective_u64() {
let card = Card::draw();
assert!(card == Card::from(u64::from(card)));
}
}