chiark / gitweb /
make shape libraries global
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 16 Sep 2020 23:37:48 +0000 (00:37 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 16 Sep 2020 23:37:48 +0000 (00:37 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/bin/otterlib.rs
src/global.rs
src/imports.rs
src/shapelib.rs

index 57c5d9e1569ea8b5abd4df00b0540ae2dcee1178..84b4dfcc667d7ddbdcd2cb0ba12ac09fd9787744 100644 (file)
@@ -3,6 +3,5 @@ pub use otter::imports::*;
 #[throws(anyhow::Error)]
 fn main(){
   let f = env::args().nth(1).unwrap();
-  let l = shapelib::LibraryContents::load(f)?;
-  dbg!(l);
+  shapelib::load(f.clone(),f)?;
 }
index c9492a11a6567daed6164933bdc8abd53c4999c0..b5282277cdf8a1308653783ad94aed0e588d68a8 100644 (file)
@@ -151,11 +151,11 @@ pub struct InstanceAccess<'i, Id> {
 // ========== internal data structures ==========
 
 lazy_static! {
-  static ref GLOBAL : Global = Default::default();
+  pub static ref GLOBAL : Global = Default::default();
 }
 
 #[derive(Default)]
-struct Global {
+pub struct Global {
   // lock hierarchy: InstanceContainer < games < {players, clients}
   // (in order of criticality (perf impact); outermost first, innermost last)
   games   : RwLock<HashMap<Arc<InstanceName>,InstanceRef>>,
@@ -164,6 +164,7 @@ struct Global {
   config  : RwLock<Arc<ServerConfig>>,
   dirty   : Mutex<VecDeque<InstanceRef>>,
   save_area_lock : Mutex<Option<File>>,
+  pub shapelibs : RwLock<HashMap<String,LibraryContents>>,
 }
 
 #[derive(Debug)]
index 730becdef9b950b33daa4745fb5b021cb21333fd..bdbdb1fe0c0be509e6f9f612812b4e45c36ffe5d 100644 (file)
@@ -101,7 +101,7 @@ pub use crate::api::{Lens,TransparentLens};
 pub use crate::utils::*;
 pub use crate::spec::*;
 pub use crate::debugreader::DebugReader;
-pub use crate::shapelib;
+pub use crate::shapelib::{self,LibraryContents};
 
 pub use nix::unistd::Uid;
 
index a55f25b2a676486a08f90fd0394912708a5f3af6..edc0cf931e71c64dbd012bf7febe71e73c046391 100644 (file)
@@ -6,48 +6,49 @@ pub use crate::imports::*;
 
 #[derive(Debug)]
 pub struct LibraryContents {
-  pub dirname: String,
-  pub pieces: HashMap<String /* usvg path */, LibraryPieceInfo>,
+  dirname: String,
+  pieces: HashMap<String /* usvg path */, LibraryPieceInfo>,
 }
 
 #[derive(Debug,Clone)]
 pub struct LibraryPieceInfo {
-  pub desc: Html,
-  pub info: Arc<LibraryGroupInfo>,
+  desc: Html,
+  info: Arc<LibraryGroupInfo>,
 }
 
 #[derive(Debug,Deserialize)]
 pub struct LibraryGroupInfo {
-  pub outline: Box<dyn OutlineSpec>,
-  pub size: Vec<Coord>,
+  outline: Box<dyn OutlineSpec>,
+  size: Vec<Coord>,
   #[serde(default="num_traits::identities::One::one")]
-  pub scale: f64,
+  scale: f64,
   #[serde(default)]
-  pub centre: Option<Vec<f64>>,
-  pub category: String,
+  centre: Option<Vec<f64>>,
+  category: String,
 }
 
 #[derive(Debug,Deserialize)]
 struct LibraryGroupSpec {
-  #[serde(default)] pub stem_prefix: String,
-  #[serde(default)] pub stem_suffix: String,
-  #[serde(default)] pub flip: bool,
-  pub files: FileList,
-  #[serde(flatten)] pub info: Arc<LibraryGroupInfo>,
+  #[serde(default)] stem_prefix: String,
+  #[serde(default)] stem_suffix: String,
+  #[serde(default)] flip: bool,
+  files: FileList,
+  #[serde(flatten)] info: Arc<LibraryGroupInfo>,
 }
 
 #[derive(Deserialize,Debug)]
 #[serde(try_from="String")]
-pub struct FileList (Vec<FileEntry>);
+struct FileList (Vec<FileEntry>);
 
 #[derive(Deserialize,Debug)]
-pub struct FileEntry {
-  pub filespec: String,
-  pub desc: Html,
+struct FileEntry {
+  filespec: String,
+  desc: Html,
 }
 
 #[typetag::deserialize]
-pub trait OutlineSpec : Debug + Sync + Send {
+trait OutlineSpec : Debug + Sync + Send {
+  fn check(&self, lgi: &LibraryGroupInfo) -> Result<(),LibraryLoadError>;
 }
 
 #[derive(Error,Debug)]
@@ -61,6 +62,8 @@ pub enum LibraryLoadError{
   #[error("{:?}",&self)]
   ExpectedString(String),
   #[error("{:?}",&self)]
+  WrongNumberOfSizeDimensions { got: usize, expected: usize },
+  #[error("{:?}",&self)]
   InheritMissingParent(String,String),
   #[error("{:?}",&self)]
   InheritDepthLimitExceeded(String),
@@ -103,53 +106,74 @@ fn resolve_inherit<'r>(depth: u8, groups: &toml::value::Table,
   Cow::Owned(build)
 }
 
-impl LibraryContents {
-  #[throws(LibraryLoadError)]
-  pub fn load(dirname: String) -> LibraryContents {
-    let toml_path = format!("{}.toml", &dirname);
-    let f = File::open(toml_path)?;
-    let mut f = BufReader::new(f);
-    let mut s = String::new();
-    f.read_to_string(&mut s).unwrap();
-    let toplevel : toml::Value = s.parse()?;
-    let mut l = LibraryContents {
-      pieces: HashMap::new(),
-      dirname,
-    };
-    let empty_table = toml::value::Value::Table(Default::default());
-    let groups =
-      toplevel
-      .as_table().ok_or_else(|| LLE::ExpectedTable(format!("toplevel")))?
-      .get("group").unwrap_or(&empty_table)
-      .as_table().ok_or_else(|| LLE::ExpectedTable(format!("group")))?;
-    for (group_name, group_value) in groups {
-      let resolved = resolve_inherit(INHERIT_DEPTH_LIMIT,
-                                     &groups, group_name, group_value)?;
-      let resolved = TV::Table(resolved.into_owned());
-      let spec : LibraryGroupSpec = resolved.try_into()?;
-      for fe in spec.files.0 {
-        let usvgfile = format!("{}{}{}.usvg", spec.stem_prefix,
-                               fe.filespec, spec.stem_suffix);
-        let lp = LibraryPieceInfo { info: spec.info.clone(), desc: fe.desc };
-        type H<'e,X,Y> = hash_map::Entry<'e,X,Y>;
-        match l.pieces.entry(usvgfile) {
-          H::Occupied(oe) => throw!(LLE::DuplicateFile(
-            oe.key().clone(),
-            oe.get().clone(),
-            lp,
-          )),
-          H::Vacant(ve) => ve.insert(lp),
-        };
-      }
+#[throws(LibraryLoadError)]
+fn load_catalogue(dirname: String) -> LibraryContents {
+  let toml_path = format!("{}.toml", &dirname);
+  let f = File::open(toml_path)?;
+  let mut f = BufReader::new(f);
+  let mut s = String::new();
+  f.read_to_string(&mut s).unwrap();
+  let toplevel : toml::Value = s.parse()?;
+  let mut l = LibraryContents {
+    pieces: HashMap::new(),
+    dirname,
+  };
+  let empty_table = toml::value::Value::Table(Default::default());
+  let groups =
+    toplevel
+    .as_table().ok_or_else(|| LLE::ExpectedTable(format!("toplevel")))?
+    .get("group").unwrap_or(&empty_table)
+    .as_table().ok_or_else(|| LLE::ExpectedTable(format!("group")))?;
+  for (group_name, group_value) in groups {
+    let resolved = resolve_inherit(INHERIT_DEPTH_LIMIT,
+                                   &groups, group_name, group_value)?;
+    let resolved = TV::Table(resolved.into_owned());
+    let spec : LibraryGroupSpec = resolved.try_into()?;
+    for fe in spec.files.0 {
+      let usvgfile = format!("{}{}{}.usvg", spec.stem_prefix,
+                             fe.filespec, spec.stem_suffix);
+      let lp = LibraryPieceInfo { info: spec.info.clone(), desc: fe.desc };
+      type H<'e,X,Y> = hash_map::Entry<'e,X,Y>;
+      match l.pieces.entry(usvgfile) {
+        H::Occupied(oe) => throw!(LLE::DuplicateFile(
+          oe.key().clone(),
+          oe.get().clone(),
+          lp,
+        )),
+        H::Vacant(ve) => ve.insert(lp),
+      };
     }
-    l
   }
+  l
+}
+
+#[throws(LibraryLoadError)]
+pub fn load(libname: String, dirname: String) {
+  let data = load_catalogue(dirname.clone())?;
+  dbg!(&data);
+  GLOBAL.shapelibs.write().unwrap().insert(libname.clone(), data);
+  info!("loaded library {:?} from {:?}", libname, dirname);
 }
 
 #[derive(Deserialize,Debug)]
 struct Circle { }
 #[typetag::deserialize]
-impl OutlineSpec for Circle { }
+impl OutlineSpec for Circle {
+  #[throws(LibraryLoadError)]
+  fn check(&self, lgi: &LibraryGroupInfo) {
+    Self::get_size(lgi)?;
+  }
+}
+impl Circle {
+  #[throws(LibraryLoadError)]
+  fn get_size(lgi: &LibraryGroupInfo) -> Coord {
+    match lgi.size.as_slice() {
+      &[c] => c,
+      size => throw!(LLE::WrongNumberOfSizeDimensions
+                     { got: size.len(), expected : 1 }),
+    }
+  }
+}
 
 impl TryFrom<String> for FileList {
   type Error = LLE;