pub use crate::imports::*;
-#[derive(Deserialize,Debug)]
-#[serde(transparent)]
-pub struct Library {
- pub sections: LinkedHashMap<String, Section>,
+#[derive(Debug)]
+pub struct LibraryContents {
+ pub directory: String,
+ pub pieces: HashMap<String /* usvg path */, LibraryPieceInfo>,
}
-#[derive(Deserialize,Debug)]
-pub struct Section {
+#[derive(Debug)]
+pub struct LibraryPieceInfo {
+ pub desc: Html,
+ pub info: Arc<LibraryGroupInfo>,
+}
+
+#[derive(Debug,Deserialize)]
+pub struct LibraryGroupInfo {
pub outline: Box<dyn OutlineSpec>,
pub size: Vec<Coord>,
- pub middle: Option<Vec<f64>>,
+ #[serde(default="num_traits::identities::One::one")]
+ pub scale: f64,
+ #[serde(default)]
+ pub centre: Option<Vec<f64>>,
pub category: String,
+}
+
+#[derive(Debug,Deserialize)]
+struct LibraryGroupSpec {
+ #[serde(transparent)]
+ pub info: Arc<LibraryGroupInfo>,
+ #[serde(default)]
+ pub stem_prefix: String,
+ #[serde(default)]
+ pub stem_suffix: String,
pub files: FileList,
- pub scraper: Option<toml::Value>,
}
#[derive(Deserialize,Debug)]
#[error("error reading/opening library file: {0}")]
FileError(#[from] io::Error),
#[error("{:?}",&self)]
+ ExpectedTable(String),
+ #[error("{:?}",&self)]
+ InheritMissingParentGroup(String,String),
+ #[error("{:?}",&self)]
+ InheritDepthLimitExceeded(String),
+ #[error("{:?}",&self)]
+ DuplicateFile(String,LibraryPieceInfo,LibraryPieceInfo),
+ #[error("{:?}",&self)]
FilesListLineMissingWhitespace(usize),
}
+const INHERIT_DEPTH_LIMIT : u8 = 20;
+
+type LLE = LibraryLoadError;
+
+#[throws(LibraryLoadError)]
+fn resolve_inherit(depth: u8, groups: &toml::Table, group_name: &str,
+ group: &'g toml::Value) -> Cow<'g, toml::Table> {
+ let gn = || format!("{}", group_name);
+ let gp = || format!("group.{}", group_name);
+
+ let group = group.as_table().ok_or_else(|| LLE::ExpectedTable(gp()))?;
+
+ let parent_name = match group.get("inherit") {
+ None => { return Cow::Borrowed(group) },
+ Some(p) = p,
+ };
+ let parent = groups.get(parent_name)
+ .ok_or_else(|| LLE::MissingParentGroup(gn(), parent_name.to_string))?;
+
+ let mut build = parent.resolve_inherit(
+ depth.checked_sub(1).ok_or_else(!| LLE:InheritDepthLimitExceeded(gn()))?,
+ groups, parent_name, parent);
+
+ build.extend(group.iter());
+ build
+}
+
impl Library {
#[throws(LibraryLoadError)]
pub fn load(path: &str) -> Library {
let mut f = BufReader::new(f);
let mut s = String::new();
f.read_to_string(&mut s).unwrap();
- let l : shapelib::Library = toml::from_str(&s)?;
+ let toplevel : toml::Value = s.parse()?;
+ let mut l = LibraryContents { pieces: HashMap::new() };
+ let groups =
+ toplevel
+ .as_table().ok_or_else(|| LLE::ExpectedTable(format!("toplevel")))?;
+ .get("group").or_else(toml::value::Value::Table(Default::default()))
+ .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 spec : LibraryGroupSpec = resolved.try_into()?;
+ for f in spec.files {
+ let usvgfile = format!("{}{}{}.usvg",
+ spec.stem_prefix, f.filespec, spec.stem_suffix);
+ let lp = LibraryPieceInfo { info, desc: fileentry.desc };
+ match l.entry(usvgfile) {
+ Occupied(oe) => throw!(LLE::DuplicateFile(
+ oe.key().clone(),
+ oe.get().clone(),
+ lp,
+ )),
+ Vacant(ve) => ve.insert(lp),
+ };
+ }
+ }
l
}
}
-type LLE = LibraryLoadError;
-
#[derive(Deserialize,Debug)]
struct Circle { }
#[typetag::deserialize]