193
193
#[ macro_use]
194
194
extern crate cfg_if;
195
195
196
- use crate :: util:: { slice_as_uninit_mut, slice_assume_init_mut} ;
196
+ use crate :: util:: { slice_as_uninit_mut, slice_assume_init_mut, uninit_as_bytes_mut } ;
197
197
use core:: mem:: MaybeUninit ;
198
198
199
199
mod error;
@@ -364,6 +364,57 @@ impl Options {
364
364
// SAFETY: `dest` has been fully initialized by `imp::getrandom_inner`
365
365
Ok ( unsafe { slice_assume_init_mut ( dest) } )
366
366
}
367
+
368
+ /// Return an array of random bytes.
369
+ ///
370
+ /// Supports returning `u8` arrays and _arbitrary levels_ of nested byte
371
+ /// arrays. Requires Rust 1.51 or later (due to the use of const generics).
372
+ ///
373
+ /// # Examples
374
+ /// ```
375
+ /// use getrandom::{Error, Options};
376
+ /// fn tls_hello_random() -> Result<[u8; 32], Error> {
377
+ /// Options::DEFAULT.array()
378
+ /// }
379
+ /// # tls_hello_random().unwrap();
380
+ /// ```
381
+ ///
382
+ /// The nested array support can be used to safely and efficiently construct
383
+ /// random values of types other than byte arrays:
384
+ /// ```
385
+ /// # use getrandom::{Error, Options};
386
+ /// # fn u32_array_example() -> Result<(), Error> {
387
+ /// let random_u32s: [u32; 4] = Options::DEFAULT.array()?.map(u32::from_ne_bytes);
388
+ /// # Ok(())
389
+ /// # }
390
+ /// # u32_array_example().unwrap();
391
+ /// ```
392
+ ///
393
+ /// Multiple levels of array nesting can be used to construct more
394
+ /// complicated types, though some type annotations are needed:
395
+ /// ```
396
+ /// # #![feature(portable_simd)]
397
+ /// use std::simd::Simd;
398
+ /// # use getrandom::{Error, Options};
399
+ /// # fn simd_array_example() -> Result<(), Error> {
400
+ /// let random_vectors: [Simd<u32, 8>; 16] = Options::DEFAULT
401
+ /// .array()?
402
+ /// .map(|bytes: [_; 8]| bytes.map(u32::from_ne_bytes))
403
+ /// .map(Simd::from);
404
+ /// # Ok(())
405
+ /// # }
406
+ /// # simd_array_example().unwrap();
407
+ /// ```
408
+ #[ cfg( getrandom_const_generics) ]
409
+ #[ inline]
410
+ pub fn array < T : ArrayElement , const N : usize > ( self ) -> Result < [ T ; N ] , Error > {
411
+ let mut uninit: MaybeUninit < [ T ; N ] > = MaybeUninit :: uninit ( ) ;
412
+ imp:: getrandom_inner ( uninit_as_bytes_mut ( & mut uninit) ) ?;
413
+
414
+ // SAFETY: uninit was entirely initalized by imp::getrandom_inner, and
415
+ // any sequence of initialized bytes is valid for any ArrayElement type.
416
+ Ok ( unsafe { uninit. assume_init ( ) } )
417
+ }
367
418
}
368
419
369
420
// TODO(MSRV 1.62): Use #[derive(Default)]
@@ -372,3 +423,24 @@ impl Default for Options {
372
423
Self :: DEFAULT
373
424
}
374
425
}
426
+
427
+ /// A type supported by [Options::array] that can be initialized with random data.
428
+ ///
429
+ /// # Safety
430
+ ///
431
+ /// Any type which implements ArrayElementmust ensure that any sequence of bytes
432
+ /// is a valid representation for that type. For example, it is safe to have
433
+ /// `[u8; 6]` implement this trait, but not `bool`.
434
+ #[ cfg( getrandom_const_generics) ]
435
+ pub unsafe trait ArrayElement : private:: Sealed { }
436
+
437
+ #[ cfg( getrandom_const_generics) ]
438
+ mod private {
439
+ use super :: ArrayElement ;
440
+ pub trait Sealed { }
441
+
442
+ impl Sealed for u8 { }
443
+ unsafe impl ArrayElement for u8 { }
444
+ impl < A : ArrayElement , const N : usize > Sealed for [ A ; N ] { }
445
+ unsafe impl < A : ArrayElement , const N : usize > ArrayElement for [ A ; N ] { }
446
+ }
0 commit comments