docx_rs/reader/
section_property.rs

1use std::io::Read;
2use std::str::FromStr;
3
4use xml::attribute::OwnedAttribute;
5use xml::reader::{EventReader, XmlEvent};
6
7use crate::SectionType;
8
9use super::*;
10
11fn read_page_size(attributes: &[OwnedAttribute]) -> Result<PageSize, ReaderError> {
12    let mut size = PageSize::new();
13    for a in attributes {
14        let local_name = &a.name.local_name;
15        match local_name.as_str() {
16            "w" => {
17                size = size.width(value_to_dax(&a.value)? as u32);
18            }
19            "h" => {
20                size = size.height(value_to_dax(&a.value)? as u32);
21            }
22            _ => {}
23        }
24    }
25    Ok(size)
26}
27
28fn read_page_margin(
29    attributes: &[OwnedAttribute],
30) -> Result<crate::types::PageMargin, ReaderError> {
31    let mut margin = crate::types::PageMargin::new();
32    for a in attributes {
33        let local_name = &a.name.local_name;
34        match local_name.as_str() {
35            "top" => {
36                margin = margin.top(value_to_dax(&a.value)? as i32);
37            }
38            "right" => {
39                margin = margin.right(value_to_dax(&a.value)? as i32);
40            }
41            "bottom" => {
42                margin = margin.bottom(value_to_dax(&a.value)? as i32);
43            }
44            "left" => {
45                margin = margin.left(value_to_dax(&a.value)? as i32);
46            }
47            "header" => {
48                margin = margin.header(value_to_dax(&a.value)? as i32);
49            }
50            "footer" => {
51                margin = margin.footer(value_to_dax(&a.value)? as i32);
52            }
53            "gutter" => {
54                margin = margin.gutter(value_to_dax(&a.value)? as i32);
55            }
56            _ => {}
57        }
58    }
59    Ok(margin)
60}
61
62fn read_header_or_footer_reference(
63    attributes: &[OwnedAttribute],
64) -> Result<(String, String), ReaderError> {
65    let mut rid = "".to_owned();
66    let mut header_type = "default".to_owned();
67    for a in attributes {
68        let local_name = &a.name.local_name;
69        match local_name.as_str() {
70            "type" => {
71                header_type = a.value.to_owned();
72            }
73            "id" => {
74                rid = a.value.to_owned();
75            }
76            _ => {}
77        }
78    }
79    Ok((rid, header_type))
80}
81
82impl ElementReader for SectionProperty {
83    fn read<R: Read>(
84        r: &mut EventReader<R>,
85        _attrs: &[OwnedAttribute],
86    ) -> Result<Self, ReaderError> {
87        let mut sp = SectionProperty::new();
88        loop {
89            let e = r.next();
90            match e {
91                Ok(XmlEvent::StartElement {
92                    attributes, name, ..
93                }) => {
94                    let e = XMLElement::from_str(&name.local_name).unwrap();
95                    match e {
96                        XMLElement::PageMargin => {
97                            let margin = read_page_margin(&attributes)?;
98                            sp = sp.page_margin(margin);
99                        }
100                        XMLElement::PageSize => {
101                            let size = read_page_size(&attributes)?;
102                            sp = sp.page_size(size);
103                        }
104                        XMLElement::DocGrid => {
105                            if let Ok(doc_grid) = DocGrid::read(r, &attributes) {
106                                sp = sp.doc_grid(doc_grid);
107                            }
108                        }
109                        XMLElement::PageNumType => {
110                            if let Ok(page_num_type) = PageNumType::read(r, &attributes) {
111                                sp = sp.page_num_type(page_num_type);
112                            }
113                        }
114                        XMLElement::HeaderReference => {
115                            if let Ok((rid, header_type)) =
116                                read_header_or_footer_reference(&attributes)
117                            {
118                                match header_type.as_str() {
119                                    "default" => {
120                                        sp.header_reference =
121                                            Some(HeaderReference::new(header_type, rid));
122                                    }
123                                    "first" => {
124                                        sp.first_header_reference =
125                                            Some(HeaderReference::new(header_type, rid));
126                                    }
127                                    "even" => {
128                                        sp.even_header_reference =
129                                            Some(HeaderReference::new(header_type, rid));
130                                    }
131                                    _ => {}
132                                }
133                            }
134                        }
135                        XMLElement::FooterReference => {
136                            if let Ok((rid, footer_type)) =
137                                read_header_or_footer_reference(&attributes)
138                            {
139                                match footer_type.as_str() {
140                                    "default" => {
141                                        sp.footer_reference =
142                                            Some(FooterReference::new(footer_type, rid));
143                                    }
144                                    "first" => {
145                                        sp.first_footer_reference =
146                                            Some(FooterReference::new(footer_type, rid));
147                                    }
148                                    "even" => {
149                                        sp.even_footer_reference =
150                                            Some(FooterReference::new(footer_type, rid));
151                                    }
152                                    _ => {}
153                                }
154                            }
155                        }
156                        XMLElement::Type => {
157                            if let Some(val) = read_val(&attributes) {
158                                if let Ok(val) = SectionType::from_str(&val) {
159                                    sp.section_type = Some(val);
160                                }
161                            }
162                        }
163                        XMLElement::TitlePg => sp = sp.title_pg(),
164                        _ => {}
165                    }
166                }
167                Ok(XmlEvent::EndElement { name, .. }) => {
168                    let e = XMLElement::from_str(&name.local_name).unwrap();
169                    if e == XMLElement::SectionProperty {
170                        return Ok(sp);
171                    }
172                }
173                Err(_) => return Err(ReaderError::XMLReadError),
174                _ => {}
175            }
176        }
177    }
178}