Skip to content

Commit 6fb3413

Browse files
authored
Merge pull request #189 from LinearZoetrope/serde
Add Serde
2 parents c957abe + c6447b9 commit 6fb3413

File tree

9 files changed

+212
-1
lines changed

9 files changed

+212
-1
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ matrix:
2828
script:
2929
- cargo test
3030
- cargo test --tests --no-default-features
31+
- cargo test --features serde-1
3132
- cargo test --manifest-path rand-derive/Cargo.toml
3233

3334
env:

Cargo.toml

+13
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,25 @@ alloc = [] # enables Vec and Box support without std
2222

2323
i128_support = [] # enables i128 and u128 support
2424

25+
serde-1 = ["serde", "serde_derive"]
26+
27+
2528
[target.'cfg(unix)'.dependencies]
2629
libc = { version = "0.2", optional = true }
2730

2831
[target.'cfg(windows)'.dependencies]
2932
winapi = { version = "0.3", features = ["minwindef", "ntsecapi", "profileapi", "winnt"], optional = true }
3033

34+
[dependencies]
35+
serde = {version="1",optional=true}
36+
serde_derive = {version="1", optional=true}
37+
38+
[dev-dependencies]
39+
# This is for testing serde, unfortunately
40+
# we can't specify feature-gated dev deps yet,
41+
# see: https://github.com/rust-lang/cargo/issues/1596
42+
bincode = "0.9"
43+
3144
[workspace]
3245
members = ["rand-derive"]
3346

appveyor.yml

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ build: false
3434
test_script:
3535
- cargo test --benches
3636
- cargo test
37+
- cargo test --features serde-1
3738
- cargo test --features nightly
3839
- cargo test --tests --no-default-features --features=alloc
3940
- cargo test --manifest-path rand-derive/Cargo.toml

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@
249249

250250
#[cfg(feature="std")] extern crate std as core;
251251
#[cfg(all(feature = "alloc", not(feature="std")))] extern crate alloc;
252+
#[cfg(test)] #[cfg(feature="serde-1")] extern crate bincode;
253+
#[cfg(feature="serde-1")] extern crate serde;
254+
#[cfg(feature="serde-1")] #[macro_use] extern crate serde_derive;
252255

253256
use core::marker;
254257
use core::mem;

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

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2017-2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// https://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! ISAAC serde helper functions.
12+
13+
pub(super) mod rand_size_serde {
14+
const RAND_SIZE_LEN: usize = 8;
15+
const RAND_SIZE: usize = 1 << RAND_SIZE_LEN;
16+
17+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
18+
use serde::de::{Visitor,SeqAccess};
19+
use serde::de;
20+
21+
use std::fmt;
22+
23+
pub fn serialize<T, S>(arr: &[T;RAND_SIZE], ser: S) -> Result<S::Ok, S::Error>
24+
where
25+
T: Serialize,
26+
S: Serializer
27+
{
28+
use serde::ser::SerializeTuple;
29+
30+
let mut seq = ser.serialize_tuple(RAND_SIZE)?;
31+
32+
for e in arr.iter() {
33+
seq.serialize_element(&e)?;
34+
}
35+
36+
seq.end()
37+
}
38+
39+
#[inline]
40+
pub fn deserialize<'de, T, D>(de: D) -> Result<[T;RAND_SIZE], D::Error>
41+
where
42+
T: Deserialize<'de>+Default+Copy,
43+
D: Deserializer<'de>,
44+
{
45+
use std::marker::PhantomData;
46+
struct ArrayVisitor<T> {
47+
_pd: PhantomData<T>,
48+
};
49+
impl<'de,T> Visitor<'de> for ArrayVisitor<T>
50+
where
51+
T: Deserialize<'de>+Default+Copy
52+
{
53+
type Value = [T; RAND_SIZE];
54+
55+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
56+
formatter.write_str("Isaac state array")
57+
}
58+
59+
#[inline]
60+
fn visit_seq<A>(self, mut seq: A) -> Result<[T; RAND_SIZE], A::Error>
61+
where
62+
A: SeqAccess<'de>,
63+
{
64+
let mut out = [Default::default();RAND_SIZE];
65+
66+
for i in 0..RAND_SIZE {
67+
match seq.next_element()? {
68+
Some(val) => out[i] = val,
69+
None => return Err(de::Error::invalid_length(i, &self)),
70+
};
71+
}
72+
73+
Ok(out)
74+
}
75+
}
76+
77+
de.deserialize_tuple(RAND_SIZE, ArrayVisitor{_pd: PhantomData})
78+
}
79+
}

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;

src/prng/xorshift.rs

+36
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use impls;
2626
/// RNGs"](https://www.jstatsoft.org/v08/i14/paper). *Journal of
2727
/// Statistical Software*. Vol. 8 (Issue 14).
2828
#[derive(Clone)]
29+
#[cfg_attr(feature="serde-1", derive(Serialize,Deserialize))]
2930
pub struct XorShiftRng {
3031
x: w<u32>,
3132
y: w<u32>,
@@ -115,3 +116,38 @@ impl Rand for XorShiftRng {
115116
XorShiftRng { x: w(x), y: w(y), z: w(z), w: w(w_) }
116117
}
117118
}
119+
120+
#[cfg(test)]
121+
mod tests {
122+
#[cfg(feature="serde-1")]
123+
use {Rng, SeedableRng};
124+
125+
#[cfg(feature="serde-1")]
126+
#[test]
127+
fn test_serde() {
128+
use super::XorShiftRng;
129+
use thread_rng;
130+
use bincode;
131+
use std::io::{BufWriter, BufReader};
132+
133+
let seed: [u32; 4] = thread_rng().gen();
134+
let mut rng: XorShiftRng = SeedableRng::from_seed(seed);
135+
136+
let buf: Vec<u8> = Vec::new();
137+
let mut buf = BufWriter::new(buf);
138+
bincode::serialize_into(&mut buf, &rng, bincode::Infinite).expect("Could not serialize");
139+
140+
let buf = buf.into_inner().unwrap();
141+
let mut read = BufReader::new(&buf[..]);
142+
let mut deserialized: XorShiftRng = bincode::deserialize_from(&mut read, bincode::Infinite).expect("Could not deserialize");
143+
144+
assert_eq!(rng.x, deserialized.x);
145+
assert_eq!(rng.y, deserialized.y);
146+
assert_eq!(rng.z, deserialized.z);
147+
assert_eq!(rng.w, deserialized.w);
148+
149+
for _ in 0..16 {
150+
assert_eq!(rng.next_u64(), deserialized.next_u64());
151+
}
152+
}
153+
}

0 commit comments

Comments
 (0)