chiark / gitweb /
wip thunk
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 12 Nov 2020 00:03:36 +0000 (00:03 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 12 Nov 2020 00:03:36 +0000 (00:03 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Cargo.lock.example
Cargo.toml
src/bin/otter.rs
src/utils.rs

index 63c510920588c772b89e41951e1bb5a6c83d7471..7a7e0f68e102514da4d6ab5e5319a44d10f18a49 100644 (file)
@@ -854,6 +854,12 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 
+[[package]]
+name = "lazy-init"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "671025f3cc9b5d5188eca51493d8097e6cd1dc3828e0a59f7befbaaf56e930ab"
+
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
@@ -1110,6 +1116,7 @@ dependencies = [
  "index_vec",
  "inventory",
  "itertools",
+ "lazy-init",
  "lazy_static",
  "libc",
  "log 0.4.11",
index 04d6d50365db51a727b302c4110e091ec587ef77..edb4edc53ba00b17dc435ed111391df1c77477c1 100644 (file)
@@ -38,6 +38,7 @@ inventory = "0.1"
 itertools = "0.9"
 lazy_static = "1"
 libc = "0.2"
+lazy-init = "0.4"
 log = "0.4"
 nix = "0.18"
 num-derive = "0.3"
index b7118ae6d5018b132f9584e2ed3bd2c7f65ae7d8..5efb32088ebef0d3970d27ad82440c967e147939 100644 (file)
@@ -128,7 +128,7 @@ fn parse_args<T:Default,U>(
   mem::drop(ap);
   let completed  =
     completer(parsed).unwrap_or_else(|e:ArgumentParseError| {
-      let ap = apmaker(&mut Default::default());
+      let ap = apmaker(&mut default());
       ap.error(&us, &e.0, &mut stderr);
       exit(EXIT_USAGE);
     });
@@ -194,16 +194,13 @@ fn main() {
       })
     })?;
     let gaccount = gaccount.unwrap_or_else(|| account.clone());
-    let mut config_store : Option<Result<Arc<ServerConfig>,APE>> = None;
-    let config = ||{
-      Ok::<_,APE>(&config_store.unwrap_or_else(||{
-        ServerConfig::read(config_filename.as_ref().map(String::as_str))
-          .context("read config file")?;
-        Ok(otter::global::config())
-      })?)
-    };
+    let config = Thunk::new(||{
+      ServerConfig::read(config_filename.as_ref().map(String::as_str))
+        .context("read config file")?;
+      Ok(otter::global::config())
+    });
     let socket_path = socket_path.map(Ok::<_,APE>).unwrap_or_else(||{
-      Ok(config()?.command_socket.clone())
+      Ok(config?.command_socket.clone())
     })?;
     Ok((subcommand, subargs, MainOpts {
       account,
@@ -377,7 +374,7 @@ const PLAYER_DEFAULT_PERMS : &[TablePermission] = &[
 ];
 
 #[throws(AE)]
-fn setup_table(ma: &MainOpts, spec: &TableSpec) -> Vec<Insn> {
+fn setup_table(_ma: &MainOpts, spec: &TableSpec) -> Vec<Insn> {
   let TableSpec { players, player_perms, acl } = spec;
   let mut player_perms = player_perms.clone()
     .unwrap_or(PLAYER_DEFAULT_PERMS.iter().cloned().collect());
@@ -390,7 +387,7 @@ fn setup_table(ma: &MainOpts, spec: &TableSpec) -> Vec<Insn> {
       deny: default(),
     })
     .chain(
-      spec.acl.ents.iter().cloned()
+      acl.ents.iter().cloned()
     )
     .collect();
 
index 2132a74d55556cab9d119606bb24b1b56470c2a7..87a98572becb2f7976ba5c5c4a0cc763c45b58dc 100644 (file)
@@ -2,8 +2,10 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later
 // There is NO WARRANTY.
 
+use std::fmt::{self, Debug};
 use std::fs;
 use std::io;
+use std::ops::Deref;
 use std::os::unix::io::IntoRawFd;
 
 use fehler::{throw, throws};
@@ -52,3 +54,42 @@ impl LocalFileExt for fs::File {
     }
   }
 }
+
+// todo #[derive(Clone)]
+pub struct Thunk<U: Sync, F: Sync + FnOnce() -> U> (
+  lazy_init::LazyTransform<F, U>
+);
+
+impl<T: Sync, F: Sync + FnOnce() -> T> Debug for Thunk<T, F> where T: Debug{
+  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    match self.0.get() {
+      Some(inner) => write!(f, "Thunk({:?})", inner),
+      None        => write!(f, "Thunk(...)"),
+    }
+  }
+}
+
+impl<T: Sync, F: Sync + FnOnce() -> T> Thunk<T, F> {
+  pub fn new(f: F) -> Self {
+    Thunk(
+      lazy_init::LazyTransform::new(f)
+    )
+  }
+  pub fn force_eval(thunk: &Self) {
+    thunk.0.get_or_create(|f| f());
+  }
+  pub fn into_inner(thunk: Self) -> T {
+    Thunk::force_eval(&thunk);
+    thunk.0.into_inner().unwrap_or_else(|_|panic!())
+  }
+}
+
+impl<T: Sync, F: Sync + FnOnce() -> T> Deref for Thunk<T, F> {
+  type Target = T;
+  fn deref(&self) -> &T {
+    Thunk::force_eval(self);
+    self.0.get().unwrap()
+  }
+}
+
+// todo: DerefMut