docx_reader/reader/
section_property.rs

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