assembly_xml/common/
mod.rs

1//! # Code that's used in all XML modules
2
3use std::{io::BufRead, todo};
4
5use displaydoc::Display;
6use quick_xml::{events::Event, Reader};
7use thiserror::Error;
8
9pub mod exact;
10
11/// A general error type
12#[derive(Debug, Display, Error)]
13pub enum XmlError {
14    /// Failed to read the next XML event
15    Reader(#[from] quick_xml::Error),
16    /// Reached EOF while searching for {0}
17    EofWhileExpecting(&'static str),
18    /// Expected <?xml declaration
19    ExpectedDecl,
20}
21
22/// The result type for this module
23pub type Result<T> = std::result::Result<T, XmlError>;
24
25/// Expect an `<?xml …` declaration
26pub fn expect_decl<B: BufRead>(xml: &mut Reader<B>, buf: &mut Vec<u8>) -> Result<()> {
27    if let Event::Decl(_) = xml.read_event(buf)? {
28        buf.clear();
29        Ok(())
30    } else {
31        Err(XmlError::ExpectedDecl)
32    }
33}
34
35/// Expect an opening tag `<{key} name="…">`
36pub fn expect_named_elem<B: BufRead>(
37    xml: &mut Reader<B>,
38    buf: &mut Vec<u8>,
39    key: &'static str,
40    parent: Option<&'static str>,
41) -> Result<Option<String>> {
42    match xml.read_event(buf)? {
43        Event::Start(start) => {
44            if start.name() == key.as_bytes() {
45                let mut name = String::new();
46                for attr in start.attributes() {
47                    let attr = attr?;
48                    if attr.key == b"name" {
49                        name = xml.decode(&attr.value).into_owned();
50                        break;
51                    }
52                }
53                buf.clear();
54                Ok(Some(name))
55            } else {
56                todo!();
57            }
58        }
59        Event::End(e) => {
60            assert_eq!(e.name(), parent.unwrap().as_bytes());
61            buf.clear();
62            Ok(None)
63        }
64        Event::Eof => Err(XmlError::EofWhileExpecting(key)),
65        _ => panic!(),
66    }
67}
68
69/// Expect an opening tag `<{key}>`
70pub fn expect_elem<B: BufRead>(
71    xml: &mut Reader<B>,
72    buf: &mut Vec<u8>,
73    key: &'static str,
74) -> Result<()> {
75    if let Event::Start(start) = xml.read_event(buf)? {
76        if start.name() == key.as_bytes() {
77            buf.clear();
78            Ok(())
79        } else {
80            todo!();
81        }
82    } else {
83        todo!()
84    }
85}
86
87/// Expect a closing tag `</{key}>`
88pub fn expect_end<B: BufRead>(
89    xml: &mut Reader<B>,
90    buf: &mut Vec<u8>,
91    key: &'static str,
92) -> Result<()> {
93    if let Event::End(end) = xml.read_event(buf)? {
94        #[allow(clippy::branches_sharing_code)]
95        if end.name() == key.as_bytes() {
96            buf.clear();
97            Ok(())
98        } else {
99            buf.clear();
100            todo!()
101        }
102    } else {
103        todo!()
104    }
105}