random_trait/
lib.rs

1#![no_std]
2#![recursion_limit = "130"]
3#![deny(missing_docs)]
4#![cfg_attr(test, deny(warnings))]
5
6//! # Random Trait
7//!
8//! This crate provides a simple thin trait for producing generic random values based on any random source.
9//! The crates assurances are based on the assurances of the RNG it is implemented on.<br>
10//! if that RNG is cryptographically secure then this crate should provide a cryptographically secure numbers. (including floats)
11//! if the RNG is biased (which is fine for tests and some other applications) then the results will also be bias.
12//! This crate **does not** try to compensate for biases in the RNG source.
13//!
14//! please see the [`GenerateRand`](trait.GenerateRand.html) and [`Random`](trait.Random.html) for more information and examples.
15//!
16
17use core::{char, mem};
18
19#[cfg(feature = "doc-comment")]
20extern crate doc_comment;
21#[cfg(feature = "doc-comment")]
22doc_comment::doctest!("../README.md");
23
24/// This trait is used by `Random::gen()` as a generic function to create a random value for any type which implements it.
25/// I try to give by default implementations for all the types in libcore, including arrays and tuples, if anything is missing please raise the issue.
26/// You can implement this for any of your types.
27/// # Examples
28/// ```rust
29/// use random_trait::{Random, GenerateRand};
30/// struct MyStuff{
31///     a: u64,
32///     b: char,
33/// }
34///
35/// impl GenerateRand for MyStuff {
36///     fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
37///         MyStuff {a: rand.gen(), b: rand.gen() }
38///     }
39/// }
40/// ```
41///
42pub trait GenerateRand {
43    /// Generate a random value, using the `rand` as source of randomness.
44    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self;
45}
46
47///
48/// This is the base trait of the crate. By implementing the required method on your random generator source
49/// it will give you a long list of functions, the important of them is `Random::gen() -> T` which will produce a random value
50/// for every type which implements `GenerateRand` (you can implement this for your own types).
51///
52/// Notice that some random sources can produce non byte-array values with more efficiency, so if you want to use that
53/// you can just override a provided method and use the random source directly.
54///
55/// If your random source is fallable in a way that can be handled please also implement `fill_bytes` and handle the errors properly.
56/// otherwise it will panic.
57///
58/// # Example
59/// ```rust
60/// use random_trait::{Random, GenerateRand};
61///
62/// #[derive(Default)]
63/// struct MyRandomGenerator {
64///     ctr: usize,
65/// }
66///
67/// impl Random for MyRandomGenerator {
68///     type Error = ();
69///     fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
70///         for e in buf.iter_mut() {
71///             *e = self.ctr as u8;
72///             self.ctr += 1;
73///         }
74///         Ok(())
75///     }
76/// }
77///
78/// # fn main() {
79/// let mut rand = MyRandomGenerator::default();
80/// let rand_u32: u32 = rand.gen();
81/// assert_eq!(rand_u32, 50462976);
82/// let rand_u32: u32 = rand.gen();
83/// assert_eq!(rand_u32, 117835012);
84/// # }
85/// ```
86///
87pub trait Random {
88    /// The Error type, based on the source of randomness, non fallible sources can use `Error=()`
89    type Error;
90
91    /// This is the main method of the trait.
92    /// You should implement this on your randomness source and will the buffer with random data.
93    fn try_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), Self::Error>;
94
95    /// Uses `try_fill_bytes` but panics if returns an error.
96    /// Override if you can gracefully handle errors in the randomness source.
97    fn fill_bytes(&mut self, buf: &mut [u8]) {
98        if self.try_fill_bytes(buf).is_err() {
99            panic!("Failed getting randmness");
100        }
101    }
102
103    /// Returns a generic random value which implements `GenerateRand`
104    fn gen<T: GenerateRand>(&mut self) -> T {
105        T::generate(self)
106    }
107
108    /// Returns a random `u8` number.
109    fn get_u8(&mut self) -> u8 {
110        let mut buf = [0u8; 1];
111        self.fill_bytes(&mut buf);
112        buf[0]
113    }
114
115    /// Returns a random `u16` number.
116    fn get_u16(&mut self) -> u16 {
117        let mut buf = [0u8; 2];
118        self.fill_bytes(&mut buf);
119        unsafe { mem::transmute(buf) }
120    }
121
122    /// Returns a random `u32` number.
123    fn get_u32(&mut self) -> u32 {
124        let mut buf = [0u8; 4];
125        self.fill_bytes(&mut buf);
126        unsafe { mem::transmute(buf) }
127    }
128
129    /// Returns a random `u64` number.
130    fn get_u64(&mut self) -> u64 {
131        let mut buf = [0u8; 8];
132        self.fill_bytes(&mut buf);
133        unsafe { mem::transmute(buf) }
134    }
135
136    /// Returns a random `usize` number.
137    #[cfg(target_pointer_width = "64")]
138    fn get_usize(&mut self) -> usize {
139        self.get_u64() as usize
140    }
141
142    /// Returns a random `usize` number.
143    #[cfg(target_pointer_width = "32")]
144    fn get_usize(&mut self) -> usize {
145        self.get_u32() as usize
146    }
147
148    /// Returns a random `usize` number.
149    #[cfg(target_pointer_width = "16")]
150    fn get_usize(&mut self) -> usize {
151        self.get_u16() as usize
152    }
153
154    /// Returns a random `u128` number.
155    #[cfg(feature = "u128")]
156    fn get_u128(&mut self) -> u128 {
157        let mut buf = [0u8; 16];
158        self.fill_bytes(&mut buf);
159        unsafe { mem::transmute(buf) }
160    }
161
162    /// Returns a random `bool` with 50/50 probability.
163    fn get_bool(&mut self) -> bool {
164        // TODO: More research, least/most significant bit?
165        let bit = self.get_u8() & 0b1000_0000;
166        debug_assert!(bit < 2);
167        bit == 1
168    }
169}
170
171impl GenerateRand for u8 {
172    #[inline]
173    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
174        rand.get_u8()
175    }
176}
177
178impl GenerateRand for u16 {
179    #[inline]
180    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
181        rand.get_u16()
182    }
183}
184
185impl GenerateRand for u32 {
186    #[inline]
187    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
188        rand.get_u32()
189    }
190}
191
192impl GenerateRand for u64 {
193    #[inline]
194    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
195        rand.get_u64()
196    }
197}
198
199impl GenerateRand for usize {
200    #[inline]
201    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
202        rand.get_usize()
203    }
204}
205
206#[cfg(feature = "u128")]
207impl GenerateRand for u128 {
208    #[inline]
209    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
210        rand.get_u128()
211    }
212}
213
214impl GenerateRand for char {
215    #[inline]
216    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
217        loop {
218            if let Some(c) = char::from_u32(rand.get_u32()) {
219                return c;
220            }
221        }
222    }
223}
224
225impl GenerateRand for bool {
226    #[inline]
227    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
228        rand.get_bool()
229    }
230}
231
232// Source: https://mumble.net/~campbell/2014/04/28/uniform-random-float
233// https://mumble.net/~campbell/2014/04/28/random_real.c
234impl GenerateRand for f64 {
235    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
236        let mut exponent: i32 = -64;
237        let mut significand = rand.get_u64();
238        while significand == 0 {
239            exponent -= 64;
240            if exponent < -1074i32 {
241                // E min(-1022)-p(53)+1  (https://en.wikipedia.org/wiki/IEEE_754)
242                // In reallity this should probably never happen. prob of ~1/(2^1024) unless randomness is broken.
243                unreachable!("The randomness is broken, got 0 16 times. (prob of 1/2^1024)");
244            }
245            significand = rand.get_u64();
246        }
247
248        // Shift the leading zeros into the exponent
249        let shift = significand.leading_zeros() as i32;
250        if shift > 0 {
251            exponent -= shift;
252            significand <<= shift;
253            significand |= rand.get_u64() >> (64 - shift);
254        }
255        // Set the sticky bit.
256        significand |= 1;
257
258        // Convert to float and scale by 2^exponent.
259        significand as f64 * exp2(exponent)
260    }
261}
262
263// Source: https://mumble.net/~campbell/2014/04/28/uniform-random-float
264// https://mumble.net/~campbell/2014/04/28/random_real.c
265impl GenerateRand for f32 {
266    fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
267        let mut exponent: i32 = -32;
268        let mut significand = rand.get_u32();
269        while significand == 0 {
270            exponent -= 32;
271            if exponent < -149i32 {
272                // E min(-126)-p(24)+1  (https://en.wikipedia.org/wiki/IEEE_754)
273                // In reallity this should probably never happen. prob of ~1/(2^1024) unless randomness is broken.
274                unreachable!("The randomness is broken, got 0 5 times. (prob of 1/2^160)");
275                // TODO: Should this stay unreachable or change to return 0?
276            }
277            significand = rand.get_u32();
278        }
279
280        // Shift the leading zeros into the exponent
281        let shift = significand.leading_zeros() as i32;
282        if shift != 0 {
283            exponent -= shift;
284            significand <<= shift;
285            significand |= rand.get_u32() >> (32 - shift);
286        }
287        // Set the sticky bit, almost definitely another 1 in the random stream.
288        significand |= 1;
289
290        // Convert to float and scale by 2^exponent.
291        significand as f32 * exp2f(exponent)
292    }
293}
294
295/// This is from IEEE-754.
296/// you take the E max, subtract the exponent from it, and shift it according to the precision-1
297fn exp2f(exp: i32) -> f32 {
298    debug_assert!(exp > -127);
299    let bits = ((127i32 + exp) as u32) << 23u32;
300    unsafe { mem::transmute(bits) } // this is the same as `f32::from_bits`
301}
302fn exp2(exp: i32) -> f64 {
303    debug_assert!(exp > -1023);
304    let bits = ((1023i32 + exp) as u64) << 52u64;
305    unsafe { mem::transmute(bits) } // this is the same as `f64::from_bits`
306}
307
308// Will overflow(i.e. sign extend) correctly https://doc.rust-lang.org/nomicon/casts.html.
309// should only be used with the same type.
310macro_rules! impl_generate_rand_ifromu {
311    ($ity:ty, $uty: ty) => {
312        impl GenerateRand for $ity {
313            #[inline]
314            fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
315                debug_assert_eq!(mem::size_of::<$ity>(), mem::size_of::<$uty>());
316                <$uty>::generate(rand) as $ity
317            }
318        }
319    };
320}
321
322impl_generate_rand_ifromu! {i8, u8}
323impl_generate_rand_ifromu! {i16, u16}
324impl_generate_rand_ifromu! {i32, u32}
325impl_generate_rand_ifromu! {i64, u64}
326impl_generate_rand_ifromu! {isize, usize}
327#[cfg(feature = "u128")]
328impl_generate_rand_ifromu! {i128, u128}
329
330// the reason for both $t and $ts is that this way each iteration it's reducing the amount of variables by one
331macro_rules! array_impls {
332    {$N:expr, $t:ident $($ts:ident)*} => {
333            impl<T: GenerateRand> GenerateRand for [T; $N] {
334                #[inline]
335                fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
336                    [rand.gen::<$t>(), $(rand.gen::<$ts>()),*]
337                }
338            }
339            array_impls!{($N - 1), $($ts)*}
340    };
341    {$N:expr,} => {
342        impl<T: GenerateRand> GenerateRand for [T; $N] {
343            #[inline]
344            fn generate<R: Random + ?Sized>(_: &mut R) -> Self { [] }
345        }
346    };
347}
348
349array_impls! {128, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T
350T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
351
352macro_rules! tuple_impls {
353    ($(
354        ($($T:ident),+),
355    )+) => {
356        $(
357            impl<$($T: GenerateRand),+> GenerateRand for ($($T,)+) {
358                #[inline]
359                fn generate<R: Random + ?Sized>(rand: &mut R) -> Self {
360                    ($({ let x: $T = rand.gen(); x},)+)
361                }
362            }
363        )+
364    }
365}
366
367tuple_impls! {
368    (A),
369    (A, B),
370    (A, B, C),
371    (A, B, C, D),
372    (A, B, C, D, E),
373    (A, B, C, D, E, F),
374    (A, B, C, D, E, F, G),
375    (A, B, C, D, E, F, G, H),
376    (A, B, C, D, E, F, G, H, I),
377    (A, B, C, D, E, F, G, H, I, J),
378    (A, B, C, D, E, F, G, H, I, J, K),
379    (A, B, C, D, E, F, G, H, I, J, K, L),
380    (A, B, C, D, E, F, G, H, I, J, K, L, M),
381    (A, B, C, D, E, F, G, H, I, J, K, L, M, N),
382    (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O),
383    (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P),
384}