From f49c8155d28c1b9b2f85dc02ad6e7a779ed4a3c3 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 15 May 2021 19:11:22 +0100 Subject: [PATCH] shapelib: Provide per-game registry iterator Currently this is juut the global registry. Signed-off-by: Ian Jackson --- daemon/cmdlistener.rs | 5 +-- src/bin/otterlib.rs | 6 ++-- src/shapelib.rs | 82 +++++++++++++++++++++++++++++++------------ 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/daemon/cmdlistener.rs b/daemon/cmdlistener.rs index a33a15eb..825f2e35 100644 --- a/daemon/cmdlistener.rs +++ b/daemon/cmdlistener.rs @@ -354,8 +354,9 @@ fn execute_and_respond(cs: &mut CommandStreamData, cmd: MgmtCommand, let (results, _auth) = access_bundles( cs,&ag,&gref, &[TP::UploadBundles], - &mut |mut _ig, _| { - let libs = shapelib::lib_name_lookup(&spec.lib)?; + &mut |ig, _| { + let regs = ig.all_shapelibs(); + let libs = regs.lib_name_lookup(&spec.lib)?; let mut results: Vec = default(); for lib in &*libs { results.extend(lib.list_glob(&spec.item)?); diff --git a/src/bin/otterlib.rs b/src/bin/otterlib.rs index 0c97a548..a2b026c9 100644 --- a/src/bin/otterlib.rs +++ b/src/bin/otterlib.rs @@ -233,8 +233,10 @@ fn main() { load_global_libs(&vec![tlibs.clone()])?; } let mut items: Vec = default(); - for lib in lib_name_list() { - for contents in &*lib_name_lookup(&lib)? { + let ig_dummy = Instance::dummy(); + let all_registries = ig_dummy.all_shapelibs(); + for lib in lib_name_list(&ig_dummy) { + for contents in all_registries.lib_name_lookup(&lib)? { for pat in opts.items.split(SPLIT) { for item in contents.list_glob(pat)? { items.push((lib.clone(), item)) diff --git a/src/shapelib.rs b/src/shapelib.rs index 9834e875..11205dee 100644 --- a/src/shapelib.rs +++ b/src/shapelib.rs @@ -6,7 +6,7 @@ pub use crate::prelude::*; pub use crate::shapelib_toml::*; use parking_lot::{const_rwlock, RwLock}; -use parking_lot::{MappedRwLockReadGuard, RwLockReadGuard}; +use parking_lot::RwLockReadGuard; // Naming convention: // *Data, *List from toml etc. (processed if need be) @@ -15,6 +15,8 @@ use parking_lot::{MappedRwLockReadGuard, RwLockReadGuard}; // Item } once loaded and part of a game, // Outline } no Arc's as we serialise/deserialize during save/load +static GLOBAL_SHAPELIBS: RwLock> = const_rwlock(None); + #[derive(Default)] pub struct Registry { libs: HashMap>, @@ -345,27 +347,60 @@ impl OccultedPieceTrait for Item { } } -static SHAPELIBS: RwLock> = const_rwlock(None); +pub struct AllRegistries<'ig> { + global: RwLockReadGuard<'static, Option>, + #[allow(dead_code)] ig: &'ig Instance, +} +pub struct AllRegistriesIterator<'i> { + regs: &'i AllRegistries<'i>, + count: u8, +} + +impl<'i> Iterator for AllRegistriesIterator<'i> { + type Item = &'i Registry; + fn next(&mut self) -> Option<&'i Registry> { + loop { + let r = match self.count { + 0 => self.regs.global.as_ref(), + _ => return None, + }; + self.count += 1; + if r.is_some() { return r } + } + } +} + +impl Instance { + pub fn all_shapelibs(&self) -> AllRegistries<'_> { + AllRegistries { + global: GLOBAL_SHAPELIBS.read(), + ig: self, + } + } +} +impl<'ig> AllRegistries<'ig> { + pub fn iter(&'ig self) -> AllRegistriesIterator<'ig> { + AllRegistriesIterator { + regs: self, + count: 0, + } + } +} -pub fn lib_name_list() -> Vec { - let reg = SHAPELIBS.read(); - reg.as_ref().map( - |reg| reg.libs.keys().cloned().collect() - ).unwrap_or_default() +pub fn lib_name_list(ig: &Instance) -> Vec { + // xxx put bundle id in here or something show it shows up in libs list + ig.all_shapelibs().iter().map( + |reg| reg.libs.keys().cloned() + ).flatten().collect() } -#[throws(SpecError)] -pub fn lib_name_lookup(libname: &str) - -> MappedRwLockReadGuard<'static, [Contents]> { - let reg = SHAPELIBS.read(); - RwLockReadGuard::try_map( reg, |reg: &Option| -> Option<_> { - (|| Some({ - reg.as_ref()?.libs.get(libname)? - .as_slice() - }))() - }) - .map_err(|_| SpE::LibraryNotFound) - ? +impl<'ig> AllRegistries<'ig> { + pub fn lib_name_lookup(&self, libname: &str) -> Result<&[Contents], SpE> { + for reg in self.iter() { + if let Some(r) = reg.libs.get(libname) { return Ok(r) } + } + return Err(SpE::LibraryNotFound); + } } pub type ItemSpecLoaded = (Box, PieceSpecLoadedOccultable); @@ -383,7 +418,8 @@ impl From for PieceSpecLoaded { impl ItemSpec { #[throws(SpecError)] pub fn find_load(&self, ig: &Instance, depth: SpecDepth) -> ItemSpecLoaded { - let libs = lib_name_lookup(&self.lib)?; + let regs = ig.all_shapelibs(); + let libs = regs.lib_name_lookup(&self.lib)?; let (lib, (item, idata)) = libs.iter().rev().find_map( |lib| Some((lib, lib.items.get_key_value(self.item.as_str())?)) ) @@ -767,7 +803,7 @@ pub struct Explicit1 { } #[throws(LibraryLoadError)] -pub fn load_1_library(l: &Explicit1) { +pub fn load_1_global_library(l: &Explicit1) { let toml_path = &l.catalogue; let catalogue_data = { let ioe = |io| LLE::FileError(toml_path.to_string(), io); @@ -783,7 +819,7 @@ pub fn load_1_library(l: &Explicit1) { let data = load_catalogue(&l.name, &mut src)?; let count = data.items.len(); - SHAPELIBS.write() + GLOBAL_SHAPELIBS.write() .get_or_insert_with(default) .libs .entry(l.name.clone()).or_default() @@ -846,7 +882,7 @@ pub fn load_global_libs(libs: &Vec) { let libs = l.resolve()?; let n = libs.len(); for e in libs { - load_1_library(&e)?; + load_1_global_library(&e)?; } info!("loaded {} shape libraries from {:?}", n, &l); -- 2.30.2