chiark / gitweb /
shapelib magic: implement
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 13 May 2022 23:44:19 +0000 (00:44 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 14 May 2022 15:00:17 +0000 (16:00 +0100)
This still has some bugs.  We mustn't invoke it just yet in our
library bundles, because it will fail.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/shapelib-toml.rs
src/shapelib.rs

index f5dfc2d2803e0a2dcfcb7a86ec4016c42831e4b3..367ac6289574ae2b30a60af03f0584b9f34fa243 100644 (file)
@@ -33,6 +33,14 @@ pub struct GroupDetails {
   pub desc_template: Option<String>,
   pub occulted: Option<OccultationMethod>,
   pub outline: OutlineDetails,
+  #[serde(default)] pub magic: Option<MagicDetails>,
+}
+
+#[derive(Debug,Deserialize)]
+pub struct MagicDetails {
+  #[serde(default)] pub item_prefix: String,
+  #[serde(default)] pub item_suffix: String,
+  pub template: String,
 }
 
 #[derive(Debug,Deserialize,Copy,Clone)]
index d985a05da43938da1fc13d6b404d3fa3d401ef50..8ff12706edd4125cd7b482d12ecd820ab1d3a08f 100644 (file)
@@ -51,7 +51,6 @@ struct ItemDetails {
 #[derive(Debug,Clone)]
 enum CatalogueEntry {
   Item(ItemData),
-  #[allow(dead_code)] // XXX
   Magic { group: Arc<GroupData>, spec: Arc<dyn PieceSpec> },
 }
 use CatalogueEntry as CatEnt;
@@ -135,6 +134,9 @@ pub enum LibraryLoadError {
   #[error("bad item name (invalid characters) in {0:?}")] BadItemName(String),
   #[error("{0}")] MaterialsFormatVersionError(#[from] MFVE),
 
+  #[error("could not parse template-expaneded TOML: {error} (in {toml:?}")]
+  TemplatedTomlError { toml: String, error: toml_de::Error },
+
   #[error("group {group}: {error}")]
   InGroup { group: String, error: Box<LLE> },
 
@@ -1228,6 +1230,36 @@ fn process_files_entry(
       d: Arc::new(ItemDetails { desc }),
     };
     l.add_item(src, src_name, &item_name, CatEnt::Item(idata))?;
+
+    if let Some(magic) = &group.d.magic { 
+      // Ideally the toml crate would have had let us build an inline
+      // table.  But in fact it won't even toml-escape the strings without
+      // a fuss, so we bodge it with strings:
+      let image_table = format!(
+        r#"{{ type="Lib", lib="{}", item="{}" }}"#,
+        TomlQuote(&l.libname), TomlQuote(item_name.as_str())
+      );
+
+      let item_name = subst_item_name(&format_item_name(
+        &magic.item_prefix, &fe, &magic.item_suffix)?)?;
+
+      let spec = regex!(r#"(?m)(^[\sA-Za-z0-9._-]+=\s*)!\s*$"#)
+        .replace_all(&magic.template, |caps: &regex::Captures| {
+          format!("{}{}", caps.get(1).unwrap().as_str(), &image_table)
+        });
+
+      let spec: Box<dyn PieceSpec> = toml_de::from_str(&spec)
+        .map_err(|error| LLE::TemplatedTomlError {
+          toml: spec.into_owned(),
+          error,
+        })?;
+
+      l.add_item(src, src_name, &item_name, CatEnt::Magic {
+        group: group.clone(),
+        spec: spec.into(),
+      })?;
+    }
+
     Ok::<_,LLE>(())
   };