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}