docx_rs/documents/elements/
indent.rs

1use serde::ser::{SerializeStruct, Serializer};
2use serde::Serialize;
3use std::io::Write;
4
5use crate::documents::BuildXML;
6use crate::types::*;
7use crate::xml_builder::*;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct Indent {
11    pub start: Option<i32>,
12    pub end: Option<i32>,
13    pub special_indent: Option<SpecialIndentType>,
14    pub start_chars: Option<i32>,
15    // Internal, for reading
16    pub hanging_chars: Option<i32>,
17    pub first_line_chars: Option<i32>,
18}
19
20impl Indent {
21    pub fn new(
22        start: Option<i32>,
23        special_indent: Option<SpecialIndentType>,
24        end: Option<i32>,
25        start_chars: Option<i32>,
26    ) -> Indent {
27        Indent {
28            start,
29            start_chars,
30            end,
31            special_indent,
32            // Internal, for reading
33            hanging_chars: None,
34            first_line_chars: None,
35        }
36    }
37
38    pub fn end(mut self, end: i32) -> Self {
39        self.end = Some(end);
40        self
41    }
42
43    pub fn hanging_chars(mut self, chars: i32) -> Self {
44        self.hanging_chars = Some(chars);
45        self
46    }
47
48    pub fn first_line_chars(mut self, chars: i32) -> Self {
49        self.first_line_chars = Some(chars);
50        self
51    }
52}
53
54impl BuildXML for Indent {
55    fn build_to<W: Write>(
56        &self,
57        stream: xml::writer::EventWriter<W>,
58    ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
59        XMLBuilder::from(stream)
60            .indent(
61                self.start,
62                self.special_indent,
63                self.end.unwrap_or_default(),
64                self.start_chars,
65            )?
66            .into_inner()
67    }
68}
69
70impl Serialize for Indent {
71    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
72    where
73        S: Serializer,
74    {
75        let mut t = serializer.serialize_struct("Indent", 3)?;
76        t.serialize_field("start", &self.start)?;
77        t.serialize_field("startChars", &self.start_chars)?;
78        t.serialize_field("end", &self.end)?;
79        t.serialize_field("specialIndent", &self.special_indent)?;
80        t.serialize_field("hangingChars", &self.hanging_chars)?;
81        t.serialize_field("firstLineChars", &self.first_line_chars)?;
82        t.end()
83    }
84}
85
86#[cfg(test)]
87mod tests {
88
89    use super::*;
90    #[cfg(test)]
91    use pretty_assertions::assert_eq;
92    use std::str;
93
94    #[test]
95    fn test_left() {
96        let b = Indent::new(Some(20), None, None, None).build();
97        assert_eq!(
98            str::from_utf8(&b).unwrap(),
99            r#"<w:ind w:left="20" w:right="0" />"#
100        );
101    }
102
103    #[test]
104    fn test_first_line() {
105        let b = Indent::new(Some(20), Some(SpecialIndentType::FirstLine(40)), None, None).build();
106        assert_eq!(
107            str::from_utf8(&b).unwrap(),
108            r#"<w:ind w:left="20" w:right="0" w:firstLine="40" />"#
109        );
110    }
111
112    #[test]
113    fn test_hanging() {
114        let b = Indent::new(Some(20), Some(SpecialIndentType::Hanging(50)), None, None).build();
115        assert_eq!(
116            str::from_utf8(&b).unwrap(),
117            r#"<w:ind w:left="20" w:right="0" w:hanging="50" />"#
118        );
119    }
120}