rdeck 0.2.0

a simple library for choosing distinct random elements
Documentation
use crate::common::Deck;
use crate::Rng;

/// core [`Deck`] implementation used to implement other decks.
///
/// the elements of the deck are integers starting at zero.
///
/// [`Deck`]: trait.Deck.html
pub struct IntDeck<R: Rng> {
	/// total size of deck
	n: usize,
	/// previously picked cards
	h: Vec<usize>,
	/// source of randomness
	r: R,
}

impl<R: Rng> IntDeck<R> {
	/// create a new [`IntDeck`] with n cards.
	///
	/// [`IntDeck`]: struct.IntDeck.html
	pub fn new(n: usize, r: R) -> Self {
		IntDeck{ n, r, h: Vec::new() }
	}
	/// remove several cards from the deck.
	/// does nothing if the card has already been removed.
	/// WARNING: removing a card that was never in the deck is undefined behavior
	pub fn remove(&mut self, cards: &[usize]) {
		self.h.extend_from_slice(cards);
		self.h.sort();
		self.h.dedup();
	}
}

impl<R: Rng> Deck for IntDeck<R> {
	type Card = usize;
	fn left(&self) -> usize { self.n - self.h.len() }
	
	fn draw(&mut self) -> usize {
		// the core algorythem of the whole library.
		// uses a bit of cleverness to only ever need one rng call,
		// unlike the obvious trivial "call again until you get a different number"
		// also, it does not require allocating the entire deck into a Vec
		let mut x: usize = self.r.next_u64() as usize % self.left();
		for y in self.h.iter() {
			if x >= *y { x += 1; }
		}
		self.h.push(x);
		self.h.sort();
		return x;
	}

	fn refill(&mut self) {
		self.h.clear();
	}
}