parco_xml/dexml/append_path.rs
1use crate::de::Reader;
2
3/// used to control the `path` parameter in error handling
4///
5/// you should use [`Reader::append_path`] and [`Reader::exit_path`] to
6/// control "where" you are in the xml tree so if you encounter an error
7/// you can give a helpful message to the user
8pub enum AppendPath<'a> {
9 /// text node shown in the path as "\:text"
10 Text,
11 /// attribute shown in the path as "\:attr"
12 GeneralAttr,
13 /// attribute shown in the path as "\:\[attr_name\]" where the name is [str] you provide
14 NamedAttr(&'a str),
15 /// element shown in the path as "\/\[element_name\]" where the name is [str] you provide
16 Element(&'a str),
17 /// custom path show as "\:\[name\]" where the name is [str] you provide
18 Custom(&'a str),
19}
20
21impl<'a> Reader<'a> {
22 /// used to control the `path` parameter in error handling
23 ///
24 /// you should use [`Reader::append_path`] and [`Reader::exit_path`] to
25 /// control "where" you are in the xml tree so if you encounter an error
26 /// you can give a helpful message to the user
27 pub fn append_path(&mut self, append_path: AppendPath) {
28 let (ch, n) = match append_path {
29 AppendPath::Text => (':', "text"),
30 AppendPath::GeneralAttr => (':', "attr"),
31 AppendPath::NamedAttr(attr) => (':', attr),
32 AppendPath::Element(el) => ('/', el),
33 AppendPath::Custom(el) => (':', el),
34 };
35 self.path.push(ch);
36 self.path.push_str(n);
37 }
38
39 /// remove the last part of the path until ":" or "/" for example
40 ///
41 /// if the path was "/document/element:my_attr"
42 /// and [`Reader::exit_path`] is called
43 /// then the result is "/document/element"
44 ///
45 /// ```rust,ignore
46 /// reader.append_path(AppendPath::Element("document"));
47 /// reader.append_path(AppendPath::Element("element"));
48 /// reader.append_path(AppendPath::NamedAttr("my_attr"));
49 /// assert_eq!(reader.path(), "/document/element:my_attr");
50 ///
51 /// reader.exit_path();
52 /// assert_eq!(reader.path(), "/document/element");
53 ///
54 /// ```
55 ///
56 pub fn exit_path(&mut self) {
57 while let Some(ch) = self.path.pop() {
58 if matches!(ch, '/' | ':') {
59 return;
60 }
61 }
62 }
63}