chiark / gitweb /
bundles: Scan shape libraries
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 12 May 2021 18:04:44 +0000 (19:04 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 12 May 2021 18:04:44 +0000 (19:04 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/bundles.rs
src/prelude.rs
src/shapelib.rs

index 817b440fca803eb96e0f4950dc97c8aa79659b0d..231ae5ae02a4c6dff8afbe0c140e45d14396eedb 100644 (file)
@@ -83,6 +83,15 @@ struct Parsed {
 #[derive(Debug)]
 struct ForProcess {
   za: IndexedZip,
+  newlibs: Vec<ForProcessLib>,
+}
+
+#[derive(Debug)]
+struct ForProcessLib {
+  contents: shapelib::Contents,
+  dir_inzip: String,
+  svg_dir: String,
+  need_svgs: Vec<GoodItemName>,
 }
 
 const BUNDLES_MAX: Index = Index(64);
@@ -133,6 +142,12 @@ impl From<LoadError> for MgmtError {
   } }
 }
 
+impl LoadError {
+  fn badlib(libname: &str, e: &dyn Display) -> LoadError {
+    LE::BadBundle(format!("bad library: {}: {}", libname, e))
+  }
+}
+
 //---------- pathname handling (including Id leafname) ----------
 
 pub fn b_dir(instance: &InstanceName) -> String {
@@ -421,7 +436,7 @@ impl BundleParseErrorHandling for BundleParseUpload {
 }
 
 #[throws(EH::Err)]
-fn parse_bundle<EH>(id: Id, _instance_name: &InstanceName, file: File, eh: EH,
+fn parse_bundle<EH>(id: Id, instance: &InstanceName, file: File, eh: EH,
                     mut for_progress: &mut dyn progress::Reporter)
                     -> (ForProcess, Parsed)
   where EH: BundleParseErrorHandling,
@@ -434,11 +449,13 @@ fn parse_bundle<EH>(id: Id, _instance_name: &InstanceName, file: File, eh: EH,
   #[derive(Copy,Clone,Debug,EnumCount,EnumMessage,ToPrimitive)]
   enum Phase {
     #[strum(message="scan")] Scan,
+    #[strum(message="parse shape catalogues")] ParseLibs,
   }
 
   #[derive(Copy,Clone,Debug,EnumCount,EnumMessage,ToPrimitive)]
   enum ToScan {
-    #[strum(message="metadata")] Meta,
+    #[strum(message="metadata")]   Meta,
+    #[strum(message="shape libs")] Libs,
   }
   for_progress.phase_item(Phase::Scan, ToScan::Meta);
   
@@ -460,19 +477,92 @@ fn parse_bundle<EH>(id: Id, _instance_name: &InstanceName, file: File, eh: EH,
     }
   })?;
 
+  for_progress.phase_item(Phase::Scan, ToScan::Libs);
+
+  #[derive(Debug)]
+  struct LibScanned {
+    libname: String,
+    dir_inzip: String,
+    inzip: ZipIndex,
+  }
+
+  let mut libs = Vec::new();
+  for (name,i) in &za {
+    eh.besteffort(|| Ok::<_,LE>(if_chain!{
+      if let Ok([dir, file]) = name.as_ref().split('/')
+        .collect::<ArrayVec<[&str;2]>>()
+        .into_inner();
+      if unicase::eq(dir, "library");
+      if let Some((ext, base)) = file.rsplit_once('.');
+      if unicase::eq(ext, "toml");
+      then {
+        libs.push(LibScanned {
+          dir_inzip: format!("{}/{}", &dir, &base),
+          libname: base.to_lowercase(),
+          inzip: i,
+        });
+      }
+    }), ||())?;
+  }
+
+  for_progress.phase(Phase::ParseLibs, libs.len());
+
+  let mut newlibs = Vec::new();
+
+  #[derive(Debug,Clone)]
+  struct LibraryInBundle<'l> {
+    catalogue_data: String,
+    svg_dir: &'l String,
+    need_svgs: Vec<GoodItemName>,
+  }
+
+  impl shapelib::LibrarySource for LibraryInBundle<'_> {
+    fn catalogue_data(&self) -> &str { &self.catalogue_data }
+    fn svg_dir(&self) -> String { self.svg_dir.clone() }
+  }
+
+  for (progress_count, LibScanned { libname, dir_inzip, inzip })
+    in libs.into_iter().enumerate()
+  {
+    for_progress.item(progress_count, &libname);
+
+    eh.besteffort(|| Ok::<_,LE>({
+      let svg_dir = format!("{}/lib{}", id.path_dir(&instance), &inzip);
+
+      let mut zf = za.i(inzip)?;
+      let mut catalogue_data = String::new();
+      zf.read_to_string(&mut catalogue_data)
+        .map_err(|e| LE::badlib(&libname, &e))?;
+      let mut src = LibraryInBundle {
+        catalogue_data: catalogue_data,
+        svg_dir: &svg_dir,
+        need_svgs: Vec::new(),
+      };
+      let contents = shapelib::load_catalogue(&libname, &mut src)
+        .map_err(|e| LE::badlib(&libname, &e))?;
+      newlibs.push(ForProcessLib {
+        need_svgs: src.need_svgs,
+        contents, svg_dir, dir_inzip,
+      });
+    }), ||())?;
+  }
+
   // todo: do actual things, eg libraries and specs
 
-  (ForProcess { za }, Parsed { meta })
+  (ForProcess { za, newlibs },
+   Parsed { meta })
 }
 
 #[throws(LE)]
-fn process_bundle(ForProcess { za:_ }: ForProcess,
+fn process_bundle(ForProcess { za:_, newlibs:_ }: ForProcess,
                   id: Id, instance: &InstanceName,
                   _for_progress: &dyn progress::Reporter)
 {
   let dir = id.path_dir(instance);
   fs::create_dir(&dir)
     .with_context(|| dir.clone()).context("mkdir").map_err(IE::from)?;
+
+  // todo: do something with newlibs
 }
 
 //---------- scanning/incorporating/uploading ----------
index 8e8d3c72a6d0881f51937d44c43ab8357bdc6aa8..beb836ff5af3736128383bfc83ee5d1b3daf1a96 100644 (file)
@@ -152,7 +152,7 @@ pub use crate::pcrender::*;
 pub use crate::pieces::*;
 pub use crate::progress::{self, ProgressInfo, ReporterExt as _};
 pub use crate::shapelib;
-pub use crate::shapelib::{CircleShape, RectShape};
+pub use crate::shapelib::{CircleShape, RectShape, LibraryLoadError};
 pub use crate::slotmap_slot_idx::*;
 pub use crate::spec::*;
 pub use crate::spec::piece_specs::{FaceColourSpecs, SimpleCommon};
index 71a2e4b7dba390671b3bbeb9bf043b8f23935490..ba680caeef6f2a237542f3c3b46024005108b71d 100644 (file)
@@ -609,7 +609,7 @@ impl LibrarySource for BuiltinLibrary<'_> {
 }
 
 #[throws(LibraryLoadError)]
-fn load_catalogue(libname: &str, src: &mut dyn LibrarySource) -> Contents {
+pub fn load_catalogue(libname: &str, src: &mut dyn LibrarySource) -> Contents {
   let toplevel: toml::Value = src.catalogue_data().parse()?;
   let mut l = Contents {
     libname: libname.to_string(),