docx_rs/documents/elements/
comment.rs

1use serde::ser::{SerializeStruct, Serializer};
2use serde::Serialize;
3use std::io::Write;
4
5use crate::documents::*;
6use crate::xml_builder::*;
7
8#[derive(Serialize, Debug, Clone, PartialEq)]
9#[serde(rename_all = "camelCase")]
10pub struct Comment {
11    pub id: usize,
12    pub author: String,
13    pub date: String,
14    pub children: Vec<CommentChild>,
15    pub parent_comment_id: Option<usize>,
16}
17
18#[derive(Debug, Clone, PartialEq)]
19pub enum CommentChild {
20    Paragraph(Paragraph),
21    Table(Table),
22}
23
24impl Serialize for CommentChild {
25    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
26    where
27        S: Serializer,
28    {
29        match *self {
30            CommentChild::Paragraph(ref p) => {
31                let mut t = serializer.serialize_struct("Paragraph", 2)?;
32                t.serialize_field("type", "paragraph")?;
33                t.serialize_field("data", p)?;
34                t.end()
35            }
36            CommentChild::Table(ref c) => {
37                let mut t = serializer.serialize_struct("Table", 2)?;
38                t.serialize_field("type", "table")?;
39                t.serialize_field("data", c)?;
40                t.end()
41            }
42        }
43    }
44}
45
46impl Default for Comment {
47    fn default() -> Comment {
48        Comment {
49            id: 1,
50            author: "unnamed".to_owned(),
51            date: "1970-01-01T00:00:00Z".to_owned(),
52            children: vec![],
53            parent_comment_id: None,
54        }
55    }
56}
57
58impl Comment {
59    pub fn new(id: usize) -> Comment {
60        Self {
61            id,
62            ..Default::default()
63        }
64    }
65
66    pub fn author(mut self, author: impl Into<String>) -> Comment {
67        self.author = author.into();
68        self
69    }
70
71    pub fn date(mut self, date: impl Into<String>) -> Comment {
72        self.date = date.into();
73        self
74    }
75
76    pub fn add_paragraph(mut self, p: Paragraph) -> Self {
77        self.children.push(CommentChild::Paragraph(p));
78        self
79    }
80
81    pub fn add_table(mut self, t: Table) -> Self {
82        self.children.push(CommentChild::Table(t));
83        self
84    }
85
86    pub fn parent_comment_id(mut self, parent_comment_id: usize) -> Comment {
87        self.parent_comment_id = Some(parent_comment_id);
88        self
89    }
90
91    pub fn id(&self) -> usize {
92        self.id
93    }
94}
95
96impl BuildXML for CommentChild {
97    fn build_to<W: Write>(
98        &self,
99        stream: xml::writer::EventWriter<W>,
100    ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
101        match self {
102            CommentChild::Paragraph(v) => v.build_to(stream),
103            CommentChild::Table(v) => v.build_to(stream),
104        }
105    }
106}
107
108impl BuildXML for Comment {
109    fn build_to<W: Write>(
110        &self,
111        stream: xml::writer::EventWriter<W>,
112    ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
113        XMLBuilder::from(stream)
114            .open_comment(&self.id.to_string(), &self.author, &self.date, "")?
115            .add_children(&self.children)?
116            .close()?
117            .into_inner()
118    }
119}
120
121#[cfg(test)]
122mod tests {
123
124    use super::*;
125    #[cfg(test)]
126    use pretty_assertions::assert_eq;
127    use std::str;
128
129    #[test]
130    fn test_comment_default() {
131        let b = Comment::new(1).build();
132        assert_eq!(
133            str::from_utf8(&b).unwrap(),
134            r#"<w:comment w:id="1" w:author="unnamed" w:date="1970-01-01T00:00:00Z" w:initials="" />"#
135        );
136    }
137
138    #[test]
139    fn test_comment_with_default_paragraph() {
140        let b = Comment::new(1).add_paragraph(Paragraph::new()).build();
141        assert_eq!(
142            str::from_utf8(&b).unwrap(),
143            r#"<w:comment w:id="1" w:author="unnamed" w:date="1970-01-01T00:00:00Z" w:initials=""><w:p w14:paraId="12345678"><w:pPr><w:rPr /></w:pPr></w:p></w:comment>"#
144        );
145    }
146}