diff --git a/.travis.yml b/.travis.yml index 7466e29e365..84d7c9deeb7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,7 @@ matrix: script: - cargo test - cargo test --tests --no-default-features + - cargo test --features serde-1 - cargo test --manifest-path rand-derive/Cargo.toml env: diff --git a/Cargo.toml b/Cargo.toml index 13d76debd68..3f469cc6667 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,12 +22,26 @@ alloc = [] # enables Vec and Box support without std i128_support = [] # enables i128 and u128 support +serde-1 = ["serde", "serde_derive"] + + [target.'cfg(unix)'.dependencies] libc = { version = "0.2", optional = true } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["minwindef", "ntsecapi", "profileapi", "winnt"], optional = true } +[dependencies] +serde = {version="1",optional=true} +serde_derive = {version="1", optional=true} + +[dev-dependencies] +log = "0.3.0" +# This is for testing serde, unfortunately +# we can't specify feature-gated dev deps yet, +# see: https://github.com/rust-lang/cargo/issues/1596 +bincode = "0.9" + [workspace] members = ["rand-derive"] diff --git a/appveyor.yml b/appveyor.yml index e5800fa7a07..14c572f5f93 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,6 +34,7 @@ build: false test_script: - cargo test --benches - cargo test + - cargo test --features serde-1 - cargo test --features nightly - cargo test --tests --no-default-features --features=alloc - cargo test --manifest-path rand-derive/Cargo.toml diff --git a/src/lib.rs b/src/lib.rs index db3d930e8f5..210e8ee81c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -249,6 +249,10 @@ #[cfg(feature="std")] extern crate std as core; #[cfg(all(feature = "alloc", not(feature="std")))] extern crate alloc; +#[cfg(test)] #[macro_use] extern crate log; +#[cfg(test)] #[cfg(feature="serde-1")] extern crate bincode; +#[cfg(feature="serde-1")] extern crate serde; +#[cfg(feature="serde-1")] #[macro_use] extern crate serde_derive; use core::marker; use core::mem; diff --git a/src/prng/chacha.rs b/src/prng/chacha.rs index 639f4e2e554..3e1d887046f 100644 --- a/src/prng/chacha.rs +++ b/src/prng/chacha.rs @@ -11,11 +11,11 @@ //! The ChaCha random number generator. use core::fmt; -use {Rng, SeedableRng, Rand}; +use {Rand, Rng, SeedableRng}; use impls; -const KEY_WORDS : usize = 8; // 8 words for the 256-bit key -const STATE_WORDS : usize = 16; +const KEY_WORDS: usize = 8; // 8 words for the 256-bit key +const STATE_WORDS: usize = 16; const CHACHA_ROUNDS: u32 = 20; // Cryptographically secure from 8 upwards as of this writing /// A random number generator that uses the ChaCha20 algorithm [1]. @@ -29,9 +29,9 @@ const CHACHA_ROUNDS: u32 = 20; // Cryptographically secure from 8 upwards as of /// Salsa20*](https://cr.yp.to/chacha.html) #[derive(Clone)] pub struct ChaChaRng { - buffer: [u32; STATE_WORDS], // Internal buffer of output - state: [u32; STATE_WORDS], // Initial state - index: usize, // Index into state + buffer: [u32; STATE_WORDS], // Internal buffer of output + state: [u32; STATE_WORDS], // Initial state + index: usize, // Index into state } // Custom Debug implementation that does not expose the internal state @@ -79,7 +79,6 @@ fn core(new: &mut [u32; STATE_WORDS], input: &[u32; STATE_WORDS]) { } impl ChaChaRng { - /// Create an ChaCha random number generator using the default /// fixed key of 8 zero words. /// @@ -101,9 +100,9 @@ impl ChaChaRng { /// - 2419978656 pub fn new_unseeded() -> ChaChaRng { let mut rng = ChaChaRng { - buffer: [0; STATE_WORDS], - state: [0; STATE_WORDS], - index: STATE_WORDS + buffer: [0; STATE_WORDS], + state: [0; STATE_WORDS], + index: STATE_WORDS, }; rng.init(&[0; KEY_WORDS]); rng @@ -129,9 +128,9 @@ impl ChaChaRng { /// println!("{:?}", ra.next_u32()); /// ``` pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) { - self.state[12] = (counter_low >> 0) as u32; + self.state[12] = (counter_low >> 0) as u32; self.state[13] = (counter_low >> 32) as u32; - self.state[14] = (counter_high >> 0) as u32; + self.state[14] = (counter_high >> 0) as u32; self.state[15] = (counter_high >> 32) as u32; self.index = STATE_WORDS; // force recomputation } @@ -161,7 +160,7 @@ impl ChaChaRng { self.state[3] = 0x6B206574; for i in 0..KEY_WORDS { - self.state[4+i] = key[i]; + self.state[4 + i] = key[i]; } self.state[12] = 0; @@ -178,11 +177,17 @@ impl ChaChaRng { self.index = 0; // update 128-bit counter self.state[12] = self.state[12].wrapping_add(1); - if self.state[12] != 0 { return }; + if self.state[12] != 0 { + return; + }; self.state[13] = self.state[13].wrapping_add(1); - if self.state[13] != 0 { return }; + if self.state[13] != 0 { + return; + }; self.state[14] = self.state[14].wrapping_add(1); - if self.state[14] != 0 { return }; + if self.state[14] != 0 { + return; + }; self.state[15] = self.state[15].wrapping_add(1); } } @@ -216,8 +221,7 @@ impl Rng for ChaChaRng { } let (consumed_u32, filled_u8) = - impls::fill_via_u32_chunks(&self.buffer[self.index..], - &mut dest[read_len..]); + impls::fill_via_u32_chunks(&self.buffer[self.index..], &mut dest[read_len..]); self.index += consumed_u32; read_len += filled_u8; @@ -226,7 +230,6 @@ impl Rng for ChaChaRng { } impl<'a> SeedableRng<&'a [u32]> for ChaChaRng { - fn reseed(&mut self, seed: &'a [u32]) { *self = Self::from_seed(seed); } @@ -237,14 +240,14 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng { /// words are used, the remaining are set to zero. fn from_seed(seed: &'a [u32]) -> ChaChaRng { let mut rng = ChaChaRng { - buffer: [0; STATE_WORDS], - state: [0; STATE_WORDS], - index: STATE_WORDS + buffer: [0; STATE_WORDS], + state: [0; STATE_WORDS], + index: STATE_WORDS, }; rng.init(&[0u32; KEY_WORDS]); // set key in place { - let key = &mut rng.state[4 .. 4+KEY_WORDS]; + let key = &mut rng.state[4..4 + KEY_WORDS]; for (k, s) in key.iter_mut().zip(seed.iter()) { *k = *s; } @@ -255,7 +258,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng { impl Rand for ChaChaRng { fn rand(other: &mut R) -> ChaChaRng { - let mut key : [u32; KEY_WORDS] = [0; KEY_WORDS]; + let mut key: [u32; KEY_WORDS] = [0; KEY_WORDS]; for word in key.iter_mut() { *word = other.gen(); } @@ -263,7 +266,6 @@ impl Rand for ChaChaRng { } } - #[cfg(test)] mod test { use {Rng, SeedableRng}; @@ -289,22 +291,54 @@ mod test { let mut rng1: ChaChaRng = SeedableRng::from_seed(seed); let mut results = [0u32; 16]; - for i in results.iter_mut() { *i = rng1.next_u32(); } - let expected = [0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653, - 0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b, - 0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8, - 0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2]; + for i in results.iter_mut() { + *i = rng1.next_u32(); + } + let expected = [ + 0xade0b876, + 0x903df1a0, + 0xe56a5d40, + 0x28bd8653, + 0xb819d2bd, + 0x1aed8da0, + 0xccef36a8, + 0xc70d778b, + 0x7c5941da, + 0x8d485751, + 0x3fe02477, + 0x374ad8b8, + 0xf4b8436a, + 0x1ca11815, + 0x69b687c3, + 0x8665eeb2, + ]; assert_eq!(results, expected); - for i in results.iter_mut() { *i = rng1.next_u32(); } - let expected = [0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73, - 0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32, - 0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874, - 0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b]; + for i in results.iter_mut() { + *i = rng1.next_u32(); + } + let expected = [ + 0xbee7079f, + 0x7a385155, + 0x7c97ba98, + 0x0d082d73, + 0xa0290fcb, + 0x6965e348, + 0x3e53c612, + 0xed7aee32, + 0x7621b729, + 0x434ee69c, + 0xb03371d5, + 0xd539d874, + 0x281fed31, + 0x45fb0a51, + 0x1f0ae1ac, + 0x6f4d794b, + ]; assert_eq!(results, expected); - let seed: &[_] = &[0,1,2,3,4,5,6,7]; + let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; let mut rng2: ChaChaRng = SeedableRng::from_seed(seed); // Store the 17*i-th 32-bit word, @@ -315,10 +349,24 @@ mod test { rng2.next_u32(); } } - let expected = [0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036, - 0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384, - 0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530, - 0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4]; + let expected = [ + 0xf225c81a, + 0x6ab1be57, + 0x04d42951, + 0x70858036, + 0x49884684, + 0x64efec72, + 0x4be2d186, + 0x3615b384, + 0x11cfa18e, + 0xd3c50049, + 0x75c775f6, + 0x434c6530, + 0x2c5bad8f, + 0x898881dc, + 0x5f1c86d9, + 0xc1f8e7f4, + ]; assert_eq!(results, expected); } @@ -329,16 +377,46 @@ mod test { let mut results = [0u8; 32]; rng.fill_bytes(&mut results); // Same as first values in test_isaac_true_values as bytes in LE order - let expected = [118, 184, 224, 173, 160, 241, 61, 144, - 64, 93, 106, 229, 83, 134, 189, 40, - 189, 210, 25, 184, 160, 141, 237, 26, - 168, 54, 239, 204, 139, 119, 13, 199]; + let expected = [ + 118, + 184, + 224, + 173, + 160, + 241, + 61, + 144, + 64, + 93, + 106, + 229, + 83, + 134, + 189, + 40, + 189, + 210, + 25, + 184, + 160, + 141, + 237, + 26, + 168, + 54, + 239, + 204, + 139, + 119, + 13, + 199, + ]; assert_eq!(results, expected); } #[test] fn test_chacha_clone() { - let seed: &[_] = &[0,1,2,3,4,5,6,7]; + let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; let mut rng: ChaChaRng = SeedableRng::from_seed(seed); let mut clone = rng.clone(); for _ in 0..16 {