Coverage Report

Created: 2026-04-09 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/fastrand-1.8.0/src/lib.rs
Line
Count
Source
1
//! A simple and fast random number generator.
2
//!
3
//! The implementation uses [Wyrand](https://github.com/wangyi-fudan/wyhash), a simple and fast
4
//! generator but **not** cryptographically secure.
5
//!
6
//! # Examples
7
//!
8
//! Flip a coin:
9
//!
10
//! ```
11
//! if fastrand::bool() {
12
//!     println!("heads");
13
//! } else {
14
//!     println!("tails");
15
//! }
16
//! ```
17
//!
18
//! Generate a random `i32`:
19
//!
20
//! ```
21
//! let num = fastrand::i32(..);
22
//! ```
23
//!
24
//! Choose a random element in an array:
25
//!
26
//! ```
27
//! let v = vec![1, 2, 3, 4, 5];
28
//! let i = fastrand::usize(..v.len());
29
//! let elem = v[i];
30
//! ```
31
//!
32
//! Shuffle an array:
33
//!
34
//! ```
35
//! let mut v = vec![1, 2, 3, 4, 5];
36
//! fastrand::shuffle(&mut v);
37
//! ```
38
//!
39
//! Generate a random [`Vec`] or [`String`]:
40
//!
41
//! ```
42
//! use std::iter::repeat_with;
43
//!
44
//! let v: Vec<i32> = repeat_with(|| fastrand::i32(..)).take(10).collect();
45
//! let s: String = repeat_with(fastrand::alphanumeric).take(10).collect();
46
//! ```
47
//!
48
//! To get reproducible results on every run, initialize the generator with a seed:
49
//!
50
//! ```
51
//! // Pick an arbitrary number as seed.
52
//! fastrand::seed(7);
53
//!
54
//! // Now this prints the same number on every run:
55
//! println!("{}", fastrand::u32(..));
56
//! ```
57
//!
58
//! To be more efficient, create a new [`Rng`] instance instead of using the thread-local
59
//! generator:
60
//!
61
//! ```
62
//! use std::iter::repeat_with;
63
//!
64
//! let rng = fastrand::Rng::new();
65
//! let mut bytes: Vec<u8> = repeat_with(|| rng.u8(..)).take(10_000).collect();
66
//! ```
67
68
#![forbid(unsafe_code)]
69
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
70
71
use std::cell::Cell;
72
use std::collections::hash_map::DefaultHasher;
73
use std::hash::{Hash, Hasher};
74
use std::ops::{Bound, RangeBounds};
75
use std::thread;
76
77
#[cfg(target_arch = "wasm32")]
78
use instant::Instant;
79
#[cfg(not(target_arch = "wasm32"))]
80
use std::time::Instant;
81
82
/// A random number generator.
83
#[derive(Debug, PartialEq, Eq)]
84
pub struct Rng(Cell<u64>);
85
86
impl Default for Rng {
87
    #[inline]
88
0
    fn default() -> Rng {
89
0
        Rng::new()
90
0
    }
91
}
92
93
impl Clone for Rng {
94
    /// Clones the generator by deterministically deriving a new generator based on the initial
95
    /// seed.
96
    ///
97
    /// # Example
98
    ///
99
    /// ```
100
    /// // Seed two generators equally, and clone both of them.
101
    /// let base1 = fastrand::Rng::new();
102
    /// base1.seed(0x4d595df4d0f33173);
103
    /// base1.bool(); // Use the generator once.
104
    ///
105
    /// let base2 = fastrand::Rng::new();
106
    /// base2.seed(0x4d595df4d0f33173);
107
    /// base2.bool(); // Use the generator once.
108
    ///
109
    /// let rng1 = base1.clone();
110
    /// let rng2 = base2.clone();
111
    ///
112
    /// assert_eq!(rng1.u64(..), rng2.u64(..), "the cloned generators are identical");
113
    /// ```
114
0
    fn clone(&self) -> Rng {
115
0
        Rng::with_seed(self.gen_u64())
116
0
    }
117
}
118
119
impl Rng {
120
    /// Generates a random `u32`.
121
    #[inline]
122
27.9k
    fn gen_u32(&self) -> u32 {
123
27.9k
        self.gen_u64() as u32
124
27.9k
    }
<fastrand::Rng>::gen_u32
Line
Count
Source
122
27.9k
    fn gen_u32(&self) -> u32 {
123
27.9k
        self.gen_u64() as u32
124
27.9k
    }
Unexecuted instantiation: <fastrand::Rng>::gen_u32
125
126
    /// Generates a random `u64`.
127
    #[inline]
128
27.9k
    fn gen_u64(&self) -> u64 {
129
27.9k
        let s = self.0.get().wrapping_add(0xA0761D6478BD642F);
130
27.9k
        self.0.set(s);
131
27.9k
        let t = u128::from(s) * u128::from(s ^ 0xE7037ED1A0B428DB);
132
27.9k
        (t as u64) ^ (t >> 64) as u64
133
27.9k
    }
<fastrand::Rng>::gen_u64
Line
Count
Source
128
27.9k
    fn gen_u64(&self) -> u64 {
129
27.9k
        let s = self.0.get().wrapping_add(0xA0761D6478BD642F);
130
27.9k
        self.0.set(s);
131
27.9k
        let t = u128::from(s) * u128::from(s ^ 0xE7037ED1A0B428DB);
132
27.9k
        (t as u64) ^ (t >> 64) as u64
133
27.9k
    }
Unexecuted instantiation: <fastrand::Rng>::gen_u64
134
135
    /// Generates a random `u128`.
136
    #[inline]
137
0
    fn gen_u128(&self) -> u128 {
138
0
        (u128::from(self.gen_u64()) << 64) | u128::from(self.gen_u64())
139
0
    }
140
141
    /// Generates a random `u32` in `0..n`.
142
    #[inline]
143
27.9k
    fn gen_mod_u32(&self, n: u32) -> u32 {
144
        // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
145
27.9k
        let mut r = self.gen_u32();
146
27.9k
        let mut hi = mul_high_u32(r, n);
147
27.9k
        let mut lo = r.wrapping_mul(n);
148
27.9k
        if lo < n {
149
0
            let t = n.wrapping_neg() % n;
150
0
            while lo < t {
151
0
                r = self.gen_u32();
152
0
                hi = mul_high_u32(r, n);
153
0
                lo = r.wrapping_mul(n);
154
0
            }
155
27.9k
        }
156
27.9k
        hi
157
27.9k
    }
<fastrand::Rng>::gen_mod_u32
Line
Count
Source
143
27.9k
    fn gen_mod_u32(&self, n: u32) -> u32 {
144
        // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
145
27.9k
        let mut r = self.gen_u32();
146
27.9k
        let mut hi = mul_high_u32(r, n);
147
27.9k
        let mut lo = r.wrapping_mul(n);
148
27.9k
        if lo < n {
149
0
            let t = n.wrapping_neg() % n;
150
0
            while lo < t {
151
0
                r = self.gen_u32();
152
0
                hi = mul_high_u32(r, n);
153
0
                lo = r.wrapping_mul(n);
154
0
            }
155
27.9k
        }
156
27.9k
        hi
157
27.9k
    }
Unexecuted instantiation: <fastrand::Rng>::gen_mod_u32
158
159
    /// Generates a random `u64` in `0..n`.
160
    #[inline]
161
0
    fn gen_mod_u64(&self, n: u64) -> u64 {
162
        // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
163
0
        let mut r = self.gen_u64();
164
0
        let mut hi = mul_high_u64(r, n);
165
0
        let mut lo = r.wrapping_mul(n);
166
0
        if lo < n {
167
0
            let t = n.wrapping_neg() % n;
168
0
            while lo < t {
169
0
                r = self.gen_u64();
170
0
                hi = mul_high_u64(r, n);
171
0
                lo = r.wrapping_mul(n);
172
0
            }
173
0
        }
174
0
        hi
175
0
    }
176
177
    /// Generates a random `u128` in `0..n`.
178
    #[inline]
179
0
    fn gen_mod_u128(&self, n: u128) -> u128 {
180
        // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
181
0
        let mut r = self.gen_u128();
182
0
        let mut hi = mul_high_u128(r, n);
183
0
        let mut lo = r.wrapping_mul(n);
184
0
        if lo < n {
185
0
            let t = n.wrapping_neg() % n;
186
0
            while lo < t {
187
0
                r = self.gen_u128();
188
0
                hi = mul_high_u128(r, n);
189
0
                lo = r.wrapping_mul(n);
190
0
            }
191
0
        }
192
0
        hi
193
0
    }
194
}
195
196
thread_local! {
197
    static RNG: Rng = Rng(Cell::new({
198
        let mut hasher = DefaultHasher::new();
199
        Instant::now().hash(&mut hasher);
200
        thread::current().id().hash(&mut hasher);
201
        let hash = hasher.finish();
202
        (hash << 1) | 1
203
    }));
204
}
205
206
/// Computes `(a * b) >> 32`.
207
#[inline]
208
27.9k
fn mul_high_u32(a: u32, b: u32) -> u32 {
209
27.9k
    (((a as u64) * (b as u64)) >> 32) as u32
210
27.9k
}
fastrand::mul_high_u32
Line
Count
Source
208
27.9k
fn mul_high_u32(a: u32, b: u32) -> u32 {
209
27.9k
    (((a as u64) * (b as u64)) >> 32) as u32
210
27.9k
}
Unexecuted instantiation: fastrand::mul_high_u32
211
212
/// Computes `(a * b) >> 64`.
213
#[inline]
214
0
fn mul_high_u64(a: u64, b: u64) -> u64 {
215
0
    (((a as u128) * (b as u128)) >> 64) as u64
216
0
}
217
218
/// Computes `(a * b) >> 128`.
219
#[inline]
220
0
fn mul_high_u128(a: u128, b: u128) -> u128 {
221
    // Adapted from: https://stackoverflow.com/a/28904636
222
0
    let a_lo = a as u64 as u128;
223
0
    let a_hi = (a >> 64) as u64 as u128;
224
0
    let b_lo = b as u64 as u128;
225
0
    let b_hi = (b >> 64) as u64 as u128;
226
0
    let carry = (a_lo * b_lo) >> 64;
227
0
    let carry = ((a_hi * b_lo) as u64 as u128 + (a_lo * b_hi) as u64 as u128 + carry) >> 64;
228
0
    a_hi * b_hi + ((a_hi * b_lo) >> 64) + ((a_lo * b_hi) >> 64) + carry
229
0
}
230
231
macro_rules! rng_integer {
232
    ($t:tt, $unsigned_t:tt, $gen:tt, $mod:tt, $doc:tt) => {
233
        #[doc = $doc]
234
        ///
235
        /// Panics if the range is empty.
236
        #[inline]
237
27.9k
        pub fn $t(&self, range: impl RangeBounds<$t>) -> $t {
238
27.9k
            let panic_empty_range = || {
239
0
                panic!(
240
0
                    "empty range: {:?}..{:?}",
241
0
                    range.start_bound(),
242
0
                    range.end_bound()
Unexecuted instantiation: <fastrand::Rng>::u8::<core::ops::range::RangeTo<u8>>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::u32::<core::ops::range::RangeFull>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::u64::<core::ops::range::RangeFull>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::i8::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::u8::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::i16::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::i32::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::i64::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::u16::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::i128::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::u128::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::isize::<_>::{closure#0}
Unexecuted instantiation: <fastrand::Rng>::usize::<_>::{closure#0}
243
                )
244
            };
245
246
27.9k
            let low = match range.start_bound() {
247
27.9k
                Bound::Unbounded => std::$t::MIN,
248
0
                Bound::Included(&x) => x,
249
0
                Bound::Excluded(&x) => x.checked_add(1).unwrap_or_else(panic_empty_range),
250
            };
251
252
27.9k
            let high = match range.end_bound() {
253
0
                Bound::Unbounded => std::$t::MAX,
254
0
                Bound::Included(&x) => x,
255
27.9k
                Bound::Excluded(&x) => x.checked_sub(1).unwrap_or_else(panic_empty_range),
256
            };
257
258
27.9k
            if low > high {
259
0
                panic_empty_range();
260
27.9k
            }
261
262
27.9k
            if low == std::$t::MIN && high == std::$t::MAX {
263
0
                self.$gen() as $t
264
            } else {
265
27.9k
                let len = high.wrapping_sub(low).wrapping_add(1);
266
27.9k
                low.wrapping_add(self.$mod(len as $unsigned_t as _) as $t)
267
            }
268
27.9k
        }
<fastrand::Rng>::u8::<core::ops::range::RangeTo<u8>>
Line
Count
Source
237
27.9k
        pub fn $t(&self, range: impl RangeBounds<$t>) -> $t {
238
27.9k
            let panic_empty_range = || {
239
                panic!(
240
                    "empty range: {:?}..{:?}",
241
                    range.start_bound(),
242
                    range.end_bound()
243
                )
244
            };
245
246
27.9k
            let low = match range.start_bound() {
247
27.9k
                Bound::Unbounded => std::$t::MIN,
248
0
                Bound::Included(&x) => x,
249
0
                Bound::Excluded(&x) => x.checked_add(1).unwrap_or_else(panic_empty_range),
250
            };
251
252
27.9k
            let high = match range.end_bound() {
253
0
                Bound::Unbounded => std::$t::MAX,
254
0
                Bound::Included(&x) => x,
255
27.9k
                Bound::Excluded(&x) => x.checked_sub(1).unwrap_or_else(panic_empty_range),
256
            };
257
258
27.9k
            if low > high {
259
0
                panic_empty_range();
260
27.9k
            }
261
262
27.9k
            if low == std::$t::MIN && high == std::$t::MAX {
263
0
                self.$gen() as $t
264
            } else {
265
27.9k
                let len = high.wrapping_sub(low).wrapping_add(1);
266
27.9k
                low.wrapping_add(self.$mod(len as $unsigned_t as _) as $t)
267
            }
268
27.9k
        }
Unexecuted instantiation: <fastrand::Rng>::u32::<core::ops::range::RangeFull>
Unexecuted instantiation: <fastrand::Rng>::u64::<core::ops::range::RangeFull>
Unexecuted instantiation: <fastrand::Rng>::i8::<_>
Unexecuted instantiation: <fastrand::Rng>::u8::<_>
Unexecuted instantiation: <fastrand::Rng>::i16::<_>
Unexecuted instantiation: <fastrand::Rng>::i32::<_>
Unexecuted instantiation: <fastrand::Rng>::i64::<_>
Unexecuted instantiation: <fastrand::Rng>::u16::<_>
Unexecuted instantiation: <fastrand::Rng>::i128::<_>
Unexecuted instantiation: <fastrand::Rng>::u128::<_>
Unexecuted instantiation: <fastrand::Rng>::isize::<_>
Unexecuted instantiation: <fastrand::Rng>::usize::<_>
269
    };
270
}
271
272
impl Rng {
273
    /// Creates a new random number generator.
274
    #[inline]
275
0
    pub fn new() -> Rng {
276
0
        Rng::with_seed(
277
0
            RNG.try_with(|rng| rng.u64(..))
278
0
                .unwrap_or(0x4d595df4d0f33173),
279
        )
280
0
    }
281
282
    /// Creates a new random number generator with the initial seed.
283
    #[inline]
284
0
    pub fn with_seed(seed: u64) -> Self {
285
0
        let rng = Rng(Cell::new(0));
286
287
0
        rng.seed(seed);
288
0
        rng
289
0
    }
290
291
    /// Generates a random `char` in ranges a-z and A-Z.
292
    #[inline]
293
0
    pub fn alphabetic(&self) -> char {
294
        const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
295
0
        let len = CHARS.len() as u8;
296
0
        let i = self.u8(..len);
297
0
        CHARS[i as usize] as char
298
0
    }
299
300
    /// Generates a random `char` in ranges a-z, A-Z and 0-9.
301
    #[inline]
302
27.9k
    pub fn alphanumeric(&self) -> char {
303
        const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
304
27.9k
        let len = CHARS.len() as u8;
305
27.9k
        let i = self.u8(..len);
306
27.9k
        CHARS[i as usize] as char
307
27.9k
    }
<fastrand::Rng>::alphanumeric
Line
Count
Source
302
27.9k
    pub fn alphanumeric(&self) -> char {
303
        const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
304
27.9k
        let len = CHARS.len() as u8;
305
27.9k
        let i = self.u8(..len);
306
27.9k
        CHARS[i as usize] as char
307
27.9k
    }
Unexecuted instantiation: <fastrand::Rng>::alphanumeric
308
309
    /// Generates a random `bool`.
310
    #[inline]
311
0
    pub fn bool(&self) -> bool {
312
0
        self.u8(..) % 2 == 0
313
0
    }
314
315
    /// Generates a random digit in the given `base`.
316
    ///
317
    /// Digits are represented by `char`s in ranges 0-9 and a-z.
318
    ///
319
    /// Panics if the base is zero or greater than 36.
320
    #[inline]
321
0
    pub fn digit(&self, base: u32) -> char {
322
0
        if base == 0 {
323
0
            panic!("base cannot be zero");
324
0
        }
325
0
        if base > 36 {
326
0
            panic!("base cannot be larger than 36");
327
0
        }
328
0
        let num = self.u8(..base as u8);
329
0
        if num < 10 {
330
0
            (b'0' + num) as char
331
        } else {
332
0
            (b'a' + num - 10) as char
333
        }
334
0
    }
335
336
    /// Generates a random `f32` in range `0..1`.
337
0
    pub fn f32(&self) -> f32 {
338
0
        let b = 32;
339
0
        let f = std::f32::MANTISSA_DIGITS - 1;
340
0
        f32::from_bits((1 << (b - 2)) - (1 << f) + (self.u32(..) >> (b - f))) - 1.0
341
0
    }
342
343
    /// Generates a random `f64` in range `0..1`.
344
0
    pub fn f64(&self) -> f64 {
345
0
        let b = 64;
346
0
        let f = std::f64::MANTISSA_DIGITS - 1;
347
0
        f64::from_bits((1 << (b - 2)) - (1 << f) + (self.u64(..) >> (b - f))) - 1.0
348
0
    }
349
350
    rng_integer!(
351
        i8,
352
        u8,
353
        gen_u32,
354
        gen_mod_u32,
355
        "Generates a random `i8` in the given range."
356
    );
357
358
    rng_integer!(
359
        i16,
360
        u16,
361
        gen_u32,
362
        gen_mod_u32,
363
        "Generates a random `i16` in the given range."
364
    );
365
366
    rng_integer!(
367
        i32,
368
        u32,
369
        gen_u32,
370
        gen_mod_u32,
371
        "Generates a random `i32` in the given range."
372
    );
373
374
    rng_integer!(
375
        i64,
376
        u64,
377
        gen_u64,
378
        gen_mod_u64,
379
        "Generates a random `i64` in the given range."
380
    );
381
382
    rng_integer!(
383
        i128,
384
        u128,
385
        gen_u128,
386
        gen_mod_u128,
387
        "Generates a random `i128` in the given range."
388
    );
389
390
    #[cfg(target_pointer_width = "16")]
391
    rng_integer!(
392
        isize,
393
        usize,
394
        gen_u32,
395
        gen_mod_u32,
396
        "Generates a random `isize` in the given range."
397
    );
398
    #[cfg(target_pointer_width = "32")]
399
    rng_integer!(
400
        isize,
401
        usize,
402
        gen_u32,
403
        gen_mod_u32,
404
        "Generates a random `isize` in the given range."
405
    );
406
    #[cfg(target_pointer_width = "64")]
407
    rng_integer!(
408
        isize,
409
        usize,
410
        gen_u64,
411
        gen_mod_u64,
412
        "Generates a random `isize` in the given range."
413
    );
414
415
    /// Generates a random `char` in range a-z.
416
    #[inline]
417
0
    pub fn lowercase(&self) -> char {
418
        const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
419
0
        let len = CHARS.len() as u8;
420
0
        let i = self.u8(..len);
421
0
        CHARS[i as usize] as char
422
0
    }
423
424
    /// Initializes this generator with the given seed.
425
    #[inline]
426
0
    pub fn seed(&self, seed: u64) {
427
0
        self.0.set(seed);
428
0
    }
429
430
    /// Gives back **current** seed that is being held by this generator.
431
    #[inline]
432
0
    pub fn get_seed(&self) -> u64 {
433
0
        self.0.get()
434
0
    }
435
436
    /// Shuffles a slice randomly.
437
    #[inline]
438
0
    pub fn shuffle<T>(&self, slice: &mut [T]) {
439
0
        for i in 1..slice.len() {
440
0
            slice.swap(i, self.usize(..=i));
441
0
        }
442
0
    }
443
444
    rng_integer!(
445
        u8,
446
        u8,
447
        gen_u32,
448
        gen_mod_u32,
449
        "Generates a random `u8` in the given range."
450
    );
451
452
    rng_integer!(
453
        u16,
454
        u16,
455
        gen_u32,
456
        gen_mod_u32,
457
        "Generates a random `u16` in the given range."
458
    );
459
460
    rng_integer!(
461
        u32,
462
        u32,
463
        gen_u32,
464
        gen_mod_u32,
465
        "Generates a random `u32` in the given range."
466
    );
467
468
    rng_integer!(
469
        u64,
470
        u64,
471
        gen_u64,
472
        gen_mod_u64,
473
        "Generates a random `u64` in the given range."
474
    );
475
476
    rng_integer!(
477
        u128,
478
        u128,
479
        gen_u128,
480
        gen_mod_u128,
481
        "Generates a random `u128` in the given range."
482
    );
483
484
    #[cfg(target_pointer_width = "16")]
485
    rng_integer!(
486
        usize,
487
        usize,
488
        gen_u32,
489
        gen_mod_u32,
490
        "Generates a random `usize` in the given range."
491
    );
492
    #[cfg(target_pointer_width = "32")]
493
    rng_integer!(
494
        usize,
495
        usize,
496
        gen_u32,
497
        gen_mod_u32,
498
        "Generates a random `usize` in the given range."
499
    );
500
    #[cfg(target_pointer_width = "64")]
501
    rng_integer!(
502
        usize,
503
        usize,
504
        gen_u64,
505
        gen_mod_u64,
506
        "Generates a random `usize` in the given range."
507
    );
508
    #[cfg(target_pointer_width = "128")]
509
    rng_integer!(
510
        usize,
511
        usize,
512
        gen_u128,
513
        gen_mod_u128,
514
        "Generates a random `usize` in the given range."
515
    );
516
517
    /// Generates a random `char` in range A-Z.
518
    #[inline]
519
0
    pub fn uppercase(&self) -> char {
520
        const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
521
0
        let len = CHARS.len() as u8;
522
0
        let i = self.u8(..len);
523
0
        CHARS[i as usize] as char
524
0
    }
525
526
    /// Generates a random `char` in the given range.
527
    ///
528
    /// Panics if the range is empty.
529
    #[inline]
530
0
    pub fn char(&self, range: impl RangeBounds<char>) -> char {
531
        use std::convert::{TryFrom, TryInto};
532
533
0
        let panic_empty_range = || {
534
0
            panic!(
535
0
                "empty range: {:?}..{:?}",
536
0
                range.start_bound(),
537
0
                range.end_bound()
538
            )
539
        };
540
541
0
        let surrogate_start = 0xd800u32;
542
0
        let surrogate_len = 0x800u32;
543
544
0
        let low = match range.start_bound() {
545
0
            Bound::Unbounded => 0u8 as char,
546
0
            Bound::Included(&x) => x,
547
0
            Bound::Excluded(&x) => {
548
0
                let scalar = if x as u32 == surrogate_start - 1 {
549
0
                    surrogate_start + surrogate_len
550
                } else {
551
0
                    x as u32 + 1
552
                };
553
0
                char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
554
            }
555
        };
556
557
0
        let high = match range.end_bound() {
558
0
            Bound::Unbounded => std::char::MAX,
559
0
            Bound::Included(&x) => x,
560
0
            Bound::Excluded(&x) => {
561
0
                let scalar = if x as u32 == surrogate_start + surrogate_len {
562
0
                    surrogate_start - 1
563
                } else {
564
0
                    (x as u32).wrapping_sub(1)
565
                };
566
0
                char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
567
            }
568
        };
569
570
0
        if low > high {
571
0
            panic_empty_range();
572
0
        }
573
574
0
        let gap = if (low as u32) < surrogate_start && (high as u32) >= surrogate_start {
575
0
            surrogate_len
576
        } else {
577
0
            0
578
        };
579
0
        let range = high as u32 - low as u32 - gap;
580
0
        let mut val = self.u32(0..=range) + low as u32;
581
0
        if val >= surrogate_start {
582
0
            val += gap;
583
0
        }
584
0
        val.try_into().unwrap()
585
0
    }
586
}
587
588
/// Initializes the thread-local generator with the given seed.
589
#[inline]
590
0
pub fn seed(seed: u64) {
591
0
    RNG.with(|rng| rng.seed(seed))
592
0
}
593
594
/// Gives back **current** seed that is being held by the thread-local generator.
595
#[inline]
596
0
pub fn get_seed() -> u64 {
597
0
    RNG.with(|rng| rng.get_seed())
598
0
}
599
600
/// Generates a random `bool`.
601
#[inline]
602
0
pub fn bool() -> bool {
603
0
    RNG.with(|rng| rng.bool())
604
0
}
605
606
/// Generates a random `char` in ranges a-z and A-Z.
607
#[inline]
608
0
pub fn alphabetic() -> char {
609
0
    RNG.with(|rng| rng.alphabetic())
610
0
}
611
612
/// Generates a random `char` in ranges a-z, A-Z and 0-9.
613
#[inline]
614
27.9k
pub fn alphanumeric() -> char {
615
27.9k
    RNG.with(|rng| rng.alphanumeric())
fastrand::alphanumeric::{closure#0}
Line
Count
Source
615
27.9k
    RNG.with(|rng| rng.alphanumeric())
Unexecuted instantiation: fastrand::alphanumeric::{closure#0}
616
27.9k
}
fastrand::alphanumeric
Line
Count
Source
614
27.9k
pub fn alphanumeric() -> char {
615
27.9k
    RNG.with(|rng| rng.alphanumeric())
616
27.9k
}
Unexecuted instantiation: fastrand::alphanumeric
617
618
/// Generates a random `char` in range a-z.
619
#[inline]
620
0
pub fn lowercase() -> char {
621
0
    RNG.with(|rng| rng.lowercase())
622
0
}
623
624
/// Generates a random `char` in range A-Z.
625
#[inline]
626
0
pub fn uppercase() -> char {
627
0
    RNG.with(|rng| rng.uppercase())
628
0
}
629
630
/// Generates a random digit in the given `base`.
631
///
632
/// Digits are represented by `char`s in ranges 0-9 and a-z.
633
///
634
/// Panics if the base is zero or greater than 36.
635
#[inline]
636
0
pub fn digit(base: u32) -> char {
637
0
    RNG.with(|rng| rng.digit(base))
638
0
}
639
640
/// Shuffles a slice randomly.
641
#[inline]
642
0
pub fn shuffle<T>(slice: &mut [T]) {
643
0
    RNG.with(|rng| rng.shuffle(slice))
644
0
}
645
646
macro_rules! integer {
647
    ($t:tt, $doc:tt) => {
648
        #[doc = $doc]
649
        ///
650
        /// Panics if the range is empty.
651
        #[inline]
652
0
        pub fn $t(range: impl RangeBounds<$t>) -> $t {
653
0
            RNG.with(|rng| rng.$t(range))
Unexecuted instantiation: fastrand::i8::<_>::{closure#0}
Unexecuted instantiation: fastrand::u8::<_>::{closure#0}
Unexecuted instantiation: fastrand::i16::<_>::{closure#0}
Unexecuted instantiation: fastrand::i32::<_>::{closure#0}
Unexecuted instantiation: fastrand::i64::<_>::{closure#0}
Unexecuted instantiation: fastrand::u16::<_>::{closure#0}
Unexecuted instantiation: fastrand::u32::<_>::{closure#0}
Unexecuted instantiation: fastrand::u64::<_>::{closure#0}
Unexecuted instantiation: fastrand::char::<_>::{closure#0}
Unexecuted instantiation: fastrand::i128::<_>::{closure#0}
Unexecuted instantiation: fastrand::u128::<_>::{closure#0}
Unexecuted instantiation: fastrand::isize::<_>::{closure#0}
Unexecuted instantiation: fastrand::usize::<_>::{closure#0}
654
0
        }
Unexecuted instantiation: fastrand::i8::<_>
Unexecuted instantiation: fastrand::u8::<_>
Unexecuted instantiation: fastrand::i16::<_>
Unexecuted instantiation: fastrand::i32::<_>
Unexecuted instantiation: fastrand::i64::<_>
Unexecuted instantiation: fastrand::u16::<_>
Unexecuted instantiation: fastrand::u32::<_>
Unexecuted instantiation: fastrand::u64::<_>
Unexecuted instantiation: fastrand::char::<_>
Unexecuted instantiation: fastrand::i128::<_>
Unexecuted instantiation: fastrand::u128::<_>
Unexecuted instantiation: fastrand::isize::<_>
Unexecuted instantiation: fastrand::usize::<_>
655
    };
656
}
657
658
integer!(u8, "Generates a random `u8` in the given range.");
659
integer!(i8, "Generates a random `i8` in the given range.");
660
integer!(u16, "Generates a random `u16` in the given range.");
661
integer!(i16, "Generates a random `i16` in the given range.");
662
integer!(u32, "Generates a random `u32` in the given range.");
663
integer!(i32, "Generates a random `i32` in the given range.");
664
integer!(u64, "Generates a random `u64` in the given range.");
665
integer!(i64, "Generates a random `i64` in the given range.");
666
integer!(u128, "Generates a random `u128` in the given range.");
667
integer!(i128, "Generates a random `i128` in the given range.");
668
integer!(usize, "Generates a random `usize` in the given range.");
669
integer!(isize, "Generates a random `isize` in the given range.");
670
integer!(char, "Generates a random `char` in the given range.");
671
672
/// Generates a random `f32` in range `0..1`.
673
0
pub fn f32() -> f32 {
674
0
    RNG.with(|rng| rng.f32())
675
0
}
676
677
/// Generates a random `f64` in range `0..1`.
678
0
pub fn f64() -> f64 {
679
0
    RNG.with(|rng| rng.f64())
680
0
}