use crate::core::card::{Card, Suit, Value};
use std::ops::Index;
use std::ops::{RangeFrom, RangeFull, RangeTo};
use std::slice::Iter;
use super::RSPokerError;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct FlatHand(Vec<Card>);
impl FlatHand {
pub fn new_with_cards(cards: Vec<Card>) -> Self {
Self(cards)
}
pub fn new_from_str(hand_string: &str) -> Result<Self, RSPokerError> {
let mut chars = hand_string.chars();
let mut cards: Vec<Card> = Vec::with_capacity(7);
loop {
let vco = chars.next();
if vco.is_none() {
break;
} else {
let sco = chars.next();
let v = vco
.and_then(Value::from_char)
.ok_or(RSPokerError::UnexpectedValueChar)?;
let s = sco
.and_then(Suit::from_char)
.ok_or(RSPokerError::UnexpectedSuitChar)?;
let c = Card { value: v, suit: s };
match cards.binary_search(&c) {
Ok(_) => return Err(RSPokerError::DuplicateCardInHand(c)),
Err(i) => cards.insert(i, c),
};
}
}
if chars.next().is_some() {
return Err(RSPokerError::UnparsedCharsRemaining);
}
cards.reserve(7);
Ok(Self(cards))
}
pub fn push(&mut self, c: Card) {
self.0.push(c);
}
pub fn truncate(&mut self, len: usize) {
self.0.truncate(len);
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter(&self) -> Iter<Card> {
self.0.iter()
}
}
impl Default for FlatHand {
fn default() -> Self {
Self(Vec::with_capacity(7))
}
}
impl Index<usize> for FlatHand {
type Output = Card;
fn index(&self, index: usize) -> &Card {
&self.0[index]
}
}
impl Index<RangeFull> for FlatHand {
type Output = [Card];
fn index(&self, range: RangeFull) -> &[Card] {
&self.0[range]
}
}
impl Index<RangeTo<usize>> for FlatHand {
type Output = [Card];
fn index(&self, index: RangeTo<usize>) -> &[Card] {
&self.0[index]
}
}
impl Index<RangeFrom<usize>> for FlatHand {
type Output = [Card];
fn index(&self, index: RangeFrom<usize>) -> &[Card] {
&self.0[index]
}
}
impl Extend<Card> for FlatHand {
fn extend<T: IntoIterator<Item = Card>>(&mut self, iter: T) {
self.0.extend(iter);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_card() {
let mut h = FlatHand::default();
let c = Card {
value: Value::Three,
suit: Suit::Spade,
};
h.push(c);
assert_eq!(1, h.len());
}
#[test]
fn test_index() {
let mut h = FlatHand::default();
h.push(Card {
value: Value::Four,
suit: Suit::Spade,
});
assert_eq!(
Card {
value: Value::Four,
suit: Suit::Spade,
},
h[0]
);
}
#[test]
fn test_parse_error() {
assert!(FlatHand::new_from_str("BAD").is_err());
assert!(FlatHand::new_from_str("Adx").is_err());
}
#[test]
fn test_parse_one_hand() {
let h = FlatHand::new_from_str("Ad").unwrap();
assert_eq!(1, h.len())
}
#[test]
fn test_parse_empty() {
let h = FlatHand::new_from_str("").unwrap();
assert!(h.is_empty());
}
#[test]
fn test_new_with_cards() {
let h = FlatHand::new_with_cards(vec![
Card::new(Value::Jack, Suit::Spade),
Card::new(Value::Jack, Suit::Heart),
]);
assert_eq!(2, h.len());
}
#[test]
fn test_error_on_duplicate_card() {
assert!(FlatHand::new_from_str("AdAd").is_err());
}
#[test]
fn test_deterministic_new_from_str() {
let h = FlatHand::new_from_str("AdKd").unwrap();
assert_eq!(h, FlatHand::new_from_str("AdKd").unwrap());
assert_eq!(h, FlatHand::new_from_str("AdKd").unwrap());
assert_eq!(h, FlatHand::new_from_str("AdKd").unwrap());
assert_eq!(h, FlatHand::new_from_str("AdKd").unwrap());
assert_eq!(h, FlatHand::new_from_str("AdKd").unwrap());
assert_eq!(h, FlatHand::new_from_str("AdKd").unwrap());
}
}