random_picker/
lib.rs

1//! Generates random choices based on the weight table of probabilities.
2//! It can be used to calculate each item's probability of being picked up
3//! when picking a given amount of non-repetitive items, or to compare
4//! the speed of OS random source with that of the CSPRNG.
5
6// by wuwbobo2021 <https://github.com/wuwbobo2021>, <wuwbobo@outlook.com>
7
8mod calc;
9mod config;
10mod picker;
11
12pub use crate::{config::*, picker::*};
13
14/// Convenience wrapper for exactly one picking operation.
15///
16/// ```
17/// let picks: Vec<String> = random_picker::pick(2,
18///     "a=1;b=15;c=1.5".parse().unwrap()
19/// ).unwrap();
20/// // nonrepetitive by default
21/// assert!(picks.iter().any(|k| k == "a" || k == "c"));
22/// ```
23pub fn pick<T>(amount: usize, conf: Config<T>) -> Result<Vec<T>, Error>
24where
25    T: Clone + Eq + std::hash::Hash,
26{
27    Picker::build(conf)?.pick(amount)
28}
29
30/// Possible errors returned by functions in this crate.
31#[derive(Debug)]
32pub enum Error {
33    /// The table is invalid and cannot be used by the picker.
34    InvalidTable,
35    /// The given amount exceeds the amount of possible items in the table.
36    InvalidAmount,
37    /// Error from the random generator.
38    RandError(rand::Error),
39    /// Failure of the multi-thread probability calculator.
40    ThreadError,
41}
42
43impl std::fmt::Display for Error {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        use Error::*;
46        match self {
47            InvalidTable => write!(f, "Invalid probability table"),
48            InvalidAmount => write!(f, "Invalid amount of items to be picked up"),
49            RandError(e) => write!(f, "RNG Error: {:?}", e),
50            ThreadError => write!(f, "Thread error during calculation"),
51        }
52    }
53}
54
55impl std::error::Error for Error {}