From c95a4a156bc460ad0fcf7a1053a87e12d24d1042 Mon Sep 17 00:00:00 2001 From: Vinzent Steinberg Date: Mon, 9 Apr 2018 19:15:21 +0200 Subject: [PATCH 1/5] Docs for implementing `SeedableRng` for large seeds Fixes #354. --- rand_core/src/lib.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 93da90208d4..fc44acaf20e 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -284,6 +284,28 @@ pub trait SeedableRng: Sized { /// partially overlapping periods. /// /// For cryptographic RNG's a seed of 256 bits is recommended, `[u8; 32]`. + /// + /// + /// # Implementing `SeedableRng` for RNGs with large seeds + /// + /// Note that the required traits `core::default::Default` and + /// `core::convert::AsMut` are not implemented for large arrays + /// `[u8; N]` with `N` > 32. To be able to implement the traits required by + /// `SeedableRng` for RNGs with such large seeds, the newtype pattern can be + /// used: + /// + /// ```ignore + /// pub struct MyRngSeed(pub [u8; N]); + /// + /// impl Default for MyRngSeed { ... } + /// impl AsMut for MyRngSeed { ... } + /// + /// impl SeedableRng for MyRng { + /// type Seed = MyRngSeed; + /// + /// fn from_seed(seed: MyRngSeed) -> MyRng { ... } + /// } + /// ``` type Seed: Sized + Default + AsMut<[u8]>; /// Create a new PRNG using the given seed. @@ -307,6 +329,25 @@ pub trait SeedableRng: Sized { /// seeds it is preferable to map these to alternative constant value(s), /// for example `0xBAD5EEDu32` or `0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad /// seed"). This is assuming only a small number of values must be rejected. + /// Alternatively, the newtype pattern can be used to make sure only valid + /// seeds can be constructed: + /// + /// ```ignore + /// pub struct MyRngSeed([u8; N]); + /// + /// impl MyRngSeed { + /// fn new(seed: [u8; N]) -> Option { ... } + /// } + /// + /// impl Default for MyRngSeed { ... } + /// impl AsMut for MyRngSeed { ... } + /// + /// impl SeedableRng for MyRng { + /// type Seed = MyRngSeed; + /// + /// fn from_seed(seed: MyRngSeed) -> MyRng { ... } + /// } + /// ``` fn from_seed(seed: Self::Seed) -> Self; /// Create a new PRNG seeded from another `Rng`. From dce75101f0947876fef705a6e550bb0d2be4d189 Mon Sep 17 00:00:00 2001 From: Vinzent Steinberg Date: Tue, 10 Apr 2018 10:58:06 +0200 Subject: [PATCH 2/5] Don't suggest newtype pattern to work around invalid seeds This does not work, because the seed has to implement `AsMut<[u8]>`, so any invariants enforced by the constructor can be circumvented. --- rand_core/src/lib.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index fc44acaf20e..216a46059d9 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -329,25 +329,6 @@ pub trait SeedableRng: Sized { /// seeds it is preferable to map these to alternative constant value(s), /// for example `0xBAD5EEDu32` or `0x0DDB1A5E5BAD5EEDu64` ("odd biases? bad /// seed"). This is assuming only a small number of values must be rejected. - /// Alternatively, the newtype pattern can be used to make sure only valid - /// seeds can be constructed: - /// - /// ```ignore - /// pub struct MyRngSeed([u8; N]); - /// - /// impl MyRngSeed { - /// fn new(seed: [u8; N]) -> Option { ... } - /// } - /// - /// impl Default for MyRngSeed { ... } - /// impl AsMut for MyRngSeed { ... } - /// - /// impl SeedableRng for MyRng { - /// type Seed = MyRngSeed; - /// - /// fn from_seed(seed: MyRngSeed) -> MyRng { ... } - /// } - /// ``` fn from_seed(seed: Self::Seed) -> Self; /// Create a new PRNG seeded from another `Rng`. From b75cfb59fcf877c5ba114bd57475e9a42fb64b22 Mon Sep 17 00:00:00 2001 From: Vinzent Steinberg Date: Tue, 10 Apr 2018 11:09:18 +0200 Subject: [PATCH 3/5] Expand large seed example so it compiles --- rand_core/src/lib.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 216a46059d9..9a6b39d3228 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -294,16 +294,35 @@ pub trait SeedableRng: Sized { /// `SeedableRng` for RNGs with such large seeds, the newtype pattern can be /// used: /// - /// ```ignore - /// pub struct MyRngSeed(pub [u8; N]); + /// ``` + /// use rand_core::SeedableRng; + /// + /// pub struct MyRngSeed(pub [u8; 64]); + /// pub struct MyRng(MyRngSeed); /// - /// impl Default for MyRngSeed { ... } - /// impl AsMut for MyRngSeed { ... } + /// impl Default for MyRngSeed { + /// fn default() -> MyRngSeed { + /// MyRngSeed([ + /// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /// ]) + /// } + /// } + /// + /// impl AsMut<[u8]> for MyRngSeed { + /// fn as_mut(&mut self) -> &mut [u8] { + /// &mut self.0 + /// } + /// } /// /// impl SeedableRng for MyRng { /// type Seed = MyRngSeed; /// - /// fn from_seed(seed: MyRngSeed) -> MyRng { ... } + /// fn from_seed(seed: MyRngSeed) -> MyRng { + /// MyRng(MyRngSeed) + /// } /// } /// ``` type Seed: Sized + Default + AsMut<[u8]>; From ed77f12df694d936728d4f1806df1df930570811 Mon Sep 17 00:00:00 2001 From: Vinzent Steinberg Date: Tue, 10 Apr 2018 11:32:23 +0200 Subject: [PATCH 4/5] Simplify example for large seeds --- rand_core/src/lib.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 9a6b39d3228..291edd4daaa 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -297,17 +297,13 @@ pub trait SeedableRng: Sized { /// ``` /// use rand_core::SeedableRng; /// - /// pub struct MyRngSeed(pub [u8; 64]); + /// const N: usize = 64; + /// pub struct MyRngSeed(pub [u8; N]); /// pub struct MyRng(MyRngSeed); /// /// impl Default for MyRngSeed { /// fn default() -> MyRngSeed { - /// MyRngSeed([ - /// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /// ]) + /// MyRngSeed([0; N]) /// } /// } /// From 65e7cf1c5bc5f5e5569ab6e721df4704a86f3c2f Mon Sep 17 00:00:00 2001 From: Vinzent Steinberg Date: Tue, 10 Apr 2018 12:13:17 +0200 Subject: [PATCH 5/5] Fix doctest --- rand_core/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rand_core/src/lib.rs b/rand_core/src/lib.rs index 291edd4daaa..61dc4cb9aed 100644 --- a/rand_core/src/lib.rs +++ b/rand_core/src/lib.rs @@ -317,7 +317,7 @@ pub trait SeedableRng: Sized { /// type Seed = MyRngSeed; /// /// fn from_seed(seed: MyRngSeed) -> MyRng { - /// MyRng(MyRngSeed) + /// MyRng(seed) /// } /// } /// ```