From aa10dd32c483bda57db73272545339366a5b7119 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 11 Mar 2021 17:32:59 +0000 Subject: [PATCH] fake rng: provide facility Signed-off-by: Ian Jackson --- src/config.rs | 8 +++++-- src/fake-rng.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/prelude.rs | 1 + 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/fake-rng.rs diff --git a/src/config.rs b/src/config.rs index 173717df..252ba54c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -36,6 +36,7 @@ pub struct ServerConfigSpec { pub shapelibs: Option>, pub sendmail: Option, pub debug_js_inject_file: Option, + #[serde(default)] pub fake_rng: FakeRngSpec, /// Disable this for local testing only. See LICENCE. pub check_bundled_sources: Option, } @@ -63,6 +64,7 @@ pub struct ServerConfig { pub sendmail: String, pub debug_js_inject: Arc, pub check_bundled_sources: bool, + pub fake_rng: RngWrap, } impl TryFrom for WholeServerConfig { @@ -74,9 +76,11 @@ impl TryFrom for WholeServerConfig { http_port, public_url, sse_wildcard_url, rocket_workers, template_dir, nwtemplate_dir, wasm_dir, log, bundled_sources, shapelibs, sendmail, - debug_js_inject_file, check_bundled_sources, + debug_js_inject_file, check_bundled_sources, fake_rng, } = spec; + let fake_rng = fake_rng.start(); + if let Some(cd) = change_directory { env::set_current_dir(&cd) .context(cd) @@ -178,7 +182,7 @@ impl TryFrom for WholeServerConfig { http_port, public_url, sse_wildcard_url, rocket_workers, template_dir, nwtemplate_dir, wasm_dir, bundled_sources, shapelibs, sendmail, - debug_js_inject, check_bundled_sources, + debug_js_inject, check_bundled_sources, fake_rng, }; WholeServerConfig { server: Arc::new(server), diff --git a/src/fake-rng.rs b/src/fake-rng.rs new file mode 100644 index 00000000..0904b080 --- /dev/null +++ b/src/fake-rng.rs @@ -0,0 +1,60 @@ +// Copyright 2020-2021 Ian Jackson and contributors to Otter +// SPDX-License-Identifier: AGPL-3.0-or-later +// There is NO WARRANTY. + +use crate::prelude::*; + +use parking_lot::Mutex; + +#[derive(Deserialize,Debug,Clone,Default)] +#[serde(transparent)] +pub struct FakeRngSpec(Vec); + +impl FakeRngSpec { + pub fn start(self) -> RngWrap { RngWrap( + if self.0.is_empty() { None } + else { Some(Arc::new(FakeRng { + i: Mutex::new(0), + ents: self.0, + })) } + )} +} + +#[derive(Debug,Clone)] +pub struct RngWrap ( + Option> +); + +#[derive(Debug)] +struct FakeRng { + i: Mutex, + ents: Vec, +} + +impl RngWrap { + pub fn is_fake(&self) -> bool { self.0.is_some() } + + #[throws(as Option)] + fn next(&self) -> &str { + let fake = self.0.as_ref()?; + let mut i = fake.i.lock(); + let e = fake.ents[*i].as_str(); + *i += 1; + *i %= fake.ents.len(); + e + } + + pub fn shuffle(&self, slice: &mut [T]) { match self.next() { + None => { + let mut rng = thread_rng(); + slice.shuffle(&mut rng); + }, + Some(s) => { + let l = slice.len(); + let n: usize = s.parse().unwrap_or(0); + let front = slice[0..n].to_owned(); + slice.copy_within(n.., 0); + slice[l-n..].copy_from_slice(&front); + }, + } } +} diff --git a/src/lib.rs b/src/lib.rs index b569821b..7796d698 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,3 +34,4 @@ pub mod utils; #[path = "shapelib-toml.rs"] pub mod shapelib_toml; #[path = "slotmap-slot-idx.rs"] pub mod slotmap_slot_idx; #[path = "toml-de.rs"] pub mod toml_de; +#[path = "fake-rng.rs"] pub mod fake_rng; diff --git a/src/prelude.rs b/src/prelude.rs index ca98ece1..ea380536 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -115,6 +115,7 @@ pub use crate::commands::{MgmtGameUpdateMode}; pub use crate::config::*; pub use crate::debugreader::DebugReader; pub use crate::error::*; +pub use crate::fake_rng::*; pub use crate::gamestate::*; pub use crate::global::*; pub use crate::hidden::*; -- 2.30.2