187
187
#[ macro_use]
188
188
extern crate cfg_if;
189
189
190
+ use crate :: util:: { slice_as_uninit_mut, slice_assume_init_mut} ;
191
+ use core:: mem:: MaybeUninit ;
192
+
190
193
mod error;
191
194
mod util;
192
195
// To prevent a breaking change when targets are added, we always export the
@@ -200,7 +203,8 @@ pub use crate::error::Error;
200
203
201
204
// System-specific implementations.
202
205
//
203
- // These should all provide getrandom_inner with the same signature as getrandom.
206
+ // These should all provide getrandom_inner with the signature
207
+ // `fn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error>`.
204
208
cfg_if ! {
205
209
if #[ cfg( any( target_os = "emscripten" , target_os = "haiku" ,
206
210
target_os = "redox" ) ) ] {
@@ -284,9 +288,34 @@ cfg_if! {
284
288
/// In general, `getrandom` will be fast enough for interactive usage, though
285
289
/// significantly slower than a user-space CSPRNG; for the latter consider
286
290
/// [`rand::thread_rng`](https://docs.rs/rand/*/rand/fn.thread_rng.html).
291
+ #[ inline]
287
292
pub fn getrandom ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
288
- if dest. is_empty ( ) {
289
- return Ok ( ( ) ) ;
290
- }
291
- imp:: getrandom_inner ( dest)
293
+ // SAFETY: The `&mut MaybeUninit<_>` reference doesn't escape.
294
+ getrandom_uninit_slice ( unsafe { slice_as_uninit_mut ( dest) } ) . map ( |_| ( ) )
295
+ }
296
+
297
+ /// Version of the `getrandom` function which fills `dest` with random bytes
298
+ /// returns a mutable reference to those bytes.
299
+ ///
300
+ /// On successful completion this function is guaranteed to return a slice
301
+ /// which points to the same memory as `dest` and has the same length.
302
+ /// In other words, it's safe to assume that `dest` is initialized after
303
+ /// this function has returned `Ok`.
304
+ ///
305
+ /// # Examples
306
+ ///
307
+ /// ```ignore
308
+ /// # // We ignore this test since `uninit_array` is unstable.
309
+ /// #![feature(maybe_uninit_uninit_array)]
310
+ /// # fn main() -> Result<(), getrandom::Error> {
311
+ /// let mut buf = core::mem::MaybeUninit::uninit_array::<1024>();
312
+ /// let buf: &mut [u8] = getrandom::getrandom_uninit_slice(&mut buf)?;
313
+ /// # Ok(()) }
314
+ /// ```
315
+ #[ inline]
316
+ pub fn getrandom_uninit_slice ( dest : & mut [ MaybeUninit < u8 > ] ) -> Result < & mut [ u8 ] , Error > {
317
+ imp:: getrandom_inner ( dest) ?;
318
+ // SAFETY: `dest` has been fully initialized by `imp::getrandom_inner`
319
+ // since it returned `Ok`.
320
+ Ok ( unsafe { slice_assume_init_mut ( dest) } )
292
321
}
0 commit comments