docx_rs/documents/elements/
comment.rs1use 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}