namespace_set.rs

  1use std::collections::BTreeMap;
  2use std::cell::RefCell;
  3use std::rc::Rc;
  4
  5
  6#[derive(Clone, Debug, PartialEq, Eq)]
  7pub struct NamespaceSet {
  8    parent: RefCell<Option<Rc<NamespaceSet>>>,
  9    namespaces: BTreeMap<Option<String>, String>,
 10}
 11
 12impl Default for NamespaceSet {
 13    fn default() -> Self {
 14        NamespaceSet {
 15            parent: RefCell::new(None),
 16            namespaces: BTreeMap::new(),
 17        }
 18    }
 19}
 20
 21impl NamespaceSet {
 22    pub fn declared_ns(&self) -> &BTreeMap<Option<String>, String> {
 23        &self.namespaces
 24    }
 25    
 26    pub fn get(&self, prefix: &Option<String>) -> Option<String> {
 27        match self.namespaces.get(prefix) {
 28            Some(ns) => Some(ns.clone()),
 29            None => match *self.parent.borrow() {
 30                None => None,
 31                Some(ref parent) => parent.get(prefix)
 32            },
 33        }
 34    }
 35
 36    pub fn has<NS: AsRef<str>>(&self, prefix: &Option<String>, wanted_ns: NS) -> bool {
 37        match self.namespaces.get(prefix) {
 38            Some(ns) =>
 39                ns == wanted_ns.as_ref(),
 40            None => match *self.parent.borrow() {
 41                None =>
 42                    false,
 43                Some(ref parent) =>
 44                    parent.has(prefix, wanted_ns),
 45            },
 46        }
 47    }
 48
 49    pub fn set_parent(&self, parent: Rc<NamespaceSet>) {
 50        let mut parent_ns = self.parent.borrow_mut();
 51        let new_set = parent;
 52        *parent_ns = Some(new_set);
 53    }
 54
 55}
 56
 57impl From<BTreeMap<Option<String>, String>> for NamespaceSet {
 58    fn from(namespaces: BTreeMap<Option<String>, String>) -> Self {
 59        NamespaceSet {
 60            parent: RefCell::new(None),
 61            namespaces: namespaces,
 62        }
 63    }
 64}
 65
 66impl From<Option<String>> for NamespaceSet {
 67    fn from(namespace: Option<String>) -> Self {
 68        match namespace {
 69            None => Self::default(),
 70            Some(namespace) => Self::from(namespace),
 71        }
 72    }
 73}
 74
 75impl From<String> for NamespaceSet {
 76    fn from(namespace: String) -> Self {
 77        let mut namespaces = BTreeMap::new();
 78        namespaces.insert(None, namespace);
 79
 80        NamespaceSet {
 81            parent: RefCell::new(None),
 82            namespaces: namespaces,
 83        }
 84    }
 85}
 86
 87impl From<(Option<String>, String)> for NamespaceSet {
 88    fn from(prefix_namespace: (Option<String>, String)) -> Self {
 89        let (prefix, namespace) = prefix_namespace;
 90        let mut namespaces = BTreeMap::new();
 91        namespaces.insert(prefix, namespace);
 92
 93        NamespaceSet {
 94            parent: RefCell::new(None),
 95            namespaces: namespaces,
 96        }
 97    }
 98}
 99
100impl From<(String, String)> for NamespaceSet {
101    fn from(prefix_namespace: (String, String)) -> Self {
102        let (prefix, namespace) = prefix_namespace;
103        Self::from((Some(prefix), namespace))
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110    use std::rc::Rc;
111
112    #[test]
113    fn get_has() {
114        let namespaces = NamespaceSet::from("foo".to_owned());
115        assert_eq!(namespaces.get(&None), Some("foo".to_owned()));
116        assert!(namespaces.has(&None, "foo"));
117    }
118
119    #[test]
120    fn get_has_prefixed() {
121        let namespaces = NamespaceSet::from(("x".to_owned(), "bar".to_owned()));
122        assert_eq!(namespaces.get(&Some("x".to_owned())), Some("bar".to_owned()));
123        assert!(namespaces.has(&Some("x".to_owned()), "bar"));
124    }
125
126    #[test]
127    fn get_has_recursive() {
128        let mut parent = NamespaceSet::from("foo".to_owned());
129        for _ in 0..1000 {
130            let namespaces = NamespaceSet::default();
131            namespaces.set_parent(Rc::new(parent));
132            assert_eq!(namespaces.get(&None), Some("foo".to_owned()));
133            assert!(namespaces.has(&None, "foo"));
134            parent = namespaces;
135        }
136    }
137
138    #[test]
139    fn get_has_prefixed_recursive() {
140        let mut parent = NamespaceSet::from(("x".to_owned(), "bar".to_owned()));
141        for _ in 0..1000 {
142            let namespaces = NamespaceSet::default();
143            namespaces.set_parent(Rc::new(parent));
144            assert_eq!(namespaces.get(&Some("x".to_owned())), Some("bar".to_owned()));
145            assert!(namespaces.has(&Some("x".to_owned()), "bar"));
146            parent = namespaces;
147        }
148    }
149
150}