1use arbitrary::Unstructured;
2use rand::RngExt;
3
4const ALPHANUM_CHARS: &[char; 62] = &[
5 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
6 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
7 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
8 '5', '6', '7', '8', '9',
9];
10
11#[derive(Debug, thiserror::Error)]
13pub enum ResponseError {
14 #[error("randomness source attempted to choose from an empty range")]
16 EmptyChoose,
17 #[error("randomness source exhausted or produced invalid data")]
19 Exhausted,
20 #[error("invalid format: {0}")]
22 InvalidFormat(String),
23}
24
25pub trait RandomProvider {
30 fn gen_bool(&mut self) -> Result<bool, ResponseError>;
32
33 fn gen_i32_range(&mut self, min: i32, max: i32) -> Result<i32, ResponseError>;
35
36 fn gen_usize_range(&mut self, min: usize, max: usize) -> Result<usize, ResponseError>;
38
39 fn gen_f64_range(&mut self, min: f64, max: f64) -> Result<f64, ResponseError>;
41
42 fn gen_alphanumeric_char(&mut self) -> Result<char, ResponseError>;
44
45 fn choose_index(&mut self, len: usize) -> Result<usize, ResponseError>;
47
48 fn ratio(&mut self, numerator: u32, denominator: u32) -> Result<bool, ResponseError>;
50}
51
52impl RandomProvider for Unstructured<'_> {
53 fn gen_bool(&mut self) -> Result<bool, ResponseError> {
54 self.arbitrary::<bool>()
55 .map_err(|_| ResponseError::Exhausted)
56 }
57
58 fn gen_i32_range(&mut self, min: i32, max: i32) -> Result<i32, ResponseError> {
59 self.int_in_range(min..=max)
60 .map_err(|_| ResponseError::Exhausted)
61 }
62
63 fn gen_usize_range(&mut self, min: usize, max: usize) -> Result<usize, ResponseError> {
64 self.int_in_range(min..=max)
65 .map_err(|_| ResponseError::Exhausted)
66 }
67
68 fn gen_f64_range(&mut self, min: f64, max: f64) -> Result<f64, ResponseError> {
69 let raw: u32 = self.arbitrary().map_err(|_| ResponseError::Exhausted)?;
72 let fraction = (raw as f64) / (u32::MAX as f64); Ok(min + fraction * (max - min))
74 }
75
76 fn gen_alphanumeric_char(&mut self) -> Result<char, ResponseError> {
77 self.choose(ALPHANUM_CHARS)
78 .map_err(|_| ResponseError::Exhausted)
79 .copied()
80 }
81
82 fn choose_index(&mut self, len: usize) -> Result<usize, ResponseError> {
83 self.choose_index(len)
84 .map_err(|_| ResponseError::EmptyChoose)
85 }
86
87 fn ratio(&mut self, numerator: u32, denominator: u32) -> Result<bool, ResponseError> {
88 self.ratio(numerator, denominator)
89 .map_err(|_| ResponseError::Exhausted)
90 }
91}
92
93pub struct RandProvider<R>(pub R);
104
105impl<R: rand::Rng> RandomProvider for RandProvider<R> {
106 fn gen_bool(&mut self) -> Result<bool, ResponseError> {
107 Ok(self.0.random_bool(0.5))
108 }
109
110 fn gen_i32_range(&mut self, min: i32, max: i32) -> Result<i32, ResponseError> {
111 Ok(self.0.random_range(min..=max))
112 }
113
114 fn gen_usize_range(&mut self, min: usize, max: usize) -> Result<usize, ResponseError> {
115 Ok(self.0.random_range(min..=max))
116 }
117
118 fn gen_f64_range(&mut self, min: f64, max: f64) -> Result<f64, ResponseError> {
119 Ok(self.0.random_range(min..=max))
120 }
121
122 fn gen_alphanumeric_char(&mut self) -> Result<char, ResponseError> {
123 Ok(self.0.sample(rand::distr::Alphanumeric) as char)
124 }
125
126 fn choose_index(&mut self, len: usize) -> Result<usize, ResponseError> {
127 if len == 0 {
128 return Err(ResponseError::EmptyChoose);
129 }
130 Ok(self.0.random_range(0..len))
131 }
132
133 fn ratio(&mut self, numerator: u32, denominator: u32) -> Result<bool, ResponseError> {
134 Ok(self.0.random_ratio(numerator, denominator))
135 }
136}