From: Ian Jackson Date: Wed, 11 May 2022 23:37:15 +0000 (+0100) Subject: mformat 2: Actually parse the outline properly X-Git-Tag: otter-1.1.0~223 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=f2f2c9628b80d21b7464fb472d1fc2d1f25b2fe1;p=otter.git mformat 2: Actually parse the outline properly This turns out to be quite hard. Signed-off-by: Ian Jackson --- diff --git a/src/shapelib-toml.rs b/src/shapelib-toml.rs index e81bafe3..f5dfc2d2 100644 --- a/src/shapelib-toml.rs +++ b/src/shapelib-toml.rs @@ -4,6 +4,8 @@ pub use crate::prelude::*; +use shapelib::OutlineDefnEnum; + #[doc(hidden)] pub type LLE = shapelib::LibraryLoadError; // At the implementation level, each loaded item contains an @@ -30,7 +32,7 @@ pub struct GroupDetails { #[serde(default)] pub colours: HashMap, pub desc_template: Option, pub occulted: Option, - #[serde(flatten)] pub outline: OutlineDetails, + pub outline: OutlineDetails, } #[derive(Debug,Deserialize,Copy,Clone)] @@ -48,12 +50,12 @@ pub enum ScaleFitDetails { Fit, Cover, Stretch } #[serde(untagged)] pub enum OutlineDetails { Full(FullOutlineDetails), // introduced with mformat=2 - Shape(Box), + Shape(OutlineDefnEnum), } #[derive(Debug,Deserialize)] pub struct FullOutlineDetails { - shape: Box, + shape: OutlineDefnEnum, #[serde(default)] size: Vec, #[serde(default)] scale: Option, } @@ -61,9 +63,9 @@ pub struct FullOutlineDetails { impl OutlineDetails { // enum_access could perhaps do this but controlling the serde // would become confusing - pub fn shape(&self) -> &dyn shapelib::OutlineDefn { match self { - OutlineDetails::Full(full) => &*full.shape, - OutlineDetails::Shape(shape) => &**shape, + pub fn shape(&self) -> OutlineDefnEnum { match self { + OutlineDetails::Full(full) => full.shape, + OutlineDetails::Shape(shape) => *shape, }} pub fn size_scale(&self) -> (&[f64], Option<&f64>) { match self { OutlineDetails::Full(full) => (&full.size, full.scale.as_ref()), diff --git a/src/shapelib.rs b/src/shapelib.rs index d853b3b2..7daa48e9 100644 --- a/src/shapelib.rs +++ b/src/shapelib.rs @@ -31,19 +31,6 @@ pub struct GroupData { #[allow(dead_code)] /*TODO*/ mformat: materials_format::Version, } -#[typetag::deserialize(tag="outline")] -pub trait OutlineDefn: Debug + Sync + Send + 'static { - /// Success or failure must not depend on `svg_sz` - /// - /// Called to *check* the group configuration before load, but - /// with a dummy svg_gz of [1,1]. That must correctly predict - /// success with other sizes. - fn load(&self, size: PosC) -> Outline { - RectShape { xy: size }.into() - } - - fn load_mf1(&self, group: &GroupData) -> Result; -} #[derive(Debug,Clone,Copy)] pub struct ShapeCalculable { } @@ -727,6 +714,51 @@ impl GroupDetails { } } +//---------- OutlineDefn etc. ---------- + +#[ambassador::delegatable_trait] +pub trait OutlineDefn: Debug + Sync + Send + 'static { + /// Success or failure must not depend on `svg_sz` + /// + /// Called to *check* the group configuration before load, but + /// with a dummy svg_gz of [1,1]. That must correctly predict + /// success with other sizes. + fn load(&self, size: PosC) -> Outline { + RectShape { xy: size }.into() + } + + fn load_mf1(&self, group: &GroupData) -> Result; +} + +// We used to do this via typetag and Box +// +// But I didnt manage to get typetag to deserialise these unit variants. +// Instead, we have this enum and a cheesy macro to impl OutlineDefn +// by delegating to a freshly made (static) unit struct value. +macro_rules! outline_defns { + { $( $Shape:ident ),* } => { paste!{ + + #[derive(Deserialize,Debug,Copy,Clone,Eq,PartialEq)] + pub enum OutlineDefnEnum { + $( $Shape, )* + } + + impl OutlineDefnEnum { + fn defn(self) -> &'static dyn OutlineDefn { + match self { $( + Self::$Shape => &[< $Shape Defn >] as _, + )* } + } + } + + } } +} + +outline_defns! { Circle, Rect } +impl_via_ambassador!{ + impl OutlineDefn for OutlineDefnEnum { defn() } +} + //---------- RectShape ---------- #[derive(Clone,Copy,Debug,Serialize,Deserialize)] @@ -780,8 +812,7 @@ impl OutlineTrait for RectShape { } #[derive(Deserialize,Debug)] -struct RectDefn { } -#[typetag::deserialize(name="Rect")] +struct RectDefn; impl OutlineDefn for RectDefn { fn load(&self, size: PosC) -> Outline { RectShape { xy: size }.into() @@ -818,8 +849,7 @@ impl OutlineTrait for CircleShape { } #[derive(Deserialize,Debug)] -struct CircleDefn { } -#[typetag::deserialize(name="Circle")] +struct CircleDefn; impl OutlineDefn for CircleDefn { fn load(&self, size: PosC) -> Outline { let diam = size