1use core::num::NonZeroUsize;
12
13use crate::Rng;
14use crate::distr::Distribution;
15use crate::distr::uniform::{UniformSampler, UniformUsize};
16#[cfg(feature = "alloc")]
17use alloc::string::String;
18
19#[derive(#[automatically_derived]
impl<'a, T: ::core::fmt::Debug> ::core::fmt::Debug for Choose<'a, T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "Choose",
"slice", &self.slice, "range", &self.range, "num_choices",
&&self.num_choices)
}
}Debug, #[automatically_derived]
impl<'a, T: ::core::clone::Clone> ::core::clone::Clone for Choose<'a, T> {
#[inline]
fn clone(&self) -> Choose<'a, T> {
Choose {
slice: ::core::clone::Clone::clone(&self.slice),
range: ::core::clone::Clone::clone(&self.range),
num_choices: ::core::clone::Clone::clone(&self.num_choices),
}
}
}Clone, #[automatically_derived]
impl<'a, T: ::core::marker::Copy> ::core::marker::Copy for Choose<'a, T> { }Copy)]
60pub struct Choose<'a, T> {
61 slice: &'a [T],
62 range: UniformUsize,
63 num_choices: NonZeroUsize,
64}
65
66impl<'a, T> Choose<'a, T> {
67 pub fn new(slice: &'a [T]) -> Result<Self, Empty> {
71 let num_choices = NonZeroUsize::new(slice.len()).ok_or(Empty)?;
72
73 Ok(Self {
74 slice,
75 range: UniformUsize::new(0, num_choices.get()).unwrap(),
76 num_choices,
77 })
78 }
79
80 pub fn num_choices(&self) -> NonZeroUsize {
82 self.num_choices
83 }
84}
85
86impl<'a, T> Distribution<&'a T> for Choose<'a, T> {
87 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> &'a T {
88 let idx = self.range.sample(rng);
89 self.slice
90 .get(idx)
91 .expect("rand::distr::slice::Choose: index out-of-range (likely memory corruption)")
92 }
93}
94
95#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Empty {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Empty")
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Empty {
#[inline]
fn clone(&self) -> Empty { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Empty { }Copy)]
99pub struct Empty;
100
101impl core::fmt::Display for Empty {
102 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103 f.write_fmt(format_args!("Tried to create a `rand::distr::slice::Choose` with an empty slice"))write!(
104 f,
105 "Tried to create a `rand::distr::slice::Choose` with an empty slice"
106 )
107 }
108}
109
110impl core::error::Error for Empty {}
111
112#[cfg(feature = "alloc")]
113impl super::SampleString for Choose<'_, char> {
114 fn append_string<R: Rng + ?Sized>(&self, rng: &mut R, string: &mut String, len: usize) {
115 let max_char_len = if self.slice.len() < 200 {
118 self.slice
119 .iter()
120 .try_fold(1, |max_len, char| {
121 Some(max_len.max(char.len_utf8())).filter(|len| *len < 4)
123 })
124 .unwrap_or(4)
125 } else {
126 4
127 };
128
129 let mut extend_len = if max_char_len == 1 || len < 100 {
132 len
133 } else {
134 len / 4
135 };
136 let mut remain_len = len;
137 while extend_len > 0 {
138 string.reserve(max_char_len * extend_len);
139 string.extend(self.sample_iter(&mut *rng).take(extend_len));
140 remain_len -= extend_len;
141 extend_len = extend_len.min(remain_len);
142 }
143 }
144}
145
146#[cfg(test)]
147mod test {
148 use super::*;
149 use core::iter;
150
151 #[test]
152 fn value_stability() {
153 let rng = crate::test::rng(651);
154 let slice = Choose::new(b"escaped emus explore extensively").unwrap();
155 let expected = b"eaxee";
156 assert!(iter::zip(slice.sample_iter(rng), expected).all(|(a, b)| a == b));
157 }
158}