pub use crate::prelude::*;
+use shapelib::OutlineDefnEnum;
+
#[doc(hidden)] pub type LLE = shapelib::LibraryLoadError;
// At the implementation level, each loaded item contains an
#[serde(default)] pub colours: HashMap<String, RecolourData>,
pub desc_template: Option<String>,
pub occulted: Option<OccultationMethod>,
- #[serde(flatten)] pub outline: OutlineDetails,
+ pub outline: OutlineDetails,
}
#[derive(Debug,Deserialize,Copy,Clone)]
#[serde(untagged)]
pub enum OutlineDetails {
Full(FullOutlineDetails), // introduced with mformat=2
- Shape(Box<dyn shapelib::OutlineDefn>),
+ Shape(OutlineDefnEnum),
}
#[derive(Debug,Deserialize)]
pub struct FullOutlineDetails {
- shape: Box<dyn shapelib::OutlineDefn>,
+ shape: OutlineDefnEnum,
#[serde(default)] size: Vec<f64>,
#[serde(default)] scale: Option<f64>,
}
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()),
#[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<f64>) -> Outline {
- RectShape { xy: size }.into()
- }
-
- fn load_mf1(&self, group: &GroupData) -> Result<Outline,LLE>;
-}
#[derive(Debug,Clone,Copy)]
pub struct ShapeCalculable { }
}
}
+//---------- 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<f64>) -> Outline {
+ RectShape { xy: size }.into()
+ }
+
+ fn load_mf1(&self, group: &GroupData) -> Result<Outline,LLE>;
+}
+
+// We used to do this via typetag and Box<dyn OutlineDefn>
+//
+// 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)]
}
#[derive(Deserialize,Debug)]
-struct RectDefn { }
-#[typetag::deserialize(name="Rect")]
+struct RectDefn;
impl OutlineDefn for RectDefn {
fn load(&self, size: PosC<f64>) -> Outline {
RectShape { xy: size }.into()
}
#[derive(Deserialize,Debug)]
-struct CircleDefn { }
-#[typetag::deserialize(name="Circle")]
+struct CircleDefn;
impl OutlineDefn for CircleDefn {
fn load(&self, size: PosC<f64>) -> Outline {
let diam = size