diff options
Diffstat (limited to 'src/document_tree/extra_attributes.rs')
| -rw-r--r-- | src/document_tree/extra_attributes.rs | 117 | 
1 files changed, 78 insertions, 39 deletions
| 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<A> { @@ -8,51 +14,84 @@ pub trait ExtraAttributes<A> {  	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<bool>, pub rtrim: Option<bool> } -#[derive(Default,Debug)] pub struct Comment { pub space: FixedSpace } -#[derive(Default,Debug)] pub struct Target { pub refuri: Option<Url>, pub refid: Option<ID>, pub refname: Vec<NameToken>, pub anonymous: Option<bool> } -#[derive(Default,Debug)] pub struct Raw { pub space: FixedSpace, pub format: Vec<NameToken> } -#[derive(Debug)] -pub struct Image { -	pub align: Option<AlignHV>, -	pub uri: Url, -	pub alt: Option<String>, -	pub height: Option<Measure>, -	pub width: Option<Measure>, -	pub scale: Option<f64>, +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<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 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<bool>, rtrim: Option<bool> }); +impl_extra!(Comment { space: FixedSpace }); +impl_extra!(Target { refuri: Option<Url>, refid: Option<ID>, refname: Vec<NameToken>, anonymous: Option<bool> }); +impl_extra!(Raw { space: FixedSpace, format: Vec<NameToken> }); +impl_extra!(#[derive(Debug)] Image { +	align: Option<AlignHV>, +	uri: Url, +	alt: Option<String>, +	height: Option<Measure>, +	width: Option<Measure>, +	scale: Option<f64>, +}); +  //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<String> } -#[derive(Default,Debug)] pub struct EnumeratedList { pub enumtype: Option<EnumeratedListType>, pub prefix: Option<String>, pub suffix: Option<String> } +impl_extra!(BulletList { bullet: Option<String> }); +impl_extra!(EnumeratedList { enumtype: Option<EnumeratedListType>, prefix: Option<String>, suffix: Option<String> }); -#[derive(Default,Debug)] pub struct Footnote { pub backrefs: Vec<ID>, pub auto: Option<bool> } -#[derive(Default,Debug)] pub struct Citation { pub backrefs: Vec<ID> } -#[derive(Default,Debug)] pub struct SystemMessage { pub backrefs: Vec<ID>, pub level: Option<usize>, pub line: Option<usize>, pub type_: Option<NameToken> } -#[derive(Default,Debug)] pub struct Figure { pub align: Option<AlignH>, pub width: Option<usize> } -#[derive(Default,Debug)] pub struct Table; //TODO +impl_extra!(Footnote { backrefs: Vec<ID>, auto: Option<bool> }); +impl_extra!(Citation { backrefs: Vec<ID> }); +impl_extra!(SystemMessage { backrefs: Vec<ID>, level: Option<usize>, line: Option<usize>, type_: Option<NameToken> }); +impl_extra!(Figure { align: Option<AlignH>, width: Option<usize> }); +impl_extra!(Table {}); //TODO -#[derive(Default,Debug)] pub struct OptionArgument { pub delimiter: Option<String> } +impl_extra!(OptionArgument { delimiter: Option<String> }); -#[derive(Default,Debug)] pub struct Reference { pub name: Option<String>, pub refuri: Option<Url>, pub refid: Option<ID>, pub refname: Vec<NameToken> } -#[derive(Default,Debug)] pub struct FootnoteReference { pub refid: Option<ID>, pub refname: Vec<NameToken>, pub auto: Option<bool> } -#[derive(Default,Debug)] pub struct CitationReference { pub refid: Option<ID>, pub refname: Vec<NameToken> } -#[derive(Default,Debug)] pub struct SubstitutionReference { pub refname: Vec<NameToken> } -#[derive(Default,Debug)] pub struct Problematic { pub refid: Option<ID> } +impl_extra!(Reference { name: Option<String>, refuri: Option<Url>, refid: Option<ID>, refname: Vec<NameToken> }); +impl_extra!(FootnoteReference { refid: Option<ID>, refname: Vec<NameToken>, auto: Option<bool> }); +impl_extra!(CitationReference { refid: Option<ID>, refname: Vec<NameToken> }); +impl_extra!(SubstitutionReference { refname: Vec<NameToken> }); +impl_extra!(Problematic { refid: Option<ID> });  //also have non-inline versions. Inline image is no figure child, inline target has content -#[derive(Default,Debug)] pub struct TargetInline { pub refuri: Option<Url>, pub refid: Option<ID>, pub refname: Vec<NameToken>, pub anonymous: Option<bool> } -#[derive(Default,Debug)] pub struct RawInline { pub space: FixedSpace, pub format: Vec<NameToken> } -#[derive(Debug)] -pub struct ImageInline { -	pub align: Option<AlignHV>, -	pub uri: Url, -	pub alt: Option<String>, -	pub height: Option<Measure>, -	pub width: Option<Measure>, -	pub scale: Option<f64>, -} +impl_extra!(TargetInline { refuri: Option<Url>, refid: Option<ID>, refname: Vec<NameToken>, anonymous: Option<bool> }); +impl_extra!(RawInline { space: FixedSpace, format: Vec<NameToken> }); +impl_extra!(#[derive(Debug)] ImageInline { +	align: Option<AlignHV>, +	uri: Url, +	alt: Option<String>, +	height: Option<Measure>, +	width: Option<Measure>, +	scale: Option<f64>, +}); | 
