···5use nailconfig::NailConfig;
6use nailkov::NailKov;
7use nailrng::FastRng;
8-use rand::{Rng, RngCore, distr::Alphanumeric, seq::IndexedRandom};
910/// Provides either the minimum configured size, or a randomised value between
11/// the minimum and maximum configured sizes if a maximum is available.
12#[inline]
13-fn get_desired_size(config: &NailConfig, rng: &mut impl RngCore) -> usize {
14 match (
15 config.generator.min_paragraph_size,
16 config.generator.max_paragraph_size,
···26pub fn text_generator<'a>(
27 chain: &'a NailKov,
28 size: usize,
29- rng: &'a mut impl RngCore,
30) -> impl Iterator<Item = &'a u8> + 'a {
31 chain
32 .generate_tokens(rng)
···169fn paragraph<'a>(
170 chain: &'a NailKov,
171 size: usize,
172- rng: &'a mut impl RngCore,
173) -> impl Iterator<Item = &'a u8> + 'a {
174 b"<p>"
175 .iter()
···181fn header<'a>(
182 chain: &'a NailKov,
183 size: usize,
184- rng: &'a mut impl RngCore,
185) -> impl Iterator<Item = &'a u8> + 'a {
186 b"\n<h2>"
187 .iter()
···5use nailconfig::NailConfig;
6use nailkov::NailKov;
7use nailrng::FastRng;
8+use rand::{RngExt, Rng, distr::Alphanumeric, seq::IndexedRandom};
910/// Provides either the minimum configured size, or a randomised value between
11/// the minimum and maximum configured sizes if a maximum is available.
12#[inline]
13+fn get_desired_size(config: &NailConfig, rng: &mut impl Rng) -> usize {
14 match (
15 config.generator.min_paragraph_size,
16 config.generator.max_paragraph_size,
···26pub fn text_generator<'a>(
27 chain: &'a NailKov,
28 size: usize,
29+ rng: &'a mut impl Rng,
30) -> impl Iterator<Item = &'a u8> + 'a {
31 chain
32 .generate_tokens(rng)
···169fn paragraph<'a>(
170 chain: &'a NailKov,
171 size: usize,
172+ rng: &'a mut impl Rng,
173) -> impl Iterator<Item = &'a u8> + 'a {
174 b"<p>"
175 .iter()
···181fn header<'a>(
182 chain: &'a NailKov,
183 size: usize,
184+ rng: &'a mut impl Rng,
185) -> impl Iterator<Item = &'a u8> + 'a {
186 b"\n<h2>"
187 .iter()
+4-4
crates/nailkov/src/lib.rs
···13use estr::IdentityHasher;
14use indexmap::IndexMap;
15use itertools::Itertools;
16-use rand::{RngCore, seq::IteratorRandom};
17use rand_distr::Distribution;
1819use distribution::{TokenWeights, TokenWeightsBuilder};
···29 chain: CachePadded<IndexMap<TokenPair, TokenWeights, TokenHasher>>,
30}
3132-pub struct NailKovIter<'a, R: RngCore> {
33 rng: &'a mut R,
34 markov: &'a NailKov,
35 prev: TokenPair,
36}
3738-impl<R: RngCore> Iterator for NailKovIter<'_, R> {
39 type Item = Token;
4041 #[inline]
···5253impl NailKov {
54 #[inline]
55- pub fn generate_tokens<'a, R: RngCore>(&'a self, rng: &'a mut R) -> NailKovIter<'a, R> {
56 NailKovIter {
57 // A markov chain that was successfully built is never empty, so
58 // it will always return with a value, making unwrapping it safe to do.
···13use estr::IdentityHasher;
14use indexmap::IndexMap;
15use itertools::Itertools;
16+use rand::{Rng, seq::IteratorRandom};
17use rand_distr::Distribution;
1819use distribution::{TokenWeights, TokenWeightsBuilder};
···29 chain: CachePadded<IndexMap<TokenPair, TokenWeights, TokenHasher>>,
30}
3132+pub struct NailKovIter<'a, R: Rng> {
33 rng: &'a mut R,
34 markov: &'a NailKov,
35 prev: TokenPair,
36}
3738+impl<R: Rng> Iterator for NailKovIter<'_, R> {
39 type Item = Token;
4041 #[inline]
···5253impl NailKov {
54 #[inline]
55+ pub fn generate_tokens<'a, R: Rng>(&'a self, rng: &'a mut R) -> NailKovIter<'a, R> {
56 NailKovIter {
57 // A markov chain that was successfully built is never empty, so
58 // it will always return with a value, making unwrapping it safe to do.
+1-1
crates/nailrng/Cargo.toml
···910[dependencies]
11rand_core.workspace = true
12-getrandom = { version = "0.3.2", features = ["std"] }
13wyrand.workspace = true
···910[dependencies]
11rand_core.workspace = true
12+getrandom = { version = "0.4", features = ["std"] }
13wyrand.workspace = true
+11-8
crates/nailrng/src/lib.rs
···1//! A very fast, user-space RNG source in the same vein as `rand`'s `ThreadRng`. Not cryptographically secure,
2//! is meant to be a very fast entropy source.
304use std::cell::UnsafeCell;
56-use rand_core::RngCore;
7use wyrand::WyRand;
89thread_local! {
···34 }
35}
3637-impl RngCore for FastRng {
0038 #[inline(always)]
39- fn next_u32(&mut self) -> u32 {
40- self.0.next_u32()
41 }
4243 #[inline(always)]
44- fn next_u64(&mut self) -> u64 {
45- self.0.next_u64()
46 }
4748 #[inline(always)]
49- fn fill_bytes(&mut self, dst: &mut [u8]) {
50- self.0.fill_bytes(dst);
51 }
52}
···1//! A very fast, user-space RNG source in the same vein as `rand`'s `ThreadRng`. Not cryptographically secure,
2//! is meant to be a very fast entropy source.
34+use core::convert::Infallible;
5use std::cell::UnsafeCell;
67+use rand_core::{Rng, TryRng};
8use wyrand::WyRand;
910thread_local! {
···35 }
36}
3738+impl TryRng for FastRng {
39+ type Error = Infallible;
40+41 #[inline(always)]
42+ fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
43+ self.0.try_next_u32()
44 }
4546 #[inline(always)]
47+ fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
48+ self.0.try_next_u64()
49 }
5051 #[inline(always)]
52+ fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), Infallible> {
53+ self.0.try_fill_bytes(dst)
54 }
55}
+2-2
crates/nailrt/src/lib.rs
···51 // Main worker MUST start, else we just error out.
52 let rt = tokio::runtime::Builder::new_current_thread()
53 .enable_all()
54- .build()?;
5556 std::thread::scope(|s| {
57 for num in 1..workers.get() {
···7677 match tokio::runtime::Builder::new_current_thread()
78 .enable_all()
79- .build()
80 {
81 Ok(rt) => {
82 rt.block_on(worker_task(
···51 // Main worker MUST start, else we just error out.
52 let rt = tokio::runtime::Builder::new_current_thread()
53 .enable_all()
54+ .build_local(Default::default())?;
5556 std::thread::scope(|s| {
57 for num in 1..workers.get() {
···7677 match tokio::runtime::Builder::new_current_thread()
78 .enable_all()
79+ .build_local(Default::default())
80 {
81 Ok(rt) => {
82 rt.block_on(worker_task(