Skip to main content

emit_core/
rng.rs

1/*!
2The [`Rng`] type.
3*/
4
5use crate::empty::Empty;
6
7/**
8A non-cryptographic source of randomness.
9*/
10pub trait Rng {
11    /**
12    Fill a buffer with random data.
13
14    This method may return `None` if the buffer couldn't be filled with random data for any reason.
15
16    The buffer is expected to have a consistent implementation of `AsMut` that always returns a reference to the same underlying bytes. This isn't required for safety, but can lead to unexpected results.
17    */
18    fn fill<A: AsMut<[u8]>>(&self, arr: A) -> Option<A>;
19
20    /**
21    Get a random 64bit number.
22    */
23    fn gen_u64(&self) -> Option<u64> {
24        self.fill([0; 8]).map(u64::from_le_bytes)
25    }
26
27    /**
28    Get a random 128bit number.
29    */
30    fn gen_u128(&self) -> Option<u128> {
31        self.fill([0; 16]).map(u128::from_le_bytes)
32    }
33}
34
35impl<'a, T: Rng + ?Sized> Rng for &'a T {
36    fn fill<A: AsMut<[u8]>>(&self, arr: A) -> Option<A> {
37        (**self).fill(arr)
38    }
39
40    fn gen_u64(&self) -> Option<u64> {
41        (**self).gen_u64()
42    }
43
44    fn gen_u128(&self) -> Option<u128> {
45        (**self).gen_u128()
46    }
47}
48
49impl<'a, T: Rng> Rng for Option<T> {
50    fn fill<A: AsMut<[u8]>>(&self, arr: A) -> Option<A> {
51        self.as_ref().and_then(|id| id.fill(arr))
52    }
53
54    fn gen_u64(&self) -> Option<u64> {
55        self.as_ref().and_then(|id| id.gen_u64())
56    }
57
58    fn gen_u128(&self) -> Option<u128> {
59        self.as_ref().and_then(|id| id.gen_u128())
60    }
61}
62
63#[cfg(feature = "alloc")]
64impl<'a, T: Rng + ?Sized + 'a> Rng for alloc::boxed::Box<T> {
65    fn fill<A: AsMut<[u8]>>(&self, arr: A) -> Option<A> {
66        (**self).fill(arr)
67    }
68
69    fn gen_u64(&self) -> Option<u64> {
70        (**self).gen_u64()
71    }
72
73    fn gen_u128(&self) -> Option<u128> {
74        (**self).gen_u128()
75    }
76}
77
78#[cfg(feature = "alloc")]
79impl<'a, T: Rng + ?Sized + 'a> Rng for alloc::sync::Arc<T> {
80    fn fill<A: AsMut<[u8]>>(&self, arr: A) -> Option<A> {
81        (**self).fill(arr)
82    }
83
84    fn gen_u64(&self) -> Option<u64> {
85        (**self).gen_u64()
86    }
87
88    fn gen_u128(&self) -> Option<u128> {
89        (**self).gen_u128()
90    }
91}
92
93impl Rng for Empty {
94    fn fill<A: AsMut<[u8]>>(&self, _: A) -> Option<A> {
95        None
96    }
97}
98
99mod internal {
100    pub trait DispatchRng {
101        fn dispatch_gen(&self, arr: &mut [u8]) -> bool;
102        fn dispatch_gen_u64(&self) -> Option<u64>;
103        fn dispatch_gen_u128(&self) -> Option<u128>;
104    }
105
106    pub trait SealedRng {
107        fn erase_rng(&self) -> crate::internal::Erased<&dyn DispatchRng>;
108    }
109}
110
111/**
112An object-safe [`Rng`].
113
114A `dyn ErasedRng` can be treated as `impl Rng`.
115*/
116pub trait ErasedRng: internal::SealedRng {}
117
118impl<T: Rng> ErasedRng for T {}
119
120impl<T: Rng> internal::SealedRng for T {
121    fn erase_rng(&self) -> crate::internal::Erased<&dyn internal::DispatchRng> {
122        crate::internal::Erased(self)
123    }
124}
125
126impl<T: Rng> internal::DispatchRng for T {
127    fn dispatch_gen(&self, arr: &mut [u8]) -> bool {
128        self.fill(arr).is_some()
129    }
130
131    fn dispatch_gen_u64(&self) -> Option<u64> {
132        self.gen_u64()
133    }
134
135    fn dispatch_gen_u128(&self) -> Option<u128> {
136        self.gen_u128()
137    }
138}
139
140impl<'a> Rng for dyn ErasedRng + 'a {
141    fn fill<A: AsMut<[u8]>>(&self, mut arr: A) -> Option<A> {
142        if self.erase_rng().0.dispatch_gen(arr.as_mut()) {
143            Some(arr)
144        } else {
145            None
146        }
147    }
148
149    fn gen_u64(&self) -> Option<u64> {
150        self.erase_rng().0.dispatch_gen_u64()
151    }
152
153    fn gen_u128(&self) -> Option<u128> {
154        self.erase_rng().0.dispatch_gen_u128()
155    }
156}
157
158impl<'a> Rng for dyn ErasedRng + Send + Sync + 'a {
159    fn fill<A: AsMut<[u8]>>(&self, arr: A) -> Option<A> {
160        (self as &(dyn ErasedRng + 'a)).fill(arr)
161    }
162
163    fn gen_u64(&self) -> Option<u64> {
164        (self as &(dyn ErasedRng + 'a)).gen_u64()
165    }
166
167    fn gen_u128(&self) -> Option<u128> {
168        (self as &(dyn ErasedRng + 'a)).gen_u128()
169    }
170}
171
172#[cfg(test)]
173mod tests {
174    use super::*;
175
176    struct MyRng {
177        fill: u8,
178    }
179
180    impl Rng for MyRng {
181        fn fill<A: AsMut<[u8]>>(&self, mut arr: A) -> Option<A> {
182            for b in arr.as_mut() {
183                *b = self.fill;
184            }
185
186            Some(arr)
187        }
188    }
189
190    #[test]
191    fn gen() {
192        for (rng, expected_u64, expected_u128) in [
193            (MyRng { fill: 0 }, 0u64, 0u128),
194            (MyRng { fill: u8::MAX }, u64::MAX, u128::MAX),
195        ] {
196            assert_eq!(expected_u64, rng.gen_u64().unwrap());
197            assert_eq!(expected_u128, rng.gen_u128().unwrap());
198        }
199    }
200
201    #[test]
202    fn option_rng() {
203        for (rng, expected) in [(Some(MyRng { fill: 42 }), Some([42u8, 42])), (None, None)] {
204            assert_eq!(expected, rng.fill([0, 0]));
205        }
206    }
207
208    #[test]
209    fn erased_rng() {
210        let rng = MyRng { fill: 42 };
211
212        let rng = &rng as &dyn ErasedRng;
213
214        assert_eq!([42, 42], rng.fill([0, 0]).unwrap());
215    }
216}