umya_spreadsheet/reader/
driver.rs

1use quick_xml::events::attributes::Attribute;
2use std::path::{Component, Path, PathBuf};
3use std::string::FromUtf8Error;
4
5#[macro_export]
6macro_rules! xml_read_loop {
7    ($reader:ident $(,$pat:pat => $result:expr)+ $(,)?) => {
8        let mut buf = Vec::new();
9        loop {
10            let ev = match $reader.read_event_into(&mut buf) {
11                Ok(v) => v,
12                Err(e) => panic!("Error at position {}: {e:?}", $reader.buffer_position()),
13            };
14
15            match ev {
16                $($pat => $result,)+
17                _ => (),
18            }
19
20            buf.clear();
21        }
22    };
23}
24
25pub(crate) use crate::xml_read_loop;
26
27#[macro_export]
28macro_rules! set_string_from_xml {
29    ($self:ident, $e:ident, $attr:ident, $xml_attr:expr) => {{
30        if let Some(v) = get_attribute($e, $xml_attr.as_bytes()) {
31            $self.$attr.set_value_string(v);
32        }
33    }};
34}
35
36pub(crate) use crate::set_string_from_xml;
37
38pub(crate) fn normalize_path(path: &str) -> PathBuf {
39    let path = Path::new(path);
40    let mut components = path.components().peekable();
41    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
42        components.next();
43        PathBuf::from(c.as_os_str())
44    } else {
45        PathBuf::new()
46    };
47
48    for component in components {
49        match component {
50            Component::Prefix(..) => unreachable!(),
51            Component::RootDir => {
52                ret.push(component.as_os_str());
53            }
54            Component::CurDir => {}
55            Component::ParentDir => {
56                ret.pop();
57            }
58            Component::Normal(c) => {
59                ret.push(c);
60            }
61        }
62    }
63    ret
64}
65
66#[inline]
67pub(crate) fn join_paths(base_path: &str, target: &str) -> String {
68    match target.split_once('/') {
69        Some(("", target)) => normalize_path_to_str(target),
70        _ => normalize_path_to_str(&format!("{}/{}", base_path, target)),
71    }
72}
73
74#[inline]
75pub(crate) fn normalize_path_to_str(path: &str) -> String {
76    let ret = normalize_path(path);
77    ret.to_str().unwrap_or("").replace('\\', "/")
78}
79
80#[inline]
81pub(crate) fn get_attribute(e: &quick_xml::events::BytesStart<'_>, key: &[u8]) -> Option<String> {
82    e.attributes()
83        .with_checks(false)
84        .find_map(|attr| match attr {
85            Ok(ref attr) if attr.key.into_inner() == key => {
86                Some(get_attribute_value(attr).unwrap())
87            }
88            _ => None,
89        })
90}
91
92#[inline]
93pub(crate) fn get_attribute_value(attr: &Attribute) -> Result<String, FromUtf8Error> {
94    String::from_utf8(attr.value.to_vec())
95}