use log::warn;
use quick_xml::events::Event;
use quick_xml::Reader;
use crate::docx::dimension::Dimension;
use crate::docx::error::Result;
use crate::docx::model::{DocumentSettings, RevisionSaveId};
use crate::docx::xml;
pub fn parse_settings(data: &[u8]) -> Result<DocumentSettings> {
let mut reader = Reader::from_reader(data);
reader.config_mut().trim_text(true);
let mut buf = Vec::new();
let mut settings = DocumentSettings::default();
loop {
match xml::next_event(&mut reader, &mut buf)? {
Event::Start(ref e) if xml::local_name(e.name().as_ref()) == b"settings" => break,
Event::Eof => return Ok(settings),
_ => {}
}
}
loop {
match xml::next_event(&mut reader, &mut buf)? {
Event::Start(ref e) => {
let qn = e.name();
let local = xml::local_name(qn.as_ref());
if local == b"rsids" {
parse_rsids(&mut reader, &mut buf, &mut settings)?;
}
}
Event::Empty(ref e) => {
let qn = e.name();
let local = xml::local_name(qn.as_ref());
match local {
b"defaultTabStop" => {
if let Some(val) = xml::optional_attr_i64(e, b"val")? {
settings.default_tab_stop = Dimension::new(val);
}
}
b"evenAndOddHeaders" => {
let enabled = xml::optional_attr_bool(e, b"val")?.unwrap_or(true);
settings.even_and_odd_headers = enabled;
}
_ => {}
}
}
Event::End(ref e) if xml::local_name(e.name().as_ref()) == b"settings" => break,
_ => {}
}
}
Ok(settings)
}
fn parse_rsids(
reader: &mut Reader<&[u8]>,
buf: &mut Vec<u8>,
settings: &mut DocumentSettings,
) -> Result<()> {
loop {
match xml::next_event(reader, buf)? {
Event::Empty(ref e) | Event::Start(ref e) => {
let qn = e.name();
let local = xml::local_name(qn.as_ref());
match local {
b"rsidRoot" => {
if let Some(val) = xml::optional_attr(e, b"val")? {
settings.rsid_root = RevisionSaveId::from_hex(&val);
}
}
b"rsid" => {
if let Some(val) = xml::optional_attr(e, b"val")? {
if let Some(rsid) = RevisionSaveId::from_hex(&val) {
settings.rsids.push(rsid);
}
}
}
_ => {
warn!(
"rsids: unsupported element <{}>",
String::from_utf8_lossy(local)
);
}
}
}
Event::End(ref e) if xml::local_name(e.name().as_ref()) == b"rsids" => break,
Event::Eof => return Err(xml::unexpected_eof(b"rsids")),
_ => {}
}
}
Ok(())
}