use serde::ser::{SerializeStruct, Serializer}; use serde::Serialize; use super::*; use crate::documents::BuildXML; use crate::xml_builder::*; #[derive(Debug, Clone, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct Document { pub children: Vec, pub section_property: SectionProperty, pub has_numbering: bool, } #[derive(Debug, Clone, PartialEq)] pub enum DocumentChild { Paragraph(Paragraph), Table(Table), BookmarkStart(BookmarkStart), BookmarkEnd(BookmarkEnd), } impl Serialize for DocumentChild { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match *self { DocumentChild::Paragraph(ref p) => { let mut t = serializer.serialize_struct("Paragraph", 2)?; t.serialize_field("type", "paragraph")?; t.serialize_field("data", p)?; t.end() } DocumentChild::Table(ref c) => { let mut t = serializer.serialize_struct("Table", 2)?; t.serialize_field("type", "table")?; t.serialize_field("data", c)?; t.end() } DocumentChild::BookmarkStart(ref c) => { let mut t = serializer.serialize_struct("BookmarkStart", 2)?; t.serialize_field("type", "bookmarkStart")?; t.serialize_field("data", c)?; t.end() } DocumentChild::BookmarkEnd(ref c) => { let mut t = serializer.serialize_struct("BookmarkEnd", 2)?; t.serialize_field("type", "bookmarkEnd")?; t.serialize_field("data", c)?; t.end() } } } } impl Default for Document { fn default() -> Self { Self { children: Vec::new(), section_property: SectionProperty::new(), has_numbering: false, } } } impl Document { pub fn new() -> Document { Default::default() } pub fn add_paragraph(mut self, p: Paragraph) -> Self { if p.has_numbering { self.has_numbering = true } self.children.push(DocumentChild::Paragraph(p)); self } pub fn add_table(mut self, t: Table) -> Self { if t.has_numbering { self.has_numbering = true } self.children.push(DocumentChild::Table(t)); self } pub fn add_bookmark_start(mut self, id: usize, name: impl Into) -> Self { self.children .push(DocumentChild::BookmarkStart(BookmarkStart::new(id, name))); self } pub fn add_bookmark_end(mut self, id: usize) -> Self { self.children .push(DocumentChild::BookmarkEnd(BookmarkEnd::new(id))); self } } impl BuildXML for Document { fn build(&self) -> Vec { let mut b = XMLBuilder::new() .declaration(Some(true)) .open_document() .open_body(); for c in &self.children { match c { DocumentChild::Paragraph(p) => b = b.add_child(p), DocumentChild::Table(t) => b = b.add_child(t), DocumentChild::BookmarkStart(s) => b = b.add_child(s), DocumentChild::BookmarkEnd(e) => b = b.add_child(e), } } b.add_child(&self.section_property).close().close().build() } } #[cfg(test)] mod tests { use super::super::Run; use super::*; #[cfg(test)] use pretty_assertions::assert_eq; use std::str; #[test] fn test_document() { let b = Document::new() .add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello"))) .build(); assert_eq!( str::from_utf8(&b).unwrap(), r#" Hello "# ); } }