193193#[ macro_use]
194194extern crate cfg_if;
195195
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 } ;
197197use core:: mem:: MaybeUninit ;
198198
199199mod error;
@@ -364,6 +364,57 @@ impl Options {
364364 // SAFETY: `dest` has been fully initialized by `imp::getrandom_inner`
365365 Ok ( unsafe { slice_assume_init_mut ( dest) } )
366366 }
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+ }
367418}
368419
369420// TODO(MSRV 1.62): Use #[derive(Default)]
@@ -372,3 +423,24 @@ impl Default for Options {
372423 Self :: DEFAULT
373424 }
374425}
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