9
9
use core:: num:: NonZeroUsize ;
10
10
11
11
use crate :: distributions:: { Distribution , Uniform } ;
12
+ use crate :: Rng ;
12
13
#[ cfg( feature = "alloc" ) ]
13
14
use alloc:: string:: String ;
14
15
16
+ #[ cfg( not( any( target_pointer_width = "32" , target_pointer_width = "64" ) ) ) ]
17
+ compile_error ! ( "unsupported pointer width" ) ;
18
+
19
+ #[ derive( Debug , Clone , Copy ) ]
20
+ enum UniformUsize {
21
+ U32 ( Uniform < u32 > ) ,
22
+ #[ cfg( target_pointer_width = "64" ) ]
23
+ U64 ( Uniform < u64 > ) ,
24
+ }
25
+
26
+ impl UniformUsize {
27
+ pub fn new ( ubound : usize ) -> Result < Self , super :: uniform:: Error > {
28
+ #[ cfg( target_pointer_width = "64" ) ]
29
+ if ubound > ( u32:: MAX as usize ) {
30
+ return Uniform :: new ( 0 , ubound as u64 ) . map ( UniformUsize :: U64 ) ;
31
+ }
32
+
33
+ Uniform :: new ( 0 , ubound as u32 ) . map ( UniformUsize :: U32 )
34
+ }
35
+
36
+ pub fn sample < R : Rng + ?Sized > ( & self , rng : & mut R ) -> usize {
37
+ match self {
38
+ UniformUsize :: U32 ( uu) => uu. sample ( rng) as usize ,
39
+ #[ cfg( target_pointer_width = "64" ) ]
40
+ UniformUsize :: U64 ( uu) => uu. sample ( rng) as usize ,
41
+ }
42
+ }
43
+ }
44
+
15
45
/// A distribution to sample items uniformly from a slice.
16
46
///
17
47
/// [`Slice::new`] constructs a distribution referencing a slice and uniformly
@@ -68,7 +98,7 @@ use alloc::string::String;
68
98
#[ derive( Debug , Clone , Copy ) ]
69
99
pub struct Slice < ' a , T > {
70
100
slice : & ' a [ T ] ,
71
- range : Uniform < usize > ,
101
+ range : UniformUsize ,
72
102
num_choices : NonZeroUsize ,
73
103
}
74
104
@@ -80,7 +110,7 @@ impl<'a, T> Slice<'a, T> {
80
110
81
111
Ok ( Self {
82
112
slice,
83
- range : Uniform :: new ( 0 , num_choices. get ( ) ) . unwrap ( ) ,
113
+ range : UniformUsize :: new ( num_choices. get ( ) ) . unwrap ( ) ,
84
114
num_choices,
85
115
} )
86
116
}
@@ -161,3 +191,17 @@ impl<'a> super::DistString for Slice<'a, char> {
161
191
}
162
192
}
163
193
}
194
+
195
+ #[ cfg( test) ]
196
+ mod test {
197
+ use super :: * ;
198
+ use core:: iter;
199
+
200
+ #[ test]
201
+ fn value_stability ( ) {
202
+ let rng = crate :: test:: rng ( 651 ) ;
203
+ let slice = Slice :: new ( b"escaped emus explore extensively" ) . unwrap ( ) ;
204
+ let expected = b"eaxee" ;
205
+ assert ! ( iter:: zip( slice. sample_iter( rng) , expected) . all( |( a, b) | a == b) ) ;
206
+ }
207
+ }
0 commit comments