svd_parser/
elementext.rs

1//! SVD Element Extensions.
2//! This module is extends roxmltree::Element objects with convenience methods
3
4use roxmltree::Node;
5
6use super::types::BoolParse;
7use super::{Parse, SVDError, SVDErrorAt};
8
9/// Defines extensions for implementation over roxmltree::Node
10pub trait ElementExt {
11    fn get_child<K>(&self, k: K) -> Option<Node>
12    where
13        K: AsRef<str>;
14    fn get_child_text_opt<K>(&self, k: K) -> Result<Option<String>, SVDErrorAt>
15    where
16        K: AsRef<str>;
17    fn get_child_text<K>(&self, k: K) -> Result<String, SVDErrorAt>
18    where
19        K: AsRef<str>;
20
21    fn get_text(&self) -> Result<&str, SVDErrorAt>;
22
23    fn get_child_elem(&self, n: &str) -> Result<Node, SVDErrorAt>;
24    fn get_child_u32(&self, n: &str) -> Result<u32, SVDErrorAt>;
25    fn get_child_u64(&self, n: &str) -> Result<u64, SVDErrorAt>;
26    fn get_child_bool(&self, n: &str) -> Result<bool, SVDErrorAt>;
27
28    fn debug(&self);
29}
30
31/// Implements extensions for roxmltree::Node
32impl ElementExt for Node<'_, '_> {
33    fn get_child<K>(&self, k: K) -> Option<Node>
34    where
35        K: AsRef<str>,
36    {
37        self.children().find(|&c| c.has_tag_name(k.as_ref()))
38    }
39    fn get_child_text_opt<K>(&self, k: K) -> Result<Option<String>, SVDErrorAt>
40    where
41        K: AsRef<str>,
42    {
43        if let Some(child) = self.get_child(k) {
44            match child.get_text() {
45                Err(e) => {
46                    // if tag is empty just ignore it
47                    match e {
48                        SVDErrorAt {
49                            error: SVDError::EmptyTag(_),
50                            ..
51                        } => Ok(None),
52                        _ => Err(e),
53                    }
54                }
55                Ok(s) => Ok(Some(s.to_string())),
56            }
57        } else {
58            Ok(None)
59        }
60    }
61    fn get_child_text<K>(&self, k: K) -> Result<String, SVDErrorAt>
62    where
63        K: AsRef<str>,
64    {
65        let k = k.as_ref();
66        self.get_child_text_opt(k)?
67            .ok_or_else(|| SVDError::MissingTag(k.to_string()).at(self.id()))
68    }
69
70    /// Get text contained by an XML Element
71    fn get_text(&self) -> Result<&str, SVDErrorAt> {
72        match self.text() {
73            // TODO: return error on `strict`
74            Some(s) => Ok(s.trim()),
75            // FIXME: Doesn't look good because SVDError doesn't format by itself. We already
76            // capture the element and this information can be used for getting the name
77            // This would fix ParseError
78            None => Err(SVDError::EmptyTag(self.tag_name().name().to_string()).at(self.id())),
79        }
80    }
81
82    /// Get a named child element from an XML Element
83    fn get_child_elem(&self, n: &str) -> Result<Node, SVDErrorAt> {
84        self.get_child(n)
85            .ok_or_else(|| SVDError::MissingTag(n.to_string()).at(self.id()))
86    }
87
88    /// Get a u32 value from a named child element
89    fn get_child_u32(&self, n: &str) -> Result<u32, SVDErrorAt> {
90        let s = self.get_child_elem(n)?;
91        u32::parse(&s, &())
92    }
93
94    /// Get a u64 value from a named child element
95    fn get_child_u64(&self, n: &str) -> Result<u64, SVDErrorAt> {
96        let s = self.get_child_elem(n)?;
97        u64::parse(&s, &())
98    }
99
100    /// Get a bool value from a named child element
101    fn get_child_bool(&self, n: &str) -> Result<bool, SVDErrorAt> {
102        let s = self.get_child_elem(n)?;
103        BoolParse::parse(&s, &())
104    }
105
106    fn debug(&self) {
107        let name = self.tag_name().name();
108        println!("<{}>", name);
109        for c in self.children() {
110            println!("{}: {:?}", c.tag_name().name(), c.text())
111        }
112        println!("</{}>", name);
113    }
114}