From 1c953eac65faeda0e083aacc9ea6841348f4c0c6 Mon Sep 17 00:00:00 2001 From: Daniel Dulaney Date: Sat, 1 Jun 2019 13:26:22 -0400 Subject: [PATCH 1/5] Added API and failing tests for registered_namespaces - New Element::registered_namespaces method - New failing tests --- src/dom.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/dom.rs b/src/dom.rs index 947f460..a310ec5 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -262,6 +262,12 @@ impl<'d> Element<'d> { ) } + /// View all the namespaces that are registered on this element, without + /// walking up the tree. + pub fn registered_namespaces(&self) -> Vec> { + unimplemented!(); + } + /// Retrieve all namespaces that are in scope, recursively walking /// up the document tree. pub fn namespaces_in_scope(&self) -> Vec> { @@ -1061,6 +1067,49 @@ mod test { assert_eq!("uri2", ns.uri()); } + #[test] + fn elements_get_multiple_registered_namespaces() { + let package = Package::new(); + let doc = package.as_document(); + + let element = doc.create_element("alpha"); + element.register_prefix("a", "uria"); + element.register_prefix("b", "urib"); + element.register_prefix("c", "uric"); + + let nses = element.registered_namespaces(); + assert_eq!(3, nses.len()); + + let a_ns = nses.iter().find(|ns| ns.prefix() == "a").unwrap(); + assert_eq!("uria", a_ns.uri()); + + let b_ns = nses.iter().find(|ns| ns.prefix() == "b").unwrap(); + assert_eq!("urib", b_ns.uri()); + + let b_ns = nses.iter().find(|ns| ns.prefix() == "b").unwrap(); + assert_eq!("urib", b_ns.uri()); + } + + #[test] + fn elements_get_only_own_registered_namespace() { + let package = Package::new(); + let doc = package.as_document(); + + let parent = doc.create_element("parent"); + parent.register_prefix("parentprefix", "uri1"); + + let child = doc.create_element("child"); + child.register_prefix("ownprefix", "uri2"); + + parent.append_child(child); + + let nses = child.registered_namespaces(); + assert_eq!(1, nses.len()); + + let ns = nses.iter().find(|ns| ns.prefix() == "ownprefix").unwrap(); + assert_eq!("uri2", ns.uri()); + } + #[test] fn attributes_belong_to_a_document() { let package = Package::new(); From d0d6fc37a5bab41e0bf478a72bde3f4a462e59b3 Mon Sep 17 00:00:00 2001 From: Daniel Dulaney Date: Sat, 1 Jun 2019 15:14:15 -0400 Subject: [PATCH 2/5] Implemented registered_namespaces - Changed the API to return an impl Iterator (allows the consumer to iterate efficiently or convert to a Vec at their option) - Changed the tests from the previous commit to match the new API - Added an implementation in raw::Connections --- src/dom.rs | 11 ++++++----- src/raw.rs | 8 ++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/dom.rs b/src/dom.rs index a310ec5..61ddd27 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -264,8 +264,9 @@ impl<'d> Element<'d> { /// View all the namespaces that are registered on this element, without /// walking up the tree. - pub fn registered_namespaces(&self) -> Vec> { - unimplemented!(); + pub fn registered_namespaces(&self) -> impl Iterator> { + self.document.connections.element_registered_namespaces(self.node) + .map(|(prefix, uri)| Namespace { prefix, uri }) } /// Retrieve all namespaces that are in scope, recursively walking @@ -671,7 +672,7 @@ impl<'d> From> for ChildOfElement<'d> { #[cfg(test)] mod test { use super::super::{Package,QName}; - use super::{ChildOfRoot,ChildOfElement,ParentOfChild}; + use super::{ChildOfRoot,ChildOfElement,ParentOfChild,Namespace}; macro_rules! assert_qname_eq( ($l:expr, $r:expr) => (assert_eq!(Into::::into($l), $r.into())); @@ -1077,7 +1078,7 @@ mod test { element.register_prefix("b", "urib"); element.register_prefix("c", "uric"); - let nses = element.registered_namespaces(); + let nses: Vec = element.registered_namespaces().collect(); assert_eq!(3, nses.len()); let a_ns = nses.iter().find(|ns| ns.prefix() == "a").unwrap(); @@ -1103,7 +1104,7 @@ mod test { parent.append_child(child); - let nses = child.registered_namespaces(); + let nses: Vec = child.registered_namespaces().collect(); assert_eq!(1, nses.len()); let ns = nses.iter().find(|ns| ns.prefix() == "ownprefix").unwrap(); diff --git a/src/raw.rs b/src/raw.rs index 219bd01..e63ef1f 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -771,6 +771,14 @@ impl Connections { None } + pub fn element_registered_namespaces(&self, element: *mut Element) + -> impl Iterator + { + let element_ref = unsafe { &*element }; + + element_ref.prefix_to_namespace.iter().map(|(p, n)| (p.as_slice(), n.as_slice())) + } + pub fn element_namespaces_in_scope(&self, element: *mut Element) -> NamespacesInScope { From 0b11cd8c3aa29baec585aedc228da3ece4f75b59 Mon Sep 17 00:00:00 2001 From: Daniel Dulaney Date: Sat, 1 Jun 2019 16:01:16 -0400 Subject: [PATCH 3/5] Added unregister_prefix API with failing test --- src/dom.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/dom.rs b/src/dom.rs index 61ddd27..010a9dd 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -246,6 +246,15 @@ impl<'d> Element<'d> { self.document.storage.element_register_prefix(self.node, prefix, namespace_uri); } + /// Unregister a prefix on this element. This does not check for prefix + /// registrations on any ancestor elements. + /// + /// If the prefix does not exist, returns `None`. Otherwise, returns the + /// `Namespace` that was removed. + pub fn unregister_prefix(&self, prefix: &str) -> Option> { + unimplemented!() + } + /// Recursively resolve the prefix to a namespace URI. pub fn namespace_uri_for_prefix(&self, prefix: &str) -> Option<&'d str> { self.document.connections.element_namespace_uri_for_prefix(self.node, prefix) @@ -1111,6 +1120,39 @@ mod test { assert_eq!("uri2", ns.uri()); } + #[test] + fn elements_unregister_prefixes() { + let package = Package::new(); + let doc = package.as_document(); + + let el = doc.create_element("alpha"); + el.register_prefix("a", "uri_a"); + el.register_prefix("b", "uri_b"); + el.register_prefix("c", "uri_c"); + + assert!(el.registered_namespaces().find(|ns| ns.prefix == "a").is_some()); + assert!(el.registered_namespaces().find(|ns| ns.prefix == "b").is_some()); + assert!(el.registered_namespaces().find(|ns| ns.prefix == "c").is_some()); + + el.unregister_prefix("a"); + + assert!(el.registered_namespaces().find(|ns| ns.prefix == "a").is_none()); + assert!(el.registered_namespaces().find(|ns| ns.prefix == "b").is_some()); + assert!(el.registered_namespaces().find(|ns| ns.prefix == "c").is_some()); + + el.unregister_prefix("c"); + + assert!(el.registered_namespaces().find(|ns| ns.prefix == "a").is_none()); + assert!(el.registered_namespaces().find(|ns| ns.prefix == "b").is_some()); + assert!(el.registered_namespaces().find(|ns| ns.prefix == "c").is_none()); + + el.unregister_prefix("b"); + + assert!(el.registered_namespaces().find(|ns| ns.prefix == "a").is_none()); + assert!(el.registered_namespaces().find(|ns| ns.prefix == "b").is_none()); + assert!(el.registered_namespaces().find(|ns| ns.prefix == "c").is_none()); + } + #[test] fn attributes_belong_to_a_document() { let package = Package::new(); From 0fed5350b8962f26de2d3224cf1b902fc2989209 Mon Sep 17 00:00:00 2001 From: Daniel Dulaney Date: Sat, 1 Jun 2019 16:08:50 -0400 Subject: [PATCH 4/5] Added remove_entry to LazyHashMap Just a thin wrapper over std's HashMap::remove_entry --- src/lazy_hash_map.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lazy_hash_map.rs b/src/lazy_hash_map.rs index 0183624..5b752ac 100644 --- a/src/lazy_hash_map.rs +++ b/src/lazy_hash_map.rs @@ -39,6 +39,13 @@ impl LazyHashMap }) } + pub fn remove_entry(&mut self, key: &Q) -> Option<(K, V)> + where K: Borrow, + Q: Hash + Eq + { + self.map.as_mut().and_then(|m| m.remove_entry(key)) + } + pub fn iter(&self) -> Iter { Iter(self.map.as_ref().map(|m| m.iter())) } From df151febd13c0c7d0e8814999ccdb33892636c07 Mon Sep 17 00:00:00 2001 From: Daniel Dulaney Date: Sat, 1 Jun 2019 16:21:12 -0400 Subject: [PATCH 5/5] Implemented unregister_prefix - Added a new raw::Storage::element_unregister_prefix private method --- src/dom.rs | 3 ++- src/raw.rs | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/dom.rs b/src/dom.rs index 010a9dd..4991720 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -252,7 +252,8 @@ impl<'d> Element<'d> { /// If the prefix does not exist, returns `None`. Otherwise, returns the /// `Namespace` that was removed. pub fn unregister_prefix(&self, prefix: &str) -> Option> { - unimplemented!() + self.document.storage.element_unregister_prefix(self.node, prefix) + .map(|(prefix, uri)| Namespace { prefix, uri }) } /// Recursively resolve the prefix to a namespace URI. diff --git a/src/raw.rs b/src/raw.rs index e63ef1f..bbdb747 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -381,6 +381,11 @@ impl Storage { element_r.prefix_to_namespace.insert(prefix, namespace_uri); } + pub fn element_unregister_prefix(&self, element: *mut Element, prefix: &str) -> Option<(&str, &str)> { + let element_r = unsafe { &mut * element }; + element_r.prefix_to_namespace.remove_entry(prefix).map(|(p, u)| (p.as_slice(), u.as_slice())) + } + pub fn element_set_default_namespace_uri(&self, element: *mut Element, namespace_uri: Option<&str>) { let namespace_uri = namespace_uri.map(|p| self.intern(p)); let element_r = unsafe { &mut * element };