use crate::core::{Card, FlatDeck};
#[derive(Debug)]
pub struct CardIter<'a> {
possible_cards: &'a [Card],
idx: Vec<usize>,
num_cards: usize,
}
impl CardIter<'_> {
pub fn new(possible_cards: &[Card], num_cards: usize) -> CardIter {
let mut idx: Vec<usize> = (0..num_cards).collect();
if num_cards > 1 {
idx[num_cards - 1] -= 1;
}
CardIter {
possible_cards,
idx,
num_cards,
}
}
}
impl Iterator for CardIter<'_> {
type Item = Vec<Card>;
fn next(&mut self) -> Option<Vec<Card>> {
if self.num_cards == 1 {
if self.idx[0] < self.possible_cards.len() {
let c = self.possible_cards[self.idx[0]];
self.idx[0] += 1;
return Some(vec![c]);
} else {
return None;
}
}
let mut current_level: usize = self.num_cards - 1;
while current_level < self.num_cards {
self.idx[current_level] += 1;
let cards_needed_after = self.num_cards - (current_level + 1);
if self.idx[current_level] + cards_needed_after >= self.possible_cards.len() {
if current_level == 0 {
return None;
}
current_level -= 1;
} else {
if current_level < self.num_cards - 1 {
self.idx[current_level + 1] = self.idx[current_level];
}
current_level += 1;
}
}
let result_cards: Vec<Card> = self.idx.iter().map(|i| self.possible_cards[*i]).collect();
Some(result_cards)
}
}
impl<'a> IntoIterator for &'a FlatDeck {
type Item = Vec<Card>;
type IntoIter = CardIter<'a>;
fn into_iter(self) -> CardIter<'a> {
CardIter::new(&self[..], 5)
}
}
#[cfg(test)]
mod tests {
use crate::core::{Deck, FlatHand, Suit, Value};
use super::*;
#[test]
fn test_iter_one() {
let mut h = FlatHand::default();
h.push(Card {
value: Value::Two,
suit: Suit::Spade,
});
for cards in CardIter::new(&h[..], 1) {
assert_eq!(1, cards.len());
}
assert_eq!(1, CardIter::new(&h[..], 1).count());
}
#[test]
fn test_iter_two() {
let mut h = FlatHand::default();
h.push(Card {
value: Value::Two,
suit: Suit::Spade,
});
h.push(Card {
value: Value::Three,
suit: Suit::Spade,
});
h.push(Card {
value: Value::Four,
suit: Suit::Spade,
});
assert_eq!(3, CardIter::new(&h[..], 2).count());
for cards in CardIter::new(&h[..], 2) {
assert_eq!(2, cards.len());
assert!(cards[0] != cards[1]);
}
}
#[test]
fn test_iter_deck() {
let d: FlatDeck = Deck::default().into();
assert_eq!(2_598_960, d.into_iter().count());
}
}