mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
shuf: adapt to API changes of rand
This commit is contained in:
parent
14ce43fe52
commit
527602248f
2 changed files with 14 additions and 24 deletions
|
@ -16,7 +16,7 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use rand_core::{impls, Error, RngCore};
|
use rand_core::{impls, RngCore};
|
||||||
|
|
||||||
/// An RNG that reads random bytes straight from any type supporting
|
/// An RNG that reads random bytes straight from any type supporting
|
||||||
/// [`std::io::Read`], for example files.
|
/// [`std::io::Read`], for example files.
|
||||||
|
@ -30,11 +30,10 @@ use rand_core::{impls, Error, RngCore};
|
||||||
///
|
///
|
||||||
/// `ReadRng` uses [`std::io::Read::read_exact`], which retries on interrupts.
|
/// `ReadRng` uses [`std::io::Read::read_exact`], which retries on interrupts.
|
||||||
/// All other errors from the underlying reader, including when it does not
|
/// All other errors from the underlying reader, including when it does not
|
||||||
/// have enough data, will only be reported through [`try_fill_bytes`].
|
/// have enough data, will only be reported through `try_fill_bytes`.
|
||||||
/// The other [`RngCore`] methods will panic in case of an error.
|
/// The other [`RngCore`] methods will panic in case of an error.
|
||||||
///
|
///
|
||||||
/// [`OsRng`]: rand::rngs::OsRng
|
/// [`OsRng`]: rand::rngs::OsRng
|
||||||
/// [`try_fill_bytes`]: RngCore::try_fill_bytes
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ReadRng<R> {
|
pub struct ReadRng<R> {
|
||||||
reader: R,
|
reader: R,
|
||||||
|
@ -45,6 +44,14 @@ impl<R: Read> ReadRng<R> {
|
||||||
pub fn new(r: R) -> Self {
|
pub fn new(r: R) -> Self {
|
||||||
Self { reader: r }
|
Self { reader: r }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), ReadError> {
|
||||||
|
if dest.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`.
|
||||||
|
self.reader.read_exact(dest).map_err(ReadError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read> RngCore for ReadRng<R> {
|
impl<R: Read> RngCore for ReadRng<R> {
|
||||||
|
@ -61,16 +68,6 @@ impl<R: Read> RngCore for ReadRng<R> {
|
||||||
panic!("reading random bytes from Read implementation failed; error: {err}");
|
panic!("reading random bytes from Read implementation failed; error: {err}");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
|
||||||
if dest.is_empty() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
// Use `std::io::read_exact`, which retries on `ErrorKind::Interrupted`.
|
|
||||||
self.reader
|
|
||||||
.read_exact(dest)
|
|
||||||
.map_err(|e| Error::new(ReadError(e)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ReadRng` error type
|
/// `ReadRng` error type
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use clap::{crate_version, Arg, ArgAction, Command};
|
use clap::{crate_version, Arg, ArgAction, Command};
|
||||||
use memchr::memchr_iter;
|
use memchr::memchr_iter;
|
||||||
use rand::prelude::SliceRandom;
|
use rand::prelude::{IndexedRandom, SliceRandom};
|
||||||
use rand::{Rng, RngCore};
|
use rand::{Rng, RngCore};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -299,7 +299,7 @@ impl Shufable for RangeInclusive<usize> {
|
||||||
self.is_empty()
|
self.is_empty()
|
||||||
}
|
}
|
||||||
fn choose(&self, rng: &mut WrappedRng) -> usize {
|
fn choose(&self, rng: &mut WrappedRng) -> usize {
|
||||||
rng.gen_range(self.clone())
|
rng.random_range(self.clone())
|
||||||
}
|
}
|
||||||
type PartialShuffleIterator<'b>
|
type PartialShuffleIterator<'b>
|
||||||
= NonrepeatingIterator<'b>
|
= NonrepeatingIterator<'b>
|
||||||
|
@ -348,7 +348,7 @@ impl<'a> NonrepeatingIterator<'a> {
|
||||||
match &mut self.buf {
|
match &mut self.buf {
|
||||||
NumberSet::AlreadyListed(already_listed) => {
|
NumberSet::AlreadyListed(already_listed) => {
|
||||||
let chosen = loop {
|
let chosen = loop {
|
||||||
let guess = self.rng.gen_range(self.range.clone());
|
let guess = self.rng.random_range(self.range.clone());
|
||||||
let newly_inserted = already_listed.insert(guess);
|
let newly_inserted = already_listed.insert(guess);
|
||||||
if newly_inserted {
|
if newly_inserted {
|
||||||
break guess;
|
break guess;
|
||||||
|
@ -435,7 +435,7 @@ fn shuf_exec(input: &mut impl Shufable, opts: Options) -> UResult<()> {
|
||||||
.map_err_context(|| format!("failed to open random source {}", r.quote()))?;
|
.map_err_context(|| format!("failed to open random source {}", r.quote()))?;
|
||||||
WrappedRng::RngFile(rand_read_adapter::ReadRng::new(file))
|
WrappedRng::RngFile(rand_read_adapter::ReadRng::new(file))
|
||||||
}
|
}
|
||||||
None => WrappedRng::RngDefault(rand::thread_rng()),
|
None => WrappedRng::RngDefault(rand::rng()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if opts.repeat {
|
if opts.repeat {
|
||||||
|
@ -520,13 +520,6 @@ impl RngCore for WrappedRng {
|
||||||
Self::RngDefault(r) => r.fill_bytes(dest),
|
Self::RngDefault(r) => r.fill_bytes(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
|
|
||||||
match self {
|
|
||||||
Self::RngFile(r) => r.try_fill_bytes(dest),
|
|
||||||
Self::RngDefault(r) => r.try_fill_bytes(dest),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue