From 5986361b30d1c4eeec3596038aab0db435b2b3d5 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 17 Sep 2020 00:37:48 +0100 Subject: [PATCH] make shape libraries global Signed-off-by: Ian Jackson --- src/bin/otterlib.rs | 3 +- src/global.rs | 5 +- src/imports.rs | 2 +- src/shapelib.rs | 142 ++++++++++++++++++++++++++------------------ 4 files changed, 88 insertions(+), 64 deletions(-) diff --git a/src/bin/otterlib.rs b/src/bin/otterlib.rs index 57c5d9e1..84b4dfcc 100644 --- a/src/bin/otterlib.rs +++ b/src/bin/otterlib.rs @@ -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)?; } diff --git a/src/global.rs b/src/global.rs index c9492a11..b5282277 100644 --- a/src/global.rs +++ b/src/global.rs @@ -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,InstanceRef>>, @@ -164,6 +164,7 @@ struct Global { config : RwLock>, dirty : Mutex>, save_area_lock : Mutex>, + pub shapelibs : RwLock>, } #[derive(Debug)] diff --git a/src/imports.rs b/src/imports.rs index 730becde..bdbdb1fe 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -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; diff --git a/src/shapelib.rs b/src/shapelib.rs index a55f25b2..edc0cf93 100644 --- a/src/shapelib.rs +++ b/src/shapelib.rs @@ -6,48 +6,49 @@ pub use crate::imports::*; #[derive(Debug)] pub struct LibraryContents { - pub dirname: String, - pub pieces: HashMap, + dirname: String, + pieces: HashMap, } #[derive(Debug,Clone)] pub struct LibraryPieceInfo { - pub desc: Html, - pub info: Arc, + desc: Html, + info: Arc, } #[derive(Debug,Deserialize)] pub struct LibraryGroupInfo { - pub outline: Box, - pub size: Vec, + outline: Box, + size: Vec, #[serde(default="num_traits::identities::One::one")] - pub scale: f64, + scale: f64, #[serde(default)] - pub centre: Option>, - pub category: String, + centre: Option>, + 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, + #[serde(default)] stem_prefix: String, + #[serde(default)] stem_suffix: String, + #[serde(default)] flip: bool, + files: FileList, + #[serde(flatten)] info: Arc, } #[derive(Deserialize,Debug)] #[serde(try_from="String")] -pub struct FileList (Vec); +struct FileList (Vec); #[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 for FileList { type Error = LLE; -- 2.30.2