Skip to content

Commit 505fcae

Browse files
committed
Isaac Serde
1 parent c3443e2 commit 505fcae

File tree

4 files changed

+147
-1
lines changed

4 files changed

+147
-1
lines changed

src/prng/isaac.rs

+37
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,11 @@ const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
8787
///
8888
/// [3]: Jean-Philippe Aumasson, [*On the pseudo-random generator ISAAC*](
8989
/// https://eprint.iacr.org/2006/438)
90+
#[cfg_attr(feature="serde-1", derive(Serialize,Deserialize))]
9091
pub struct IsaacRng {
92+
#[cfg_attr(feature="serde-1",serde(with="super::isaac_serde::rand_size_serde"))]
9193
rsl: [u32; RAND_SIZE],
94+
#[cfg_attr(feature="serde-1",serde(with="super::isaac_serde::rand_size_serde"))]
9295
mem: [w32; RAND_SIZE],
9396
a: w32,
9497
b: w32,
@@ -465,4 +468,38 @@ mod test {
465468
assert_eq!(rng.next_u64(), clone.next_u64());
466469
}
467470
}
471+
472+
#[test]
473+
#[cfg(feature="serde-1")]
474+
fn test_rng_serde() {
475+
use bincode;
476+
use std::io::{BufWriter, BufReader};
477+
478+
let seed: &[_] = &[1, 23, 456, 7890, 12345];
479+
let mut rng: IsaacRng = SeedableRng::from_seed(seed);
480+
481+
let buf: Vec<u8> = Vec::new();
482+
let mut buf = BufWriter::new(buf);
483+
bincode::serialize_into(&mut buf, &rng, bincode::Infinite).expect("Could not serialize");
484+
485+
let buf = buf.into_inner().unwrap();
486+
let mut read = BufReader::new(&buf[..]);
487+
let mut deserialized: IsaacRng = bincode::deserialize_from(&mut read, bincode::Infinite).expect("Could not deserialize");
488+
489+
assert_eq!(rng.index, deserialized.index);
490+
/* Can't assert directly because of the array size */
491+
for (orig,deser) in rng.rsl.iter().zip(deserialized.rsl.iter()) {
492+
assert_eq!(orig, deser);
493+
}
494+
for (orig,deser) in rng.mem.iter().zip(deserialized.mem.iter()) {
495+
assert_eq!(orig, deser);
496+
}
497+
assert_eq!(rng.a, deserialized.a);
498+
assert_eq!(rng.b, deserialized.b);
499+
assert_eq!(rng.c, deserialized.c);
500+
501+
for _ in 0..16 {
502+
assert_eq!(rng.next_u64(), deserialized.next_u64());
503+
}
504+
}
468505
}

src/prng/isaac64.rs

+38
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,11 @@ const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
7171
///
7272
/// [1]: Bob Jenkins, [*ISAAC and RC4*](
7373
/// http://burtleburtle.net/bob/rand/isaac.html)
74+
#[cfg_attr(feature="serde-1", derive(Serialize,Deserialize))]
7475
pub struct Isaac64Rng {
76+
#[cfg_attr(feature="serde-1",serde(with="super::isaac_serde::rand_size_serde"))]
7577
rsl: [u64; RAND_SIZE],
78+
#[cfg_attr(feature="serde-1",serde(with="super::isaac_serde::rand_size_serde"))]
7679
mem: [w64; RAND_SIZE],
7780
a: w64,
7881
b: w64,
@@ -473,4 +476,39 @@ mod test {
473476
assert_eq!(rng.next_u64(), clone.next_u64());
474477
}
475478
}
479+
480+
#[test]
481+
#[cfg(feature="serde-1")]
482+
fn test_rng_serde() {
483+
use bincode;
484+
use std::io::{BufWriter, BufReader};
485+
486+
let seed: &[_] = &[1, 23, 456, 7890, 12345];
487+
let mut rng: Isaac64Rng = SeedableRng::from_seed(seed);
488+
489+
let buf: Vec<u8> = Vec::new();
490+
let mut buf = BufWriter::new(buf);
491+
bincode::serialize_into(&mut buf, &rng, bincode::Infinite).expect("Could not serialize");
492+
493+
let buf = buf.into_inner().unwrap();
494+
let mut read = BufReader::new(&buf[..]);
495+
let mut deserialized: Isaac64Rng = bincode::deserialize_from(&mut read, bincode::Infinite).expect("Could not deserialize");
496+
497+
assert_eq!(rng.index, deserialized.index);
498+
assert_eq!(rng.half_used, deserialized.half_used);
499+
/* Can't assert directly because of the array size */
500+
for (orig,deser) in rng.rsl.iter().zip(deserialized.rsl.iter()) {
501+
assert_eq!(orig, deser);
502+
}
503+
for (orig,deser) in rng.mem.iter().zip(deserialized.mem.iter()) {
504+
assert_eq!(orig, deser);
505+
}
506+
assert_eq!(rng.a, deserialized.a);
507+
assert_eq!(rng.b, deserialized.b);
508+
assert_eq!(rng.c, deserialized.c);
509+
510+
for _ in 0..16 {
511+
assert_eq!(rng.next_u64(), deserialized.next_u64());
512+
}
513+
}
476514
}

src/prng/isaac_serde.rs

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#[cfg(feature="serde-1")]
2+
pub(super) mod rand_size_serde {
3+
const RAND_SIZE_LEN: usize = 8;
4+
const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
5+
6+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
7+
use serde::de::{Visitor,SeqAccess};
8+
use serde::de;
9+
10+
use std::fmt;
11+
12+
pub fn serialize<T, S>(arr: &[T;RAND_SIZE], ser: S) -> Result<S::Ok, S::Error>
13+
where
14+
T: Serialize,
15+
S: Serializer
16+
{
17+
use serde::ser::SerializeTuple;
18+
19+
let mut seq = ser.serialize_tuple(RAND_SIZE)?;
20+
21+
for e in arr.iter() {
22+
seq.serialize_element(&e)?;
23+
}
24+
25+
seq.end()
26+
}
27+
28+
#[inline]
29+
pub fn deserialize<'de, T, D>(de: D) -> Result<[T;RAND_SIZE], D::Error>
30+
where
31+
T: Deserialize<'de>+Default+Copy,
32+
D: Deserializer<'de>,
33+
{
34+
use std::marker::PhantomData;
35+
struct ArrayVisitor<T> {
36+
_pd: PhantomData<T>,
37+
};
38+
impl<'de,T> Visitor<'de> for ArrayVisitor<T>
39+
where
40+
T: Deserialize<'de>+Default+Copy
41+
{
42+
type Value = [T; RAND_SIZE];
43+
44+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
45+
formatter.write_str("Isaac state array")
46+
}
47+
48+
#[inline]
49+
fn visit_seq<A>(self, mut seq: A) -> Result<[T; RAND_SIZE], A::Error>
50+
where
51+
A: SeqAccess<'de>,
52+
{
53+
let mut out = [Default::default();RAND_SIZE];
54+
55+
for i in 0..RAND_SIZE {
56+
match seq.next_element()? {
57+
Some(val) => out[i] = val,
58+
None => return Err(de::Error::invalid_length(i, &self)),
59+
};
60+
}
61+
62+
Ok(out)
63+
}
64+
}
65+
66+
de.deserialize_tuple(RAND_SIZE, ArrayVisitor{_pd: PhantomData})
67+
}
68+
}

src/prng/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@ mod isaac;
4646
mod isaac64;
4747
mod xorshift;
4848

49+
#[cfg(feature="serde-1")]
50+
mod isaac_serde;
51+
4952
pub use self::chacha::ChaChaRng;
5053
pub use self::hc128::Hc128Rng;
5154
pub use self::isaac::IsaacRng;
5255
pub use self::isaac64::Isaac64Rng;
53-
pub use self::xorshift::XorShiftRng;
56+
pub use self::xorshift::XorShiftRng;

0 commit comments

Comments
 (0)