From: Ian Jackson Date: Sat, 14 May 2022 19:18:55 +0000 (+0100) Subject: support: Move config X-Git-Tag: otter-1.1.0~168 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=b0b0dfe97a6d8f89d3b7ead0929c7512d3ef10fa;p=otter.git support: Move config Signed-off-by: Ian Jackson --- diff --git a/Cargo.lock b/Cargo.lock index dd68c43d..735bead6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2690,8 +2690,6 @@ dependencies = [ "enum_dispatch", "env_logger 0.9.0", "fehler", - "flexi_logger", - "fs2", "glob", "humantime-serde", "image", @@ -2699,7 +2697,6 @@ dependencies = [ "inventory", "lazy-init", "lazy-regex", - "lazy_static", "libc", "mio 0.8.2", "num", @@ -2708,10 +2705,7 @@ dependencies = [ "openssh-keys", "ordered-float", "otter-support", - "paste", "percent-encoding", - "pwd", - "rand 0.8.5", "regex", "serde", "serde_with", @@ -2723,7 +2717,6 @@ dependencies = [ "tempfile", "tera", "thiserror", - "toml", "typetag", "uds", "unicase", @@ -2830,17 +2823,24 @@ dependencies = [ "console", "derive-into-owned", "fehler", + "flexi_logger", + "fs2", + "lazy_static", "log", "nix 0.23.1", "num-derive", "num-traits", "otter-base", "parking_lot", + "paste", + "pwd", + "rand 0.8.5", "rmp", "rmp-serde", "serde", "serde_with", "strum", + "toml", "unicode-width", ] diff --git a/Cargo.toml b/Cargo.toml index de459ba5..0a04a824 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,29 +44,23 @@ educe="0.4" either="1" enum_dispatch="0.3.5" env_logger="0.9" -fs2="0.4" glob="0.3" humantime-serde="1" inventory="0.2" lazy-init="0.5" lazy-regex="2" -lazy_static="1" libc="0.2" num="0.4" once_cell="1" openssh-keys="0.5" ordered-float="2" -paste="1" percent-encoding="2" -pwd="1" -rand="0.8" regex="1" structopt="0.3" sha2="0.10" subtle="2.4" tempfile="3" tera="1.10" -toml="0.5" typetag="0.1.6" uds="0.2" unicase="2" @@ -80,7 +74,6 @@ ambassador = "0.3.1" async-condvar-fair = { version="0.2", features=["parking_lot_0_12"] } const-default = { version="1", features=["derive" ] } enum-map = { version="2" , features=["serde" ] } -flexi_logger = { version="0.22" , features=["specfile" ] } image = { version = "0.24", default-features=false, features=["jpeg","png"] } index_vec = { version="0.1.1", features=["serde" ] } mio = { version="0.8", features=["os-ext", "os-poll" ] } diff --git a/apitest/apitest.rs b/apitest/apitest.rs index 3a1979c0..91145c53 100644 --- a/apitest/apitest.rs +++ b/apitest/apitest.rs @@ -34,7 +34,7 @@ pub type MC = MgmtCommand; // -------------------- private crates ---------- -use otter::config::DAEMON_STARTUP_REPORT; +use otter_support::config::DAEMON_STARTUP_REPORT; // ==================== public constants ==================== diff --git a/cli/otter.rs b/cli/otter.rs index c8dae276..91d99dd6 100644 --- a/cli/otter.rs +++ b/cli/otter.rs @@ -267,7 +267,7 @@ fn main() { }); ServerConfig::read(Some(&config_filename), default()) .context("read config file")?; - Ok::<_,AE>((otter::config::config(), config_filename)) + Ok::<_,AE>((otter_support::config::config(), config_filename)) })().map_err(|e| ArgumentParseError( format!("failed to find/load config: {}", &e) )) diff --git a/src/accounts.rs b/src/accounts.rs index fb3c6fe7..cd0fd837 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -6,8 +6,6 @@ use crate::prelude::*; use parking_lot::{Mutex, const_mutex, MutexGuard}; -use authproofs::*; - #[path="sshkeys.rs"] pub mod sshkeys; @@ -490,7 +488,6 @@ pub fn load_accounts() { pub mod loaded_acl { use crate::prelude::*; - use authproofs::*; pub trait Perm: FromPrimitive + ToPrimitive + Copy + Eq + Hash + Debug + Sync + Send + 'static diff --git a/src/bin/otterlib.rs b/src/bin/otterlib.rs index fb05bb40..4d618c08 100644 --- a/src/bin/otterlib.rs +++ b/src/bin/otterlib.rs @@ -239,7 +239,7 @@ fn main() { const SPLIT: &[char] = &[',', ' ']; for libs in opts.libs.split(SPLIT) { - let tlibs = Config1::PathGlob(libs.to_owned()); + let tlibs = ShapelibConfig1::PathGlob(libs.to_owned()); load_global_libs(&[tlibs.clone()])?; } let mut items: Vec = default(); diff --git a/src/bundles.rs b/src/bundles.rs index ca6afe66..40b70f27 100644 --- a/src/bundles.rs +++ b/src/bundles.rs @@ -295,8 +295,9 @@ impl Id { //---------- displaing/presenting/authorising ---------- +#[ext(pub)] impl Authorisation { - pub fn bundles(self) -> Authorisation { self.so_promise() } + fn bundles(self) -> Authorisation { self.so_promise() } } impl Display for State { diff --git a/src/commands.rs b/src/commands.rs index 5a9db84a..ec44b62f 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -264,8 +264,8 @@ pub enum MgmtError { #[error("{0}")] CoordinateOverflow (#[from] CoordinateOverflow), #[error("TOML syntax error: {0}")] TomlSyntaxError(String), #[error("TOML structure error: {0}")] TomlStructureError(String), - #[error("RNG is real, command not supported")] RngIsReal, - #[error("Time is real, command not supported")] TimeIsReal, + #[error("{0}, command not supported")] RngIsReal(#[from] RngIsReal), + #[error("{0}, command not supported")] TimeIsReal(#[from] TimeIsReal), #[error("upload truncated")] UploadTruncated, #[error("upload corrupted")] UploadCorrupted, #[error("too many bundles")] TooManyBundles, diff --git a/src/crates.rs b/src/crates.rs index 4f30987d..e670f638 100644 --- a/src/crates.rs +++ b/src/crates.rs @@ -15,23 +15,18 @@ pub use digest; pub use educe; pub use either; pub use env_logger; -pub use flexi_logger; -pub use fs2; pub use glob; pub use humantime_serde::{self, re::humantime}; pub use index_vec; pub use lazy_init; -pub use lazy_static; pub use inventory; pub use libc; pub use once_cell; pub use ordered_float; -pub use pwd; pub use regex; pub use sha2; pub use slotmap; pub use tera; -pub use toml; pub use uds; pub use vecdeque_stableix; pub use zip as zipfile; diff --git a/src/error.rs b/src/error.rs index 47cec919..3b9554ea 100644 --- a/src/error.rs +++ b/src/error.rs @@ -188,8 +188,6 @@ pub enum Inapplicable { BadPieceStateForOperation, } -pub type StartupError = anyhow::Error; - pub use Fatal::{NoClient,NoPlayer}; pub enum AggregatedIE { diff --git a/src/global.rs b/src/global.rs index 50a14812..115345f8 100644 --- a/src/global.rs +++ b/src/global.rs @@ -217,8 +217,6 @@ pub struct Global { // (in order of lock acquisition (L first), so also in order of criticality // (perf impact); outermost first, innermost last) - // slow global locks: - pub save_area_lock: Mutex>, // <- accounts::accounts -> games_table: RwLock, @@ -226,7 +224,6 @@ pub struct Global { // <- InstanceContainer -> // inner locks which the game needs: dirty: Mutex>, - pub config: RwLock, // fast global lookups players: RwLock>, @@ -324,14 +321,15 @@ impl InstanceWeakRef { } } +#[ext(pub)] impl Unauthorised { #[throws(GameBeingDestroyed)] - pub fn lock<'r>(&'r self) -> Unauthorised, A> { + fn lock<'r>(&'r self) -> Unauthorised, A> { let must_not_escape = self.by_ref(Authorisation::promise_any()); Unauthorised::of(must_not_escape.lock()?) } - pub fn lock_even_destroying<'r>(&'r self) -> Unauthorised, A> { + fn lock_even_destroying<'r>(&'r self) -> Unauthorised, A> { let must_not_escape = self.by_ref(Authorisation::promise_any()); Unauthorised::of(InstanceGuard { c: must_not_escape.lock_even_destroying(), @@ -339,7 +337,7 @@ impl Unauthorised { }) } - pub fn lock_bundles<'r>(&'r self) -> Unauthorised, A> { + fn lock_bundles<'r>(&'r self) -> Unauthorised, A> { let must_not_escape = self.by_ref(Authorisation::promise_any()); Unauthorised::of(must_not_escape.lock_bundles()) } diff --git a/src/imports.rs b/src/imports.rs index 53b659c4..bf7b81be 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -20,9 +20,7 @@ pub use std::fmt::{self, Debug, Display}; pub use std::hash::Hash; pub use std::iter; pub use std::iter::{repeat_with}; -pub use std::marker::PhantomData; pub use std::num::{NonZeroUsize, TryFromIntError, Wrapping}; -pub use std::net::{IpAddr, SocketAddr, ToSocketAddrs, Ipv6Addr, Ipv4Addr}; pub use std::path::PathBuf; pub use std::str; pub use std::str::FromStr; @@ -30,7 +28,6 @@ pub use std::string::ParseError; pub use std::sync::atomic::AtomicBool; pub use std::sync::mpsc; pub use std::thread::{self, sleep}; -pub use std::time::{self, Duration, Instant}; pub use async_condvar_fair::{Condvar, BatonExt as _}; pub use boolinator::Boolinator as _; @@ -44,21 +41,12 @@ pub use either::{Either, Left, Right}; pub use enum_dispatch::enum_dispatch; pub use enum_map::{Enum, EnumMap}; pub use fehler::{throw, throws}; -pub use flexi_logger::LogSpecification; -pub use fs2::FileExt; pub use index_vec::{define_index_type, index_vec, IndexSlice, IndexVec}; pub use lazy_regex::regex; -pub use lazy_static::lazy_static; -pub use log::{log, log_enabled}; pub use ordered_float::OrderedFloat; -pub use paste::paste; pub use percent_encoding::percent_decode_str; pub use percent_encoding::utf8_percent_encode; pub use percent_encoding::NON_ALPHANUMERIC; -pub use rand::distributions::Alphanumeric; -pub use rand::thread_rng; -pub use rand::Rng; -pub use rand::prelude::SliceRandom; pub use regex::Regex; pub use sha2::{Sha512, Sha512_256}; pub use slotmap::{dense::DenseSlotMap, SparseSecondaryMap, Key as _}; @@ -88,14 +76,11 @@ pub use crate::{deref_to_field, deref_to_field_mut}; pub use crate::ensure_eq; pub use crate::format_by_fmt_hex; pub use crate::impl_via_ambassador; -pub use crate::trace_dbg; pub use crate::{want, wantok, wants, want_let, want_failed_internal}; pub use crate::serde_with_compat; pub use crate::accounts::loaded_acl::{self, EffectiveACL, LoadedAcl, PermSet}; pub use crate::accounts::*; -pub use crate::authproofs::{self, Authorisation, Unauthorised}; -pub use crate::authproofs::AuthorisationSuperuser; pub use crate::asseturl::*; pub use crate::bundles::{self, InstanceBundles, MgmtBundleListExt}; pub use crate::commands::{AccessTokenInfo, AccessTokenReport, MgmtError}; @@ -103,12 +88,9 @@ pub use crate::commands::{MgmtCommand, MgmtResponse}; pub use crate::commands::{MgmtGameInstruction, MgmtGameResponse}; pub use crate::commands::{MgmtBundleList, MgmtGameUpdateMode}; pub use crate::commands::{ProgressUpdateMode}; -pub use crate::config::*; pub use crate::debugreader::DebugReader; pub use crate::digestrw::{self, *}; pub use crate::error::*; -pub use crate::fake_rng::*; -pub use crate::fake_time::*; pub use crate::fastsplit::*; pub use crate::gamestate::*; pub use crate::global::*; @@ -129,7 +111,6 @@ pub use crate::shapelib::{LibraryLoadError}; pub use crate::slotmap_slot_idx::*; pub use crate::spec::*; pub use crate::spec::piece_specs::{FaceColourSpecs, SimpleCommon}; -pub use crate::toml_de; pub use crate::timedfd::*; pub use crate::updates::*; pub use crate::utils::*; @@ -142,8 +123,6 @@ pub type SecondarySlotMap = slotmap::secondary::SecondaryMap; pub type SvgData = Vec; pub type Colour = Html; -pub const MS: time::Duration = time::Duration::from_millis(1); - // ---------- type abbreviations ---------- // accounts.rs diff --git a/src/lib.rs b/src/lib.rs index 2a3762bc..d9dcc27d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,11 +24,9 @@ pub mod prelude; pub mod accounts; pub mod asseturl; -pub mod authproofs; pub mod bundles; pub mod clock; pub mod commands; -pub mod config; pub mod currency; pub mod deck; pub mod dice; @@ -55,9 +53,6 @@ pub mod updates; pub mod ui; pub mod utils; -#[path = "fake-rng.rs"] pub mod fake_rng; -#[path = "fake-time.rs"] pub mod fake_time; #[path = "materials-format.rs"] pub mod materials_format; #[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; diff --git a/src/shapelib.rs b/src/shapelib.rs index 475819f2..988fd604 100644 --- a/src/shapelib.rs +++ b/src/shapelib.rs @@ -10,6 +10,9 @@ pub use crate::prelude::GoodItemName; // not sure why this is needed use parking_lot::{const_rwlock, RwLock}; use parking_lot::RwLockReadGuard; +use ShapelibConfig1 as Config1; +use ShapelibExplicit1 as Explicit1; + //==================== structs and definitions ==================== // Naming convention: @@ -1504,20 +1507,6 @@ impl<'ig> AllRegistries<'ig> { //==================== configu and loading global libs ==================== -#[derive(Deserialize,Debug,Clone)] -#[serde(untagged)] -pub enum Config1 { - PathGlob(String), - Explicit(Explicit1), -} - -#[derive(Deserialize,Debug,Clone)] -pub struct Explicit1 { - pub name: String, - pub catalogue: String, - pub dirname: String, -} - #[throws(LibraryLoadError)] pub fn load_1_global_library(l: &Explicit1) { let toml_path = &l.catalogue; @@ -1542,7 +1531,8 @@ pub fn load_1_global_library(l: &Explicit1) { count, &l.name, &l.catalogue, &l.dirname); } -impl Config1 { +#[ext(pub)] +impl ShapelibConfig1 { fn resolve(&self) -> Result>, LibraryLoadError> { use Config1::*; Ok(match self { diff --git a/src/utils.rs b/src/utils.rs index 6aa05744..f653cb8c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -125,23 +125,6 @@ pub mod timespec_serde { } } -//---------- IpAddress ---------- - -pub trait IpAddress: Debug { - fn with_port(&self, port: u16) -> SocketAddr; -} - -impl IpAddress for A where A: Into + Debug + Clone { - fn with_port(&self, port: u16) -> SocketAddr { - match (self.clone().into(), port) - .to_socket_addrs() - .map(|i| i.at_most_one()) { - Ok(Ok(Some(addr))) => addr, - x => panic!("{:?},{} gave {:?}", self, port, x), - } - } -} - //---------- get_or_extend_with ---------- @@ -333,74 +316,6 @@ impl Result> // todo: DerefMut -//========== toml ==================== - -#[derive(Debug,Copy,Clone,Eq,PartialEq,Ord,PartialOrd)] -pub struct TomlQuote<'s>(pub &'s str); - -// We reimplement this because the toml crate doesn't expose it, and -// looking at the github issues etc. for that crate isn't encuraging. -impl<'s> Display for TomlQuote<'s> { - #[throws(fmt::Error)] - fn fmt(&self, f: &mut fmt::Formatter) { - for c in self.0.chars() { - match c { - '"' | '\\'=> write!(f, "\\{}", c)?, - c if (c < ' ' && c != '\t') || c == '\x7f' => { - write!(f, r#"\u{:04x}"#, c as u32).unwrap(); - continue; - } - c => write!(f, "{}", c)?, - } - } - } -} - -#[test] -fn toml_quote_string_test(){ - assert_eq!(TomlQuote(r#"w \ " ƒ."#).to_string(), - r#"w \\ \" \u0007\u007fƒ."#); -} - -pub fn toml_merge<'u, - S: 'u + AsRef, - KV: IntoIterator - >( - table: &mut toml::value::Table, - updates: KV, -) { - use toml::value::{Table, Value}; - type TME<'e> = toml::map::Entry<'e>; - - let mut kv = updates.into_iter().map(|(k, v)| (k.as_ref(), v)); - inner(table, &mut kv); - - fn inner<'u>( - table: &mut Table, - updates: &'u mut dyn Iterator - ) { - for (k, v) in updates { - let e = table.entry(k); - match e { - TME::Vacant(ve) => { - ve.insert(v.clone()); - } - TME::Occupied(mut oe) => match (oe.get_mut(), v) { - (Value::Table(old), Value::Table(new)) => { - toml_merge(old, new); - } - (Value::Array(old), Value::Array(new)) => { - old.extend(new.iter().cloned()); - } - (old, new) => { - *old = new.clone(); - } - } - } - } - } -} - //========== .insert() and .remove() on various Entry ========== macro_rules! entry_define_insert_remove { @@ -740,11 +655,6 @@ macro_rules! want_let { //========== miscellaneous macros ========== -paste!{ - #[cfg(debug_assertions)] - pub fn []() -> T { panic!("todo item triggered") } -} - #[macro_export] macro_rules! impl_via_ambassador{ { @@ -765,19 +675,6 @@ macro_rules! impl_via_ambassador{ } )* } } -#[macro_export] -macro_rules! trace_dbg { - ($msg:expr $(,$val:expr)*) => { - if log_enabled!(log::Level::Trace) { - #[allow(unused_mut)] - let mut buf = format!("{}", &$msg); - $( write!(&mut buf, " {}={:?}", stringify!($val), &$val).unwrap(); )* - trace!("{}", buf); - } - } - -} - #[macro_export] macro_rules! ensure_eq { ($v1:expr, $v2:expr) => { diff --git a/support/Cargo.toml b/support/Cargo.toml index 16b036ce..70e7610e 100644 --- a/support/Cargo.toml +++ b/support/Cargo.toml @@ -33,14 +33,22 @@ chrono-tz="0.6" console="0.15" derive-into-owned="0.2" fehler="1" +fs2="0.4" +lazy_static="1" log="0.4" nix="0.23" num-derive="0.3" parking_lot="0.12" +paste="1" +pwd="1" +rand="0.8" rmp="0.8" rmp-serde="1" +toml="0.5" unicode-width="0.1" +flexi_logger = { version="0.22" , features=["specfile" ] } + # Repeated in other Cargo.toml's because importing does not work properly num-traits="0.2" serde_with="1" diff --git a/src/authproofs.rs b/support/authproofs.rs similarity index 100% rename from src/authproofs.rs rename to support/authproofs.rs diff --git a/src/config.rs b/support/config.rs similarity index 94% rename from src/config.rs rename to support/config.rs index 9d24e754..178405c7 100644 --- a/src/config.rs +++ b/support/config.rs @@ -38,7 +38,7 @@ pub struct ServerConfigSpec { pub wasm_dir: Option, pub log: Option, pub bundled_sources: Option, - pub shapelibs: Option>, + pub shapelibs: Option>, pub specs_dir: Option, pub sendmail: Option, /// for auth keys, split on spaces @@ -54,6 +54,20 @@ pub struct ServerConfigSpec { pub check_bundled_sources: Option, } +#[derive(Deserialize,Debug,Clone)] +#[serde(untagged)] +pub enum ShapelibConfig1 { + PathGlob(String), + Explicit(ShapelibExplicit1), +} + +#[derive(Deserialize,Debug,Clone)] +pub struct ShapelibExplicit1 { + pub name: String, + pub catalogue: String, + pub dirname: String, +} + #[derive(Debug,Clone)] pub struct WholeServerConfig { server: Arc, @@ -74,7 +88,7 @@ pub struct ServerConfig { pub libexec_dir: String, pub usvg_bin: String, pub bundled_sources: String, - pub shapelibs: Vec, + pub shapelibs: Vec, pub specs_dir: String, pub sendmail: String, pub ssh_proxy_bin: String, @@ -213,7 +227,7 @@ impl ServerConfigSpec { let shapelibs = shapelibs.unwrap_or_else(||{ let glob = defpath(None, DEFAULT_LIBRARY_GLOB); - vec![ shapelib::Config1::PathGlob(glob) ] + vec![ ShapelibConfig1::PathGlob(glob) ] }); let sendmail = prctx.resolve(&sendmail.unwrap_or_else( @@ -318,15 +332,21 @@ impl ServerConfigSpec { } } +lazy_static! { + static ref SAVE_AREA_LOCK: Mutex> = default(); + + static ref CONFIG: RwLock = default(); +} + pub fn config() -> Arc { - GLOBAL.config.read().server.clone() + CONFIG.read().server.clone() } pub fn log_config() -> LogSpecification { - GLOBAL.config.read().log.clone() + CONFIG.read().log.clone() } fn set_config(whole: WholeServerConfig) { - *GLOBAL.config.write() = whole; + *CONFIG.write() = whole; } impl ServerConfig { @@ -346,7 +366,7 @@ impl ServerConfig { #[throws(AE)] pub fn lock_save_area(&self) { - let mut st = GLOBAL.save_area_lock.lock(); + let mut st = SAVE_AREA_LOCK.lock(); let st = &mut *st; if st.is_none() { let lockfile = format!("{}/lock", config().save_dir); @@ -359,7 +379,7 @@ impl ServerConfig { } pub fn save_dir(&self) -> &String { - let st = GLOBAL.save_area_lock.lock(); + let st = SAVE_AREA_LOCK.lock(); let mut _f: &File = st.as_ref().unwrap(); &self.save_dir } diff --git a/support/crates.rs b/support/crates.rs index 46f0e18c..fc964f5f 100644 --- a/support/crates.rs +++ b/support/crates.rs @@ -9,8 +9,14 @@ pub use otter_base; pub use anyhow; pub use chrono; pub use chrono_tz; +pub use flexi_logger; +pub use fs2; +pub use lazy_static; pub use log; pub use nix; pub use parking_lot; +pub use pwd; +pub use rand; pub use rmp_serde; +pub use toml; pub use unicode_width; diff --git a/src/fake-rng.rs b/support/fake-rng.rs similarity index 90% rename from src/fake-rng.rs rename to support/fake-rng.rs index 6522b3c7..c157fd86 100644 --- a/src/fake-rng.rs +++ b/support/fake-rng.rs @@ -11,6 +11,10 @@ use rand::distributions::uniform::SampleUniform; #[serde(transparent)] pub struct FakeRngSpec(Option>); +#[derive(Serialize,Deserialize,Error,Debug,Clone)] +#[error("RNG is real")] +pub struct RngIsReal; + impl FakeRngSpec { pub fn make_game_rng(self) -> RngWrap { RngWrap( match self.0 { None => None, @@ -35,9 +39,9 @@ struct FakeRng { impl RngWrap { pub fn is_fake(&self) -> bool { self.0.is_some() } - #[throws(MgmtError)] + #[throws(RngIsReal)] pub fn set_fake(&self, v: Vec, _: AuthorisationSuperuser) { - let mut fake = self.0.as_ref().ok_or(ME::RngIsReal)?.lock(); + let mut fake = self.0.as_ref().ok_or(RngIsReal)?.lock(); fake.i = 0; fake.ents = v; } diff --git a/src/fake-time.rs b/support/fake-time.rs similarity index 91% rename from src/fake-time.rs rename to support/fake-time.rs index 0ac9b770..c9089731 100644 --- a/src/fake-time.rs +++ b/support/fake-time.rs @@ -9,6 +9,10 @@ use parking_lot::Mutex; type Millis = u32; type Micros = u64; +#[derive(Serialize,Deserialize,Error,Debug,Clone)] +#[error("Time is real")] +pub struct TimeIsReal; + #[derive(Deserialize,Debug,Clone,Default)] #[serde(transparent)] pub struct FakeTimeConfig(pub Option); @@ -81,9 +85,9 @@ impl GlobalClock { fake.start + Duration::from_micros(fake.current) } - #[throws(MgmtError)] + #[throws(TimeIsReal)] pub fn set_fake(&self, fspec: FakeTimeSpec, _: AuthorisationSuperuser) { - let mut guard = self.fakeable.as_ref().ok_or(ME::TimeIsReal)?.lock(); + let mut guard = self.fakeable.as_ref().ok_or(TimeIsReal)?.lock(); *guard = FakeClock::from_spec(fspec) } diff --git a/support/imports.rs b/support/imports.rs index c2c7c11a..17df3a63 100644 --- a/support/imports.rs +++ b/support/imports.rs @@ -16,6 +16,8 @@ pub use std::fs::File; pub use std::io; pub use std::io::ErrorKind; pub use std::io::{BufRead, BufReader, BufWriter, Read, Write}; +pub use std::marker::PhantomData; +pub use std::net::{IpAddr, SocketAddr, ToSocketAddrs, Ipv6Addr, Ipv4Addr}; pub use std::os::linux::fs::MetadataExt as _; // todo why linux for st_mode?? pub use std::os::unix; pub use std::os::unix::ffi::OsStrExt; @@ -25,16 +27,26 @@ pub use std::os::unix::net::UnixStream; pub use std::os::unix::process::{CommandExt, ExitStatusExt}; pub use std::process::{exit, Child, Command, Stdio}; pub use std::sync::Arc; +pub use std::time::{self, Duration, Instant}; pub use anyhow::{anyhow, ensure, Context}; pub use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; pub use derive_into_owned::IntoOwned; +pub use flexi_logger::LogSpecification; +pub use fs2::FileExt; +pub use lazy_static::lazy_static; pub use log::{debug, error, info, trace, warn}; +pub use log::{log, log_enabled}; pub use nix::unistd::{self, Uid}; pub use nix::sys::time::TimeSpec; pub use nix::time::clock_gettime; pub use num_derive::{ToPrimitive, FromPrimitive}; pub use num_traits::{Bounded, FromPrimitive, ToPrimitive}; +pub use paste::paste; +pub use rand::distributions::Alphanumeric; +pub use rand::thread_rng; +pub use rand::Rng; +pub use rand::prelude::SliceRandom; pub use serde::ser::SerializeTuple; pub use serde::{de::DeserializeOwned, Deserialize, Serialize}; pub use serde::de::Error as _; @@ -53,17 +65,28 @@ pub use parking_lot::{Mutex, MutexGuard}; //pub use crate::debugmutex::{Mutex, MutexGuard}; pub use crate::matches_doesnot; +pub use crate::trace_dbg; +pub use crate::authproofs::{self, Authorisation, Unauthorised}; +pub use crate::authproofs::AuthorisationSuperuser; pub use crate::childio; +pub use crate::config::*; pub use crate::debugmutex::DebugIdentify; +pub use crate::fake_rng::*; +pub use crate::fake_time::*; pub use crate::packetframe::{FrameReader, FrameWriter, ReadFrame, WriteFrame}; pub use crate::packetframe::{ReadExt, ResponseWriter}; pub use crate::packetframe::{PacketFrameReadError, PacketFrameWriteError}; pub use crate::progress::{self, ProgressInfo, OriginatorExt as _}; pub use crate::support::*; pub use crate::termprogress; +pub use crate::toml_de; pub use crate::tz::*; +pub type StartupError = anyhow::Error; + +pub const MS: time::Duration = time::Duration::from_millis(1); + // ---------- type abbreviations ---------- pub type AE = anyhow::Error; diff --git a/support/lib.rs b/support/lib.rs index 0307bc49..17e2627b 100644 --- a/support/lib.rs +++ b/support/lib.rs @@ -6,10 +6,16 @@ pub mod crates; pub mod imports; pub mod prelude; +pub mod authproofs; pub mod childio; +pub mod config; pub mod debugmutex; pub mod packetframe; pub mod progress; pub mod support; pub mod termprogress; pub mod tz; + +#[path = "fake-rng.rs"] pub mod fake_rng; +#[path = "fake-time.rs"] pub mod fake_time; +#[path = "toml-de.rs"] pub mod toml_de; diff --git a/support/support.rs b/support/support.rs index c5aa5003..5f174bbb 100644 --- a/support/support.rs +++ b/support/support.rs @@ -4,6 +4,94 @@ use crate::prelude::*; +//========== miscellany ========== +// (roughly in order of implementation length) + +//---------- IpAddress ---------- + +pub trait IpAddress: Debug { + fn with_port(&self, port: u16) -> SocketAddr; +} + +impl IpAddress for A where A: Into + Debug + Clone { + fn with_port(&self, port: u16) -> SocketAddr { + match (self.clone().into(), port) + .to_socket_addrs() + .map(|i| i.at_most_one()) { + Ok(Ok(Some(addr))) => addr, + x => panic!("{:?},{} gave {:?}", self, port, x), + } + } +} + +//========== toml ==================== + +#[derive(Debug,Copy,Clone,Eq,PartialEq,Ord,PartialOrd)] +pub struct TomlQuote<'s>(pub &'s str); + +// We reimplement this because the toml crate doesn't expose it, and +// looking at the github issues etc. for that crate isn't encuraging. +impl<'s> Display for TomlQuote<'s> { + #[throws(fmt::Error)] + fn fmt(&self, f: &mut fmt::Formatter) { + for c in self.0.chars() { + match c { + '"' | '\\'=> write!(f, "\\{}", c)?, + c if (c < ' ' && c != '\t') || c == '\x7f' => { + write!(f, r#"\u{:04x}"#, c as u32).unwrap(); + continue; + } + c => write!(f, "{}", c)?, + } + } + } +} + +#[test] +fn toml_quote_string_test(){ + assert_eq!(TomlQuote(r#"w \ " ƒ."#).to_string(), + r#"w \\ \" \u0007\u007fƒ."#); +} + +pub fn toml_merge<'u, + S: 'u + AsRef, + KV: IntoIterator + >( + table: &mut toml::value::Table, + updates: KV, +) { + use toml::value::{Table, Value}; + type TME<'e> = toml::map::Entry<'e>; + + let mut kv = updates.into_iter().map(|(k, v)| (k.as_ref(), v)); + inner(table, &mut kv); + + fn inner<'u>( + table: &mut Table, + updates: &'u mut dyn Iterator + ) { + for (k, v) in updates { + let e = table.entry(k); + match e { + TME::Vacant(ve) => { + ve.insert(v.clone()); + } + TME::Occupied(mut oe) => match (oe.get_mut(), v) { + (Value::Table(old), Value::Table(new)) => { + toml_merge(old, new); + } + (Value::Array(old), Value::Array(new)) => { + old.extend(new.iter().cloned()); + } + (old, new) => { + *old = new.clone(); + } + } + } + } + } +} + //========== Timestamp ========== #[derive(Copy,Clone,Debug,Serialize,Deserialize,Eq,Ord,PartialEq,PartialOrd)] @@ -26,6 +114,26 @@ impl Timestamp { } } +//========== miscellaneous macros ========== + +paste!{ + #[cfg(debug_assertions)] + pub fn []() -> T { panic!("todo item triggered") } +} + +#[macro_export] +macro_rules! trace_dbg { + ($msg:expr $(,$val:expr)*) => { + if log_enabled!(log::Level::Trace) { + #[allow(unused_mut)] + let mut buf = format!("{}", &$msg); + $( write!(&mut buf, " {}={:?}", stringify!($val), &$val).unwrap(); )* + trace!("{}", buf); + } + } + +} + //========== matches_doesnot ========== #[macro_export] // <- otherwise bogus warning `unused_macros` diff --git a/src/toml-de.rs b/support/toml-de.rs similarity index 99% rename from src/toml-de.rs rename to support/toml-de.rs index e48a57a9..c915dc8b 100644 --- a/src/toml-de.rs +++ b/support/toml-de.rs @@ -3,7 +3,6 @@ // There is NO WARRANTY. use crate::crates::*; -use otter_support::crates::*; use otter_base::crates::*; use std::fmt::{Debug, Display};