Skip to content

Commit

Permalink
Merge pull request #261 from artichoke/dev/lopopolo-rand-0.9
Browse files Browse the repository at this point in the history
Upgrade to `rand_core` 0.9, MSRV 1.81.0, breaking change bonanza
  • Loading branch information
lopopolo authored Jan 30, 2025
2 parents 697446b + 2bb37d2 commit 659bf08
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 390 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,26 +57,21 @@ jobs:
- name: Install Rust toolchain
uses: artichoke/setup-rust/build-and-test@v1.12.1
with:
toolchain: "1.47.0"
toolchain: "1.81.0"

- name: Compile
run: cargo build --verbose

# skip tests because dev dependencies have a higher MSRV than rand_mt does.
- name: Compile tests
if: false
run: cargo test --no-run

- name: Test
if: false
run: cargo test

- name: Test with all features
if: false
run: cargo test --all-features

- name: Test with no default features
if: false
run: cargo test --no-default-features

rust:
Expand Down
26 changes: 12 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
[package]
name = "rand_mt"
version = "4.2.2" # remember to set `html_root_url` in `src/lib.rs`.
authors = ["David Creswick <dcrewi@gyrae.net>", "Ryan Lopopolo <rjl@hyperbo.la>"]
version = "5.0.0" # remember to set `html_root_url` in `src/lib.rs`.
authors = [
"David Creswick <dcrewi@gyrae.net>",
"Ryan Lopopolo <rjl@hyperbo.la>",
]
license = "MIT OR Apache-2.0"
edition = "2018"
rust-version = "1.47.0"
edition = "2021"
rust-version = "1.81.0"
readme = "README.md"
repository = "https://github.com/artichoke/rand_mt"
documentation = "https://docs.rs/rand_mt"
homepage = "https://github.com/artichoke/rand_mt"
description = "Reference Mersenne Twister random number generators."
keywords = ["random", "rand", "rng", "mt"]
categories = ["algorithms", "no-std", "no-std::no-alloc"]
include = ["src/**/*", "tests/**/*", "LICENSE-*", "README.md"]
include = ["/src/**/*", "/tests/**/*", "/LICENSE-*", "/README.md"]

[features]
default = ["rand-traits", "std"]
rand-traits = ["rand_core"]
# Enables `std::error::Error` impls.
std = []
default = ["rand-traits"]
rand-traits = ["dep:rand_core"]

[dependencies]
# 0.6.1 is vulnerable to underfilling a buffer.
#
# https://rustsec.org/advisories/RUSTSEC-2021-0023
rand_core = { version = "0.6.2", default-features = false, optional = true }
rand_core = { version = "0.9.0", default-features = false, optional = true }

[dev-dependencies]
getrandom = { version = "0.2.0", default-features = false }
getrandom = { version = "0.3.1", default-features = false }

# Check that crate versions are properly updated in documentation and code when
# bumping the version.
Expand Down
18 changes: 8 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,22 @@ The Mersenne Twister algorithms are not suitable for cryptographic uses, but are
ubiquitous. See the [Mersenne Twister website]. A variant of Mersenne Twister is
the [default PRNG in Ruby].

[mersenne twister website]:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
[default prng in ruby]: https://ruby-doc.org/core-3.1.2/Random.html

This crate optionally depends on [`rand_core`] and implements `RngCore` on the
RNGs in this crate.

[`rand_core`]: https://crates.io/crates/rand_core

## Usage

Add this to your `Cargo.toml`:

```toml
[dependencies]
rand_mt = "4.2.2"
rand_mt = "5.0.0"
```

Then create a RNG like:
Expand All @@ -46,16 +52,14 @@ are enabled by default:

- **rand-traits** - Enables a dependency on [`rand_core`]. Activating this
feature implements `RngCore` and `SeedableRng` on the RNGs in this crate.
- **std** - Enables a dependency on the Rust Standard Library. Activating this
feature enables [`std::error::Error`] impls on error types in this crate.

Mersenne Twister requires approximately 2.5 kilobytes of internal state. To make
the RNGs implemented in this crate practical to embed in other structs, you may
wish to store the RNG in a `Box`.

### Minimum Supported Rust Version

This crate requires at least Rust 1.47.0. This version can be bumped in minor
This crate requires at least Rust 1.81.0. This version can be bumped in minor
releases.

## License
Expand All @@ -67,10 +71,4 @@ releases.
`rand_mt` is derived from `rust-mersenne-twister` @ [`1.1.1`] which is Copyright
(c) 2015 rust-mersenne-twister developers.

[mersenne twister website]:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
[default prng in ruby]: https://ruby-doc.org/core-3.1.2/Random.html
[`rand_core`]: https://crates.io/crates/rand_core
[`rand_core`]: https://crates.io/crates/rand_core
[`std::error::error`]: https://doc.rust-lang.org/std/error/trait.Error.html
[`1.1.1`]: https://github.com/dcrewi/rust-mersenne-twister/tree/1.1.1
68 changes: 21 additions & 47 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,16 @@
//!
//! This crate provides:
//!
//! - [`Mt19937GenRand32`], the original reference Mersenne Twister
//! implementation known as `MT19937`. This is a good choice on both 32-bit
//! and 64-bit CPUs (for 32-bit output).
//! - [`Mt19937GenRand64`], the 64-bit variant of `MT19937` known as
//! `MT19937-64`. This algorithm produces a different output stream than
//! `MT19937` and produces 64-bit output. This is a good choice on 64-bit
//! CPUs.
//! - [`Mt`], the original reference Mersenne Twister implementation known as
//! `MT19937`. This is a good choice on both 32-bit and 64-bit CPUs (for
//! 32-bit output).
//! - [`Mt64`], the 64-bit variant of `MT19937` known as `MT19937-64`. This
//! algorithm produces a different output stream than `MT19937` and produces
//! 64-bit output. This is a good choice on 64-bit CPUs.
//!
//! Both of these RNGs use approximately 2.5 kilobytes of state.
//! [`Mt19937GenRand32`] uses a 32-bit seed. [`Mt19937GenRand64`] uses a 64-bit
//! seed. Both can be seeded from an iterator of seeds.
//! Both of these RNGs use approximately 2.5 kilobytes of state. [`Mt`] uses a
//! 32-bit seed. [`Mt64`] uses a 64-bit seed. Both can be seeded from an
//! iterator of seeds.
//!
//! Both RNGs implement a `recover` constructor which can reconstruct the RNG
//! state from a sequence of output samples.
Expand Down Expand Up @@ -79,54 +78,34 @@
//!
//! - **rand-traits** - Enables a dependency on [`rand_core`]. Activating this
//! feature implements `RngCore` and `SeedableRng` on the RNGs in this crate.
//! - **std** - Enables a dependency on the Rust Standard Library. Activating
//! this feature enables [`std::error::Error`] impls on error types in this
//! crate.
//!
//! Mersenne Twister requires approximately 2.5 kilobytes of internal state. To
//! make the RNGs implemented in this crate practical to embed in other structs,
//! you may wish to store the RNG in a [`Box`].
//!
#![cfg_attr(
not(feature = "std"),
doc = "[`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html"
)]
#![cfg_attr(feature = "std", doc = "[`Box`]: std::boxed::Box")]
#![cfg_attr(
not(feature = "std"),
doc = "[`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html"
)]
#![cfg_attr(
not(feature = "rand_core"),
not(feature = "rand-traits"),
doc = "[`rand_core`]: https://crates.io/crates/rand_core"
)]
//!
//! [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html"
#![doc(html_root_url = "https://docs.rs/rand_mt/4.2.2")]
#![doc(html_root_url = "https://docs.rs/rand_mt/5.0.0")]
#![no_std]

#[cfg(feature = "std")]
#[cfg(any(test, doctest))]
extern crate std;

use core::fmt;

pub use crate::mt::Mt19937GenRand32;
pub use crate::mt64::Mt19937GenRand64;
pub use crate::mt::Mt;
pub use crate::mt64::Mt64;

mod mt;
mod mt64;
#[cfg(test)]
mod vectors;

/// A type alias for [`Mt19937GenRand32`], 32-bit Mersenne Twister.
pub type Mt = Mt19937GenRand32;

/// A type alias for [`Mt19937GenRand64`], 64-bit Mersenne Twister.
pub type Mt64 = Mt19937GenRand64;

/// Error returned from fallible Mersenne Twister recovery constructors.
///
/// When the `std` feature is enabled, this type implements `std::error::Error`.
#[non_exhaustive]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum RecoverRngError {
Expand All @@ -151,27 +130,22 @@ impl fmt::Display for RecoverRngError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::TooFewSamples(expected) => {
write!(f, "Too few samples given to recover: expected {}", expected)
write!(f, "Too few samples given to recover: expected {expected}")
}
Self::TooManySamples(expected) => {
write!(f, "Too many samples given to recover: expected {expected}")
}
Self::TooManySamples(expected) => write!(
f,
"Too many samples given to recover: expected {}",
expected
),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for RecoverRngError {}
impl core::error::Error for RecoverRngError {}

#[cfg(test)]
mod tests {
#[cfg(feature = "std")]
use super::RecoverRngError;

#[test]
#[cfg(feature = "std")]
fn error_display_is_not_empty() {
use core::fmt::Write as _;
use std::string::String;
Expand All @@ -184,7 +158,7 @@ mod tests {
];
for tc in test_cases {
let mut buf = String::new();
write!(&mut buf, "{}", tc).unwrap();
write!(&mut buf, "{tc}").unwrap();
assert!(!buf.is_empty());
}
}
Expand Down
Loading

0 comments on commit 659bf08

Please sign in to comment.