@@ -74,6 +74,57 @@ impl ReseedingCore {
7474 }
7575}
7676
77+ /// The [`ThreadRng`] internal
78+ struct ThreadRngCore {
79+ inner : BlockRng < ReseedingCore > ,
80+ }
81+
82+ /// Debug implementation does not leak internal state
83+ impl fmt:: Debug for ThreadRngCore {
84+ fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
85+ write ! ( fmt, "ThreadRngCore {{ .. }}" )
86+ }
87+ }
88+
89+ impl ThreadRngCore {
90+ /// Initialize the generator using [`SysRng`]
91+ fn new ( ) -> Result < Self , SysError > {
92+ Core :: try_from_rng ( & mut SysRng ) . map ( |result| Self {
93+ inner : BlockRng :: new ( ReseedingCore { inner : result } ) ,
94+ } )
95+ }
96+
97+ /// Immediately reseed the generator
98+ ///
99+ /// This discards any remaining random data in the cache.
100+ fn reseed ( & mut self ) -> Result < ( ) , SysError > {
101+ self . inner . reset_and_skip ( 0 ) ;
102+ self . inner . core . reseed ( )
103+ }
104+ }
105+
106+ impl TryRng for ThreadRngCore {
107+ type Error = Infallible ;
108+
109+ #[ inline( always) ]
110+ fn try_next_u32 ( & mut self ) -> Result < u32 , Infallible > {
111+ Ok ( self . inner . next_word ( ) )
112+ }
113+
114+ #[ inline( always) ]
115+ fn try_next_u64 ( & mut self ) -> Result < u64 , Infallible > {
116+ Ok ( self . inner . next_u64_from_u32 ( ) )
117+ }
118+
119+ #[ inline( always) ]
120+ fn try_fill_bytes ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Infallible > {
121+ self . inner . fill_bytes ( dest) ;
122+ Ok ( ( ) )
123+ }
124+ }
125+
126+ impl TryCryptoRng for ThreadRngCore { }
127+
77128/// A reference to the thread-local generator
78129///
79130/// This type is a reference to a lazily-initialized thread-local generator.
@@ -127,7 +178,7 @@ impl ReseedingCore {
127178#[ derive( Clone ) ]
128179pub struct ThreadRng {
129180 // Rc is explicitly !Send and !Sync
130- rng : Rc < UnsafeCell < BlockRng < ReseedingCore > > > ,
181+ rng : Rc < UnsafeCell < ThreadRngCore > > ,
131182}
132183
133184impl ThreadRng {
@@ -138,8 +189,7 @@ impl ThreadRng {
138189 // SAFETY: We must make sure to stop using `rng` before anyone else
139190 // creates another mutable reference
140191 let rng = unsafe { & mut * self . rng . get ( ) } ;
141- rng. reset_and_skip ( 0 ) ;
142- rng. core . reseed ( )
192+ rng. reseed ( )
143193 }
144194}
145195
@@ -153,12 +203,11 @@ impl fmt::Debug for ThreadRng {
153203thread_local ! (
154204 // We require Rc<..> to avoid premature freeing when ThreadRng is used
155205 // within thread-local destructors. See #968.
156- static THREAD_RNG_KEY : Rc <UnsafeCell <BlockRng <ReseedingCore >>> = {
157- Rc :: new( UnsafeCell :: new( BlockRng :: new( ReseedingCore {
158- inner: Core :: try_from_rng( & mut SysRng ) . unwrap_or_else( |err| {
206+ static THREAD_RNG_KEY : Rc <UnsafeCell <ThreadRngCore >> = {
207+ Rc :: new( UnsafeCell :: new( ThreadRngCore :: new( ) . unwrap_or_else( |err| {
159208 panic!( "could not initialize ThreadRng: {}" , err)
160209 } ) ,
161- } ) ) )
210+ ) )
162211 }
163212) ;
164213
@@ -209,24 +258,23 @@ impl TryRng for ThreadRng {
209258 // SAFETY: We must make sure to stop using `rng` before anyone else
210259 // creates another mutable reference
211260 let rng = unsafe { & mut * self . rng . get ( ) } ;
212- Ok ( rng. next_word ( ) )
261+ rng. try_next_u32 ( )
213262 }
214263
215264 #[ inline( always) ]
216265 fn try_next_u64 ( & mut self ) -> Result < u64 , Infallible > {
217266 // SAFETY: We must make sure to stop using `rng` before anyone else
218267 // creates another mutable reference
219268 let rng = unsafe { & mut * self . rng . get ( ) } ;
220- Ok ( rng. next_u64_from_u32 ( ) )
269+ rng. try_next_u64 ( )
221270 }
222271
223272 #[ inline( always) ]
224273 fn try_fill_bytes ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Infallible > {
225274 // SAFETY: We must make sure to stop using `rng` before anyone else
226275 // creates another mutable reference
227276 let rng = unsafe { & mut * self . rng . get ( ) } ;
228- rng. fill_bytes ( dest) ;
229- Ok ( ( ) )
277+ rng. try_fill_bytes ( dest)
230278 }
231279}
232280
@@ -242,10 +290,22 @@ mod test {
242290 assert_eq ! ( r. random_range( 0 ..1 ) , 0 ) ;
243291 }
244292
293+ #[ test]
294+ fn test_thread_rng_core ( ) {
295+ use crate :: RngExt ;
296+ let mut r = super :: ThreadRngCore :: new ( ) . unwrap ( ) ;
297+ r. random :: < i32 > ( ) ;
298+ assert_eq ! ( r. random_range( 0 ..1 ) , 0 ) ;
299+ }
300+
245301 #[ test]
246302 fn test_debug_output ( ) {
247303 // We don't care about the exact output here, but it must not include
248304 // private CSPRNG state or the cache stored by BlockRng!
249305 assert_eq ! ( std:: format!( "{:?}" , crate :: rng( ) ) , "ThreadRng { .. }" ) ;
306+ assert_eq ! (
307+ std:: format!( "{:?}" , super :: ThreadRngCore :: new( ) . unwrap( ) ) ,
308+ "ThreadRngCore { .. }"
309+ ) ;
250310 }
251311}
0 commit comments