From b136f04bc225380a6aa5daa28075eafd767a4a98 Mon Sep 17 00:00:00 2001 From: Philipp A Date: Mon, 19 Nov 2018 22:46:33 +0100 Subject: made serializable --- src/document_tree/extra_attributes.rs | 117 ++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 39 deletions(-) (limited to 'src/document_tree/extra_attributes.rs') diff --git a/src/document_tree/extra_attributes.rs b/src/document_tree/extra_attributes.rs index d73013e..9cd097d 100644 --- a/src/document_tree/extra_attributes.rs +++ b/src/document_tree/extra_attributes.rs @@ -1,5 +1,11 @@ use url::Url; +use serde::{ + Serialize, + Serializer, + ser::SerializeStruct, +}; + use super::attribute_types::{FixedSpace,ID,NameToken,AlignHV,AlignH,Measure,EnumeratedListType}; pub trait ExtraAttributes { @@ -8,51 +14,84 @@ pub trait ExtraAttributes { fn extra_mut(&mut self) -> &mut A; } -#[derive(Default,Debug)] pub struct Address { pub space: FixedSpace } -#[derive(Default,Debug)] pub struct LiteralBlock { pub space: FixedSpace } -#[derive(Default,Debug)] pub struct DoctestBlock { pub space: FixedSpace } -#[derive(Default,Debug)] pub struct SubstitutionDefinition { pub ltrim: Option, pub rtrim: Option } -#[derive(Default,Debug)] pub struct Comment { pub space: FixedSpace } -#[derive(Default,Debug)] pub struct Target { pub refuri: Option, pub refid: Option, pub refname: Vec, pub anonymous: Option } -#[derive(Default,Debug)] pub struct Raw { pub space: FixedSpace, pub format: Vec } -#[derive(Debug)] -pub struct Image { - pub align: Option, - pub uri: Url, - pub alt: Option, - pub height: Option, - pub width: Option, - pub scale: Option, +macro_rules! count { + () => (0usize); + ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); +} + +macro_rules! ser_url { + ($self:ident, refuri ) => { $self.refuri.as_ref().map(|uri| uri.to_string()) }; + ($self:ident, uri ) => { $self.uri.to_string() }; + ($self:ident, $param:ident) => { $self.$param }; } +macro_rules! impl_extra { + ( $name:ident { $( $param:ident : $type:ty ),* $(,)* } ) => ( + impl_extra!( + #[derive(Default,Debug)] + $name { $( $param : $type, )* } + ); + ); + ( $(#[$attr:meta])+ $name:ident { $( $param:ident : $type:ty ),* $(,)* } ) => ( + $(#[$attr])+ + pub struct $name { + $( pub $param : $type, )* + } + + impl Serialize for $name { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + #[allow(unused_mut)] + let mut state = serializer.serialize_struct(stringify!($name), count!($($param)*))?; + $( state.serialize_field(stringify!($param), &ser_url!(self, $param))?; )* + state.end() + } + } + ); +} + +impl_extra!(Address { space: FixedSpace }); +impl_extra!(LiteralBlock { space: FixedSpace }); +impl_extra!(DoctestBlock { space: FixedSpace }); +impl_extra!(SubstitutionDefinition { ltrim: Option, rtrim: Option }); +impl_extra!(Comment { space: FixedSpace }); +impl_extra!(Target { refuri: Option, refid: Option, refname: Vec, anonymous: Option }); +impl_extra!(Raw { space: FixedSpace, format: Vec }); +impl_extra!(#[derive(Debug)] Image { + align: Option, + uri: Url, + alt: Option, + height: Option, + width: Option, + scale: Option, +}); + //bools usually are XML yesorno. “auto” however either exists and is set to something random like “1” or doesn’t exist -#[derive(Default,Debug)] pub struct BulletList { pub bullet: Option } -#[derive(Default,Debug)] pub struct EnumeratedList { pub enumtype: Option, pub prefix: Option, pub suffix: Option } +impl_extra!(BulletList { bullet: Option }); +impl_extra!(EnumeratedList { enumtype: Option, prefix: Option, suffix: Option }); -#[derive(Default,Debug)] pub struct Footnote { pub backrefs: Vec, pub auto: Option } -#[derive(Default,Debug)] pub struct Citation { pub backrefs: Vec } -#[derive(Default,Debug)] pub struct SystemMessage { pub backrefs: Vec, pub level: Option, pub line: Option, pub type_: Option } -#[derive(Default,Debug)] pub struct Figure { pub align: Option, pub width: Option } -#[derive(Default,Debug)] pub struct Table; //TODO +impl_extra!(Footnote { backrefs: Vec, auto: Option }); +impl_extra!(Citation { backrefs: Vec }); +impl_extra!(SystemMessage { backrefs: Vec, level: Option, line: Option, type_: Option }); +impl_extra!(Figure { align: Option, width: Option }); +impl_extra!(Table {}); //TODO -#[derive(Default,Debug)] pub struct OptionArgument { pub delimiter: Option } +impl_extra!(OptionArgument { delimiter: Option }); -#[derive(Default,Debug)] pub struct Reference { pub name: Option, pub refuri: Option, pub refid: Option, pub refname: Vec } -#[derive(Default,Debug)] pub struct FootnoteReference { pub refid: Option, pub refname: Vec, pub auto: Option } -#[derive(Default,Debug)] pub struct CitationReference { pub refid: Option, pub refname: Vec } -#[derive(Default,Debug)] pub struct SubstitutionReference { pub refname: Vec } -#[derive(Default,Debug)] pub struct Problematic { pub refid: Option } +impl_extra!(Reference { name: Option, refuri: Option, refid: Option, refname: Vec }); +impl_extra!(FootnoteReference { refid: Option, refname: Vec, auto: Option }); +impl_extra!(CitationReference { refid: Option, refname: Vec }); +impl_extra!(SubstitutionReference { refname: Vec }); +impl_extra!(Problematic { refid: Option }); //also have non-inline versions. Inline image is no figure child, inline target has content -#[derive(Default,Debug)] pub struct TargetInline { pub refuri: Option, pub refid: Option, pub refname: Vec, pub anonymous: Option } -#[derive(Default,Debug)] pub struct RawInline { pub space: FixedSpace, pub format: Vec } -#[derive(Debug)] -pub struct ImageInline { - pub align: Option, - pub uri: Url, - pub alt: Option, - pub height: Option, - pub width: Option, - pub scale: Option, -} +impl_extra!(TargetInline { refuri: Option, refid: Option, refname: Vec, anonymous: Option }); +impl_extra!(RawInline { space: FixedSpace, format: Vec }); +impl_extra!(#[derive(Debug)] ImageInline { + align: Option, + uri: Url, + alt: Option, + height: Option, + width: Option, + scale: Option, +}); -- cgit v1.2.3