From 362ceae922a678e5f66f41245fc560451abaf2ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Sat, 9 Nov 2019 01:26:48 +0100 Subject: [PATCH] minidom: Add NSChoice enum to extent element.is and .has_ns API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Maxime “pep” Buquet --- minidom-rs/CHANGELOG.md | 1 + minidom-rs/src/element.rs | 32 ++++++++++++++++++++++++----- minidom-rs/src/lib.rs | 1 + minidom-rs/src/namespace_set.rs | 36 ++++++++++++++++++++++++++++++--- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/minidom-rs/CHANGELOG.md b/minidom-rs/CHANGELOG.md index 275c0e69884a0b3638462e6353d571fe7390aad0..b1dec9c343d642f2c313af34cd2a953a1862f22e 100644 --- a/minidom-rs/CHANGELOG.md +++ b/minidom-rs/CHANGELOG.md @@ -1,6 +1,7 @@ Version XXX, released YYY: * Changes * Update edition to 2018 + * Add NSChoice enum to allow comparing NSs differently * Fixes * Update old CI configuration with newer Rust images Version 0.11.1, released 2019-09-06: diff --git a/minidom-rs/src/element.rs b/minidom-rs/src/element.rs index 199c620ef2c0d7596b3513998200988268a3ba0e..fe8e298c499c0fabb5c753a8252f9219c45f8394 100644 --- a/minidom-rs/src/element.rs +++ b/minidom-rs/src/element.rs @@ -2,7 +2,7 @@ use crate::convert::IntoAttributeValue; use crate::error::{Error, Result}; -use crate::namespace_set::NamespaceSet; +use crate::namespace_set::{NamespaceSet, NSChoice}; use crate::node::Node; use std::collections::{btree_map, BTreeMap}; @@ -246,7 +246,7 @@ impl Element { /// # Examples /// /// ```rust - /// use minidom::Element; + /// use minidom::{Element, NSChoice}; /// /// let elem = Element::builder("name").ns("namespace").build(); /// @@ -254,8 +254,19 @@ impl Element { /// assert_eq!(elem.is("name", "wrong"), false); /// assert_eq!(elem.is("wrong", "namespace"), false); /// assert_eq!(elem.is("wrong", "wrong"), false); + /// + /// assert_eq!(elem.is("name", NSChoice::None), false); + /// assert_eq!(elem.is("name", NSChoice::OneOf("namespace")), true); + /// assert_eq!(elem.is("name", NSChoice::OneOf("foo")), false); + /// assert_eq!(elem.is("name", NSChoice::AnyOf(vec!["foo", "namespace"])), true); + /// assert_eq!(elem.is("name", NSChoice::Any), true); + /// + /// let elem2 = Element::builder("name").build(); + /// + /// assert_eq!(elem2.is("name", NSChoice::None), true); + /// assert_eq!(elem2.is("name", NSChoice::Any), true); /// ``` - pub fn is, NS: AsRef>(&self, name: N, namespace: NS) -> bool { + pub fn is<'a, N: AsRef, NS: Into>>(&self, name: N, namespace: NS) -> bool { self.name == name.as_ref() && self.has_ns(namespace) } @@ -264,14 +275,25 @@ impl Element { /// # Examples /// /// ```rust - /// use minidom::Element; + /// use minidom::{Element, NSChoice}; /// /// let elem = Element::builder("name").ns("namespace").build(); /// /// assert_eq!(elem.has_ns("namespace"), true); /// assert_eq!(elem.has_ns("wrong"), false); + /// + /// assert_eq!(elem.has_ns(NSChoice::None), false); + /// assert_eq!(elem.has_ns(NSChoice::OneOf("namespace")), true); + /// assert_eq!(elem.has_ns(NSChoice::OneOf("foo")), false); + /// assert_eq!(elem.has_ns(NSChoice::AnyOf(vec!["foo", "namespace"])), true); + /// assert_eq!(elem.has_ns(NSChoice::Any), true); + /// + /// let elem2 = Element::builder("name").build(); + /// + /// assert_eq!(elem2.has_ns(NSChoice::None), true); + /// assert_eq!(elem2.has_ns(NSChoice::Any), true); /// ``` - pub fn has_ns>(&self, namespace: NS) -> bool { + pub fn has_ns<'a, NS: Into>>(&self, namespace: NS) -> bool { self.namespaces.has(&self.prefix, namespace) } diff --git a/minidom-rs/src/lib.rs b/minidom-rs/src/lib.rs index 2fd9901007af4a46b929461b30c70ee282624e36..a12b6b7de0f449f501f2974702d5430bc22d3f3f 100644 --- a/minidom-rs/src/lib.rs +++ b/minidom-rs/src/lib.rs @@ -77,5 +77,6 @@ mod tests; pub use convert::IntoAttributeValue; pub use element::{Children, ChildrenMut, Element, ElementBuilder}; +pub use namespace_set::NSChoice; pub use error::{Error, Result}; pub use node::Node; diff --git a/minidom-rs/src/namespace_set.rs b/minidom-rs/src/namespace_set.rs index 857336fe40103a285ed4b238fff73f13fc99d95b..7efdf8b9ccb8e525706d35825178794727f5d81a 100644 --- a/minidom-rs/src/namespace_set.rs +++ b/minidom-rs/src/namespace_set.rs @@ -3,6 +3,25 @@ use std::collections::BTreeMap; use std::fmt; use std::rc::Rc; +#[derive(Clone, PartialEq, Eq, Debug)] +/// Use to compare namespaces +pub enum NSChoice<'a> { + /// The element must have no namespace + None, + /// The element's namespace must match the specified namespace + OneOf(&'a str), + /// The element's namespace must be in the specified vector + AnyOf(Vec<&'a str>), + /// The element can have any namespace, or no namespace + Any, +} + +impl<'a> From<&'a str> for NSChoice<'a> { + fn from(ns: &'a str) -> NSChoice<'a> { + NSChoice::OneOf(ns) + } +} + #[derive(Clone, PartialEq, Eq)] pub struct NamespaceSet { parent: RefCell>>, @@ -51,11 +70,22 @@ impl NamespaceSet { } } - pub fn has>(&self, prefix: &Option, wanted_ns: NS) -> bool { + fn compare_ns<'a>(&self, ns: Option<&str>, wanted_ns: NSChoice<'a>) -> bool { + match (ns, wanted_ns) { + (None, NSChoice::None) | (None, NSChoice::Any) => true, + (None, NSChoice::OneOf(_)) | (None, NSChoice::AnyOf(_)) => false, + (Some(_), NSChoice::None) => false, + (Some(_), NSChoice::Any) => true, + (Some(ns), NSChoice::OneOf(wanted_ns)) => ns == wanted_ns, + (Some(ns), NSChoice::AnyOf(wanted_nss)) => wanted_nss.iter().any(|w| &ns == w), + } + } + + pub fn has<'a, NS: Into>>(&self, prefix: &Option, wanted_ns: NS) -> bool { match self.namespaces.get(prefix) { - Some(ns) => ns == wanted_ns.as_ref(), + Some(ns) => self.compare_ns(Some(ns), wanted_ns.into()), None => match *self.parent.borrow() { - None => false, + None => self.compare_ns(None, wanted_ns.into()), Some(ref parent) => parent.has(prefix, wanted_ns), }, }