11use crate :: io;
2+ use crate :: lazy;
23use crate :: mem;
3- use crate :: sync;
44use crate :: sys:: c;
55
6- // The kinds of HashMap RNG that may be available
6+ /// The kinds of HashMap RNG that may be available
77#[ derive( Clone , Copy , Debug , PartialEq ) ]
88enum HashMapRng {
99 Preferred ,
@@ -16,44 +16,35 @@ pub fn hashmap_random_keys() -> (u64, u64) {
1616 preferred_rng ( ) . expect ( "couldn't generate random bytes with preferred RNG" )
1717 }
1818 HashMapRng :: Fallback => {
19- fallback_rng ( ) . unwrap ( ) . expect ( "couldn't generate random bytes with fallback RNG" )
19+ fallback_rng ( ) . expect ( "couldn't generate random bytes with fallback RNG" )
2020 }
2121 }
2222}
2323
24- // Returns the HashMap RNG that should be used
25- //
26- // Panics if they are both broken
24+ /// Returns the HashMap RNG that should be used
25+ ///
26+ /// Panics if they are both broken
2727fn get_hashmap_rng ( ) -> HashMapRng {
2828 // Assume that if the preferred RNG is broken the first time we use it, it likely means
2929 // that: the DLL has failed to load, there is no point to calling it over-and-over again,
3030 // and we should cache the result
31- static INIT : sync:: Once = sync:: Once :: new ( ) ;
32- static mut HASHMAP_RNG : HashMapRng = HashMapRng :: Preferred ;
33-
34- unsafe {
35- INIT . call_once ( || HASHMAP_RNG = choose_hashmap_rng ( ) ) ;
36- HASHMAP_RNG
37- }
31+ static VALUE : lazy:: SyncOnceCell < HashMapRng > = lazy:: SyncOnceCell :: new ( ) ;
32+ * VALUE . get_or_init ( choose_hashmap_rng)
3833}
3934
40- // Test whether we should use the preferred or fallback RNG
41- //
42- // If the preferred RNG is successful, we choose it. Otherwise, if the fallback RNG is successful,
43- // we choose that
44- //
45- // Panics if both the preferred and the fallback RNG are both non-functional
35+ /// Test whether we should use the preferred or fallback RNG
36+ ///
37+ /// If the preferred RNG is successful, we choose it. Otherwise, if the fallback RNG is successful,
38+ /// we choose that
39+ ///
40+ /// Panics if both the preferred and the fallback RNG are both non-functional
4641fn choose_hashmap_rng ( ) -> HashMapRng {
4742 let preferred_error = match preferred_rng ( ) {
4843 Ok ( _) => return HashMapRng :: Preferred ,
4944 Err ( e) => e,
5045 } ;
5146
52- // On UWP, there is no fallback
53- let fallback_result = fallback_rng ( )
54- . unwrap_or_else ( || panic ! ( "preferred RNG broken: `{}`, no fallback" , preferred_error) ) ;
55-
56- match fallback_result {
47+ match fallback_rng ( ) {
5748 Ok ( _) => return HashMapRng :: Fallback ,
5849 Err ( fallback_error) => panic ! (
5950 "preferred RNG broken: `{}`, fallback RNG broken: `{}`" ,
@@ -62,7 +53,7 @@ fn choose_hashmap_rng() -> HashMapRng {
6253 }
6354}
6455
65- // Generate random numbers using the preferred RNG function (BCryptGenRandom)
56+ /// Generate random numbers using the preferred RNG function (BCryptGenRandom)
6657fn preferred_rng ( ) -> Result < ( u64 , u64 ) , io:: Error > {
6758 use crate :: ptr;
6859
@@ -79,18 +70,18 @@ fn preferred_rng() -> Result<(u64, u64), io::Error> {
7970 if ret == 0 { Ok ( v) } else { Err ( io:: Error :: last_os_error ( ) ) }
8071}
8172
82- // Generate random numbers using the fallback RNG function (RtlGenRandom)
73+ /// Generate random numbers using the fallback RNG function (RtlGenRandom)
8374#[ cfg( not( target_vendor = "uwp" ) ) ]
84- fn fallback_rng ( ) -> Option < Result < ( u64 , u64 ) , io:: Error > > {
75+ fn fallback_rng ( ) -> Result < ( u64 , u64 ) , io:: Error > {
8576 let mut v = ( 0 , 0 ) ;
8677 let ret =
8778 unsafe { c:: RtlGenRandom ( & mut v as * mut _ as * mut u8 , mem:: size_of_val ( & v) as c:: ULONG ) } ;
8879
89- Some ( if ret != 0 { Ok ( v) } else { Err ( io:: Error :: last_os_error ( ) ) } )
80+ if ret != 0 { Ok ( v) } else { Err ( io:: Error :: last_os_error ( ) ) }
9081}
9182
92- // We can't use RtlGenRandom with UWP, so there is no fallback
83+ /// We can't use RtlGenRandom with UWP, so there is no fallback
9384#[ cfg( target_vendor = "uwp" ) ]
94- fn fallback_rng ( ) -> Option < Result < ( u64 , u64 ) , io:: Error > > {
95- None
85+ fn fallback_rng ( ) -> Result < ( u64 , u64 ) , io:: Error > {
86+ Err ( io :: const_io_error! ( io :: ErrorKind :: Unsupported , "unsupported on UWP" ) )
9687}
0 commit comments