Skip to content

Commit 30834a5

Browse files
authored
Merge pull request #374 from dhardy/chacha
ChaCha: support reading counter and setting nonce
2 parents 35a9476 + f067cee commit 30834a5

File tree

3 files changed

+157
-180
lines changed

3 files changed

+157
-180
lines changed

benches/generators.rs

Lines changed: 3 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ macro_rules! gen_bytes {
3434
}
3535

3636
gen_bytes!(gen_bytes_xorshift, XorShiftRng::from_entropy());
37+
gen_bytes!(gen_bytes_chacha20, ChaChaRng::from_entropy());
3738
gen_bytes!(gen_bytes_hc128, Hc128Rng::from_entropy());
3839
gen_bytes!(gen_bytes_isaac, IsaacRng::from_entropy());
3940
gen_bytes!(gen_bytes_isaac64, Isaac64Rng::from_entropy());
@@ -59,6 +60,7 @@ macro_rules! gen_uint {
5960
}
6061

6162
gen_uint!(gen_u32_xorshift, u32, XorShiftRng::from_entropy());
63+
gen_uint!(gen_u32_chacha20, u32, ChaChaRng::from_entropy());
6264
gen_uint!(gen_u32_hc128, u32, Hc128Rng::from_entropy());
6365
gen_uint!(gen_u32_isaac, u32, IsaacRng::from_entropy());
6466
gen_uint!(gen_u32_isaac64, u32, Isaac64Rng::from_entropy());
@@ -67,6 +69,7 @@ gen_uint!(gen_u32_small, u32, SmallRng::from_entropy());
6769
gen_uint!(gen_u32_os, u32, OsRng::new().unwrap());
6870

6971
gen_uint!(gen_u64_xorshift, u64, XorShiftRng::from_entropy());
72+
gen_uint!(gen_u64_chacha20, u64, ChaChaRng::from_entropy());
7073
gen_uint!(gen_u64_hc128, u64, Hc128Rng::from_entropy());
7174
gen_uint!(gen_u64_isaac, u64, IsaacRng::from_entropy());
7275
gen_uint!(gen_u64_isaac64, u64, Isaac64Rng::from_entropy());
@@ -111,56 +114,6 @@ fn init_jitter(b: &mut Bencher) {
111114
});
112115
}
113116

114-
macro_rules! chacha_rounds {
115-
($fn1:ident, $fn2:ident, $fn3:ident, $rounds:expr) => {
116-
#[bench]
117-
fn $fn1(b: &mut Bencher) {
118-
let mut rng = ChaChaRng::from_entropy();
119-
rng.set_rounds($rounds);
120-
let mut buf = [0u8; BYTES_LEN];
121-
b.iter(|| {
122-
for _ in 0..RAND_BENCH_N {
123-
rng.fill_bytes(&mut buf);
124-
black_box(buf);
125-
}
126-
});
127-
b.bytes = BYTES_LEN as u64 * RAND_BENCH_N;
128-
}
129-
130-
#[bench]
131-
fn $fn2(b: &mut Bencher) {
132-
let mut rng = ChaChaRng::from_entropy();
133-
rng.set_rounds($rounds);
134-
b.iter(|| {
135-
let mut accum: u32 = 0;
136-
for _ in 0..RAND_BENCH_N {
137-
accum = accum.wrapping_add(rng.gen::<u32>());
138-
}
139-
black_box(accum);
140-
});
141-
b.bytes = size_of::<u32>() as u64 * RAND_BENCH_N;
142-
}
143-
144-
#[bench]
145-
fn $fn3(b: &mut Bencher) {
146-
let mut rng = ChaChaRng::from_entropy();
147-
rng.set_rounds($rounds);
148-
b.iter(|| {
149-
let mut accum: u64 = 0;
150-
for _ in 0..RAND_BENCH_N {
151-
accum = accum.wrapping_add(rng.gen::<u64>());
152-
}
153-
black_box(accum);
154-
});
155-
b.bytes = size_of::<u64>() as u64 * RAND_BENCH_N;
156-
}
157-
}
158-
}
159-
160-
chacha_rounds!(gen_bytes_chacha8, gen_u32_chacha8, gen_u64_chacha8, 8);
161-
chacha_rounds!(gen_bytes_chacha12, gen_u32_chacha12, gen_u64_chacha12, 12);
162-
chacha_rounds!(gen_bytes_chacha20, gen_u32_chacha20, gen_u64_chacha20, 20);
163-
164117

165118
const RESEEDING_THRESHOLD: u64 = 1024*1024*1024; // something high enough to get
166119
// deterministic measurements

rand_core/src/impls.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,28 @@ impl<R: BlockRngCore> BlockRng<R> {
228228
&mut self.core
229229
}
230230

231-
// Reset the number of available results.
232-
// This will force a new set of results to be generated on next use.
231+
/// Get the index into the result buffer.
232+
///
233+
/// If this is equal to or larger than the size of the result buffer then
234+
/// the buffer is "empty" and `generate()` must be called to produce new
235+
/// results.
236+
pub fn index(&self) -> usize {
237+
self.index
238+
}
239+
240+
/// Reset the number of available results.
241+
/// This will force a new set of results to be generated on next use.
233242
pub fn reset(&mut self) {
234243
self.index = self.results.as_ref().len();
235244
}
245+
246+
/// Generate a new set of results immediately, setting the index to the
247+
/// given value.
248+
pub fn generate_and_set(&mut self, index: usize) {
249+
assert!(index < self.results.as_ref().len());
250+
self.core.generate(&mut self.results);
251+
self.index = index;
252+
}
236253
}
237254

238255
impl<R: BlockRngCore<Item=u32>> RngCore for BlockRng<R>
@@ -241,8 +258,7 @@ where <R as BlockRngCore>::Results: AsRef<[u32]>
241258
#[inline(always)]
242259
fn next_u32(&mut self) -> u32 {
243260
if self.index >= self.results.as_ref().len() {
244-
self.core.generate(&mut self.results);
245-
self.index = 0;
261+
self.generate_and_set(0);
246262
}
247263

248264
let value = self.results.as_ref()[self.index];
@@ -271,13 +287,11 @@ where <R as BlockRngCore>::Results: AsRef<[u32]>
271287
// Read an u64 from the current index
272288
read_u64(self.results.as_ref(), index)
273289
} else if index >= len {
274-
self.core.generate(&mut self.results);
275-
self.index = 2;
290+
self.generate_and_set(2);
276291
read_u64(self.results.as_ref(), 0)
277292
} else {
278293
let x = u64::from(self.results.as_ref()[len-1]);
279-
self.core.generate(&mut self.results);
280-
self.index = 1;
294+
self.generate_and_set(1);
281295
let y = u64::from(self.results.as_ref()[0]);
282296
(y << 32) | x
283297
}
@@ -311,8 +325,8 @@ where <R as BlockRngCore>::Results: AsRef<[u32]>
311325
};
312326
self.core.generate(dest_u32);
313327
filled += self.results.as_ref().len() * 4;
328+
self.index = self.results.as_ref().len();
314329
}
315-
self.index = self.results.as_ref().len();
316330

317331
if len_remainder > 0 {
318332
self.core.generate(&mut self.results);
@@ -329,8 +343,7 @@ where <R as BlockRngCore>::Results: AsRef<[u32]>
329343
let mut read_len = 0;
330344
while read_len < dest.len() {
331345
if self.index >= self.results.as_ref().len() {
332-
self.core.generate(&mut self.results);
333-
self.index = 0;
346+
self.generate_and_set(0);
334347
}
335348
let (consumed_u32, filled_u8) =
336349
fill_via_u32_chunks(&self.results.as_ref()[self.index..],
@@ -489,8 +502,8 @@ where <R as BlockRngCore>::Results: AsRef<[u64]>
489502
};
490503
self.core.generate(dest_u64);
491504
filled += self.results.as_ref().len() * 8;
505+
self.index = self.results.as_ref().len();
492506
}
493-
self.index = self.results.as_ref().len();
494507

495508
if len_remainder > 0 {
496509
self.core.generate(&mut self.results);

0 commit comments

Comments
 (0)