From 9a2d089fc0fab5ebc09fa99ab9cd4fe95846bb58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Rica=20Pais=20da=20Silva?= Date: Mon, 11 Nov 2024 17:28:24 +0100 Subject: [PATCH] refactor: Reenable 512 bit variants of Xoshiro with remote reflected Seed512 --- README.md | 2 +- bevy_prng/README.md | 16 ++++--- bevy_prng/src/newtype.rs | 83 ++++++++++++++++++++++++++++++++++++ bevy_prng/src/xoshiro.rs | 47 +++++++++++++++++++- src/prelude.rs | 4 +- src/seed.rs | 2 +- tutorial/01-choosing-prng.md | 2 +- 7 files changed, 142 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 0a8cf54..e7feee0 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ fn setup_npc_from_source( - **`serialize`** - Enables `Serialize` and `Deserialize` derives. Enabled by default. - **`rand_chacha`** - This enables the exporting of newtyped `ChaCha*Rng` structs, for those that want/need to use a CSPRNG level source. - **`rand_pcg`** - This enables the exporting of newtyped `Pcg*` structs from `rand_pcg`. -- **`rand_xoshiro`** - This enables the exporting of newtyped `Xoshiro*` structs from `rand_xoshiro`. +- **`rand_xoshiro`** - This enables the exporting of newtyped `Xoshiro*` structs from `rand_xoshiro`. It also exports a remote-reflected version of `Seed512` so to allow setting up `Xoshiro512StarStar` and so forth. - **`wyrand`** - This enables the exporting of newtyped `WyRand` from `wyrand`, the same algorithm in use within `fastrand`/`turborand`. ## Supported Versions & MSRV diff --git a/bevy_prng/README.md b/bevy_prng/README.md index 7b4ced4..af13777 100644 --- a/bevy_prng/README.md +++ b/bevy_prng/README.md @@ -15,7 +15,7 @@ By default, `bevy_prng` won't export anything _unless_ the feature/algorithm you - **`rand_chacha`** - This enables the exporting of newtyped `ChaCha*Rng` structs, for those that want/need to use a CSPRNG level source. - **`rand_pcg`** - This enables the exporting of newtyped `Pcg*` structs from `rand_pcg`. -- **`rand_xoshiro`** - This enables the exporting of newtyped `Xoshiro*` structs from `rand_xoshiro`. +- **`rand_xoshiro`** - This enables the exporting of newtyped `Xoshiro*` structs from `rand_xoshiro`. It also exports a remote-reflected version of `Seed512` so to allow setting up `Xoshiro512StarStar` and so forth. - **`wyrand`** - This enables the exporting of newtyped `WyRand` from `wyrand`, the same algorithm in use within `fastrand`/`turborand`. In addition to these feature flags to enable various supported algorithms, there's also **`serialize`** flag to provide `serde` support for `Serialize`/`Deserialize`, which is enabled by default. @@ -44,17 +44,19 @@ All the below crates implement the necessary traits to be compatible with `bevy_ `bevy_prng` uses the same MSRV as `bevy`. -| `bevy` | `bevy_prng` | -| ------ | ----------- | -| v0.13 | v0.5 | -| v0.12 | v0.2 | -| v0.11 | v0.1 | +| `bevy` | `bevy_prng` | +| ------ | ------------ | +| v0.15 | v0.8 | +| v0.14 | v0.7 -> v0.8 | +| v0.13 | v0.5 -> v0.6 | +| v0.12 | v0.2 | +| v0.11 | v0.1 | The versions of `rand_core`/`rand` that `bevy_prng` is compatible with is as follows: | `bevy_prng` | `rand_core` | `rand` | | ------------ | ----------- | ------ | -| v0.1 -> v0.5 | v0.6 | v0.8 | +| v0.1 -> v0.8 | v0.6 | v0.8 | ## License diff --git a/bevy_prng/src/newtype.rs b/bevy_prng/src/newtype.rs index 5d422ac..abee5b3 100644 --- a/bevy_prng/src/newtype.rs +++ b/bevy_prng/src/newtype.rs @@ -57,6 +57,88 @@ macro_rules! newtype_prng { fn from_seed(seed: Self::Seed) -> Self { Self::new(<$rng>::from_seed(seed)) } + + #[inline] + fn from_rng(source: R) -> Result { + Ok(Self::new(<$rng>::from_rng(source)?)) + } + } + + impl From<$rng> for $newtype { + #[inline] + fn from(value: $rng) -> Self { + Self::new(value) + } + } + + impl SeedableEntropySource for $newtype {} + }; +} + +macro_rules! newtype_prng_remote { + ($newtype:tt, $rng:ty, $seed:ty, $doc:tt, $feature:tt) => { + #[doc = $doc] + #[derive(Debug, Clone, PartialEq, Reflect)] + #[cfg_attr( + feature = "serialize", + derive(::serde_derive::Serialize, ::serde_derive::Deserialize) + )] + #[cfg_attr( + all(feature = "serialize"), + reflect(opaque, Debug, PartialEq, FromReflect, Serialize, Deserialize) + )] + #[cfg_attr( + all(not(feature = "serialize")), + reflect(opaque, Debug, PartialEq, FromReflect) + )] + #[cfg_attr(docsrs, doc(cfg(feature = $feature)))] + #[type_path = "bevy_prng"] + #[repr(transparent)] + pub struct $newtype($rng); + + impl $newtype { + /// Create a new instance. + #[inline(always)] + #[must_use] + pub fn new(rng: $rng) -> Self { + Self(rng) + } + } + + impl RngCore for $newtype { + #[inline(always)] + fn next_u32(&mut self) -> u32 { + self.0.next_u32() + } + + #[inline(always)] + fn next_u64(&mut self) -> u64 { + self.0.next_u64() + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.0.fill_bytes(dest) + } + + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), ::rand_core::Error> { + self.0.try_fill_bytes(dest) + } + } + + impl SeedableRng for $newtype { + type Seed = $seed; + + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + Self::new(<$rng>::from_seed(seed.0)) + } + + #[inline] + fn from_rng(source: R) -> Result { + Ok(Self::new(<$rng>::from_rng(source)?)) + } } impl From<$rng> for $newtype { @@ -71,3 +153,4 @@ macro_rules! newtype_prng { } pub(crate) use newtype_prng; +pub(crate) use newtype_prng_remote; diff --git a/bevy_prng/src/xoshiro.rs b/bevy_prng/src/xoshiro.rs index a1c00a7..dc38342 100644 --- a/bevy_prng/src/xoshiro.rs +++ b/bevy_prng/src/xoshiro.rs @@ -1,11 +1,54 @@ -use crate::{newtype::newtype_prng, SeedableEntropySource}; +use crate::{ + newtype::{newtype_prng, newtype_prng_remote}, + SeedableEntropySource, +}; -use bevy::prelude::{Reflect, ReflectFromReflect}; +use bevy::{ + prelude::{Reflect, ReflectDefault, ReflectFromReflect}, + reflect::reflect_remote, +}; use rand_core::{RngCore, SeedableRng}; #[cfg(feature = "serialize")] use bevy::prelude::{ReflectDeserialize, ReflectSerialize}; +/// Remote reflected version of [`rand_xoshiro::Seed512`], needed to support +/// proper reflection for the 512 bit variants of the Xoshiro PRNG. +#[reflect_remote(::rand_xoshiro::Seed512)] +#[derive(Debug, Default, Clone)] +#[reflect(Debug, Default)] +pub struct Seed512(pub [u8; 64]); + +impl AsMut<[u8]> for Seed512 { + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } +} + +newtype_prng_remote!( + Xoshiro512StarStar, + ::rand_xoshiro::Xoshiro512StarStar, + Seed512, + "A newtyped [`rand_xoshiro::Xoshiro512StarStar`] RNG", + "rand_xoshiro" +); + +newtype_prng_remote!( + Xoshiro512PlusPlus, + ::rand_xoshiro::Xoshiro512PlusPlus, + Seed512, + "A newtyped [`rand_xoshiro::Xoshiro512PlusPlus`] RNG", + "rand_xoshiro" +); + +newtype_prng_remote!( + Xoshiro512Plus, + ::rand_xoshiro::Xoshiro512Plus, + Seed512, + "A newtyped [`rand_xoshiro::Xoshiro512Plus`] RNG", + "rand_xoshiro" +); + newtype_prng!( Xoshiro256StarStar, ::rand_xoshiro::Xoshiro256StarStar, diff --git a/src/prelude.rs b/src/prelude.rs index b010fa9..ab070fe 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -21,7 +21,7 @@ pub use bevy_prng::{Pcg32, Pcg64, Pcg64Mcg}; #[cfg(feature = "rand_xoshiro")] #[cfg_attr(docsrs, doc(cfg(feature = "rand_xoshiro")))] pub use bevy_prng::{ - Xoroshiro128Plus, Xoroshiro128PlusPlus, Xoroshiro128StarStar, Xoroshiro64Star, + Seed512, Xoroshiro128Plus, Xoroshiro128PlusPlus, Xoroshiro128StarStar, Xoroshiro64Star, Xoroshiro64StarStar, Xoshiro128Plus, Xoshiro128PlusPlus, Xoshiro128StarStar, Xoshiro256Plus, - Xoshiro256PlusPlus, Xoshiro256StarStar, + Xoshiro256PlusPlus, Xoshiro256StarStar, Xoshiro512Plus, Xoshiro512PlusPlus, Xoshiro512StarStar, }; diff --git a/src/seed.rs b/src/seed.rs index cd3e522..3db301d 100644 --- a/src/seed.rs +++ b/src/seed.rs @@ -103,7 +103,7 @@ mod tests { assert!(value.is_dynamic()); assert!(value.represents::>()); - assert!(!value.try_downcast_ref::>().is_some()); + assert!(value.try_downcast_ref::>().is_none()); let recreated = RngSeed::::from_reflect(value.as_ref()).unwrap(); diff --git a/tutorial/01-choosing-prng.md b/tutorial/01-choosing-prng.md index 237c25f..c79411e 100644 --- a/tutorial/01-choosing-prng.md +++ b/tutorial/01-choosing-prng.md @@ -61,7 +61,7 @@ fn main() { The current set of PRNG algorithms that are supported out of the box in `bevy_prng` are as follows: - `wyrand`: This provides newtyped `WyRand` from `wyrand`, the same algorithm in use within `fastrand`/`turborand`. -- `rand_xoshiro`: This provides newtyped `Xoshiro*` structs from `rand_xoshiro`. +- `rand_xoshiro`: This provides newtyped `Xoshiro*` structs from `rand_xoshiro`. It also exports a remote-reflected version of `Seed512` so to allow setting up `Xoshiro512StarStar` and so forth. - `rand_pcg`: This provides newtyped `Pcg*` structs from `rand_pcg`. - `rand_chacha`: This provides newtyped `ChaCha*Rng` structs, for those that want/need to use a CSPRNG level source.