diff --git a/src/convert.rs b/src/convert.rs index cabe86d..5340732 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -1,7 +1,5 @@ //! A module which exports a few traits for converting types to elements and attributes. -use element::{Element, ElementBuilder}; - /// A trait for types which can be converted to an attribute value. pub trait IntoAttributeValue { /// Turns this into an attribute string, or None if it shouldn't be added. diff --git a/src/element.rs b/src/element.rs index 88a048d..5db7727 100644 --- a/src/element.rs +++ b/src/element.rs @@ -11,7 +11,7 @@ use error::{Error, Result}; use quick_xml::Reader as EventReader; use quick_xml::Writer as EventWriter; -use quick_xml::events::{Event, BytesStart, BytesEnd, BytesText, BytesDecl}; +use quick_xml::events::{Event, BytesStart, BytesEnd, BytesDecl}; use std::io::BufRead; @@ -21,6 +21,7 @@ use std::slice; use convert::IntoAttributeValue; use namespace_set::NamespaceSet; +use node::Node; /// helper function to escape a `&[u8]` and replace all /// xml special characters (<, >, &, ', ") with their corresponding @@ -68,196 +69,6 @@ pub fn escape(raw: &[u8]) -> Cow<[u8]> { } } -/// A node in an element tree. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Node { - /// An `Element`. - Element(Element), - /// A text node. - Text(String), - /// A comment node. - Comment(String), -} - -impl Node { - /// Turns this into a reference to an `Element` if this is an element node. - /// Else this returns `None`. - /// - /// # Examples - /// - /// ```rust - /// use minidom::Node; - /// - /// let elm = Node::Element("".parse().unwrap()); - /// let txt = Node::Text("meow".to_owned()); - /// - /// assert_eq!(elm.as_element().unwrap().name(), "meow"); - /// assert_eq!(txt.as_element(), None); - /// ``` - pub fn as_element(&self) -> Option<&Element> { - match *self { - Node::Element(ref e) => Some(e), - Node::Text(_) => None, - Node::Comment(_) => None, - } - } - - /// Turns this into a mutable reference of an `Element` if this is an element node. - /// Else this returns `None`. - /// - /// # Examples - /// - /// ```rust - /// use minidom::Node; - /// - /// let mut elm = Node::Element("".parse().unwrap()); - /// let mut txt = Node::Text("meow".to_owned()); - /// - /// assert_eq!(elm.as_element_mut().unwrap().name(), "meow"); - /// assert_eq!(txt.as_element_mut(), None); - /// ``` - pub fn as_element_mut(&mut self) -> Option<&mut Element> { - match *self { - Node::Element(ref mut e) => Some(e), - Node::Text(_) => None, - Node::Comment(_) => None, - } - } - - /// Turns this into an `Element`, consuming self, if this is an element node. - /// Else this returns `None`. - /// - /// # Examples - /// - /// ```rust - /// use minidom::Node; - /// - /// let elm = Node::Element("".parse().unwrap()); - /// let txt = Node::Text("meow".to_owned()); - /// - /// assert_eq!(elm.into_element().unwrap().name(), "meow"); - /// assert_eq!(txt.into_element(), None); - /// ``` - pub fn into_element(self) -> Option { - match self { - Node::Element(e) => Some(e), - Node::Text(_) => None, - Node::Comment(_) => None, - } - } - - /// Turns this into an `&str` if this is a text node. - /// Else this returns `None`. - /// - /// # Examples - /// - /// ```rust - /// use minidom::Node; - /// - /// let elm = Node::Element("".parse().unwrap()); - /// let txt = Node::Text("meow".to_owned()); - /// - /// assert_eq!(elm.as_text(), None); - /// assert_eq!(txt.as_text().unwrap(), "meow"); - /// ``` - pub fn as_text(&self) -> Option<&str> { - match *self { - Node::Element(_) => None, - Node::Text(ref s) => Some(s), - Node::Comment(_) => None, - } - } - - /// Turns this into an `&mut String` if this is a text node. - /// Else this returns `None`. - /// - /// # Examples - /// - /// ```rust - /// use minidom::Node; - /// - /// let mut elm = Node::Element("".parse().unwrap()); - /// let mut txt = Node::Text("meow".to_owned()); - /// - /// assert_eq!(elm.as_text_mut(), None); - /// { - /// let text_mut = txt.as_text_mut().unwrap(); - /// assert_eq!(text_mut, "meow"); - /// text_mut.push_str("zies"); - /// assert_eq!(text_mut, "meowzies"); - /// } - /// assert_eq!(txt.as_text().unwrap(), "meowzies"); - /// ``` - pub fn as_text_mut(&mut self) -> Option<&mut String> { - match *self { - Node::Element(_) => None, - Node::Text(ref mut s) => Some(s), - Node::Comment(_) => None, - } - } - - /// Turns this into an `String`, consuming self, if this is a text node. - /// Else this returns `None`. - /// - /// # Examples - /// - /// ```rust - /// use minidom::Node; - /// - /// let elm = Node::Element("".parse().unwrap()); - /// let txt = Node::Text("meow".to_owned()); - /// - /// assert_eq!(elm.into_text(), None); - /// assert_eq!(txt.into_text().unwrap(), "meow"); - /// ``` - pub fn into_text(self) -> Option { - match self { - Node::Element(_) => None, - Node::Text(s) => Some(s), - Node::Comment(_) => None, - } - } - - fn write_to_inner(&self, writer: &mut EventWriter) -> Result<()>{ - match *self { - Node::Element(ref elmt) => elmt.write_to_inner(writer)?, - Node::Text(ref s) => { - writer.write_event(Event::Text(BytesText::from_plain_str(s)))?; - () - }, - Node::Comment(ref s) => { - writer.write_event(Event::Comment(BytesText::from_plain_str(s)))?; - () - }, - }; - - Ok(()) - } -} - -impl From for Node { - fn from(elm: Element) -> Node { - Node::Element(elm) - } -} - -impl From for Node { - fn from(s: String) -> Node { - Node::Text(s) - } -} - -impl<'a> From<&'a str> for Node { - fn from(s: &'a str) -> Node { - Node::Text(s.to_owned()) - } -} - -impl From for Node { - fn from(builder: ElementBuilder) -> Node { - Node::Element(builder.build()) - } -} #[derive(Clone, PartialEq, Eq, Debug)] /// A struct representing a DOM Element. diff --git a/src/lib.rs b/src/lib.rs index 20be49d..5ea7e70 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,10 +71,12 @@ extern crate failure; pub mod error; pub mod element; pub mod convert; +pub mod node; mod namespace_set; #[cfg(test)] mod tests; pub use error::{Error, Result}; -pub use element::{Element, Node, Children, ChildrenMut, ElementBuilder}; +pub use element::{Element, Children, ChildrenMut, ElementBuilder}; +pub use node::Node; pub use convert::IntoAttributeValue; diff --git a/src/node.rs b/src/node.rs new file mode 100644 index 0000000..7fe5dda --- /dev/null +++ b/src/node.rs @@ -0,0 +1,202 @@ +//! Provides the `Node` struct, which represents a node in the DOM. + +use std::io::Write; + +use quick_xml::Writer as EventWriter; +use quick_xml::events::{Event, BytesText}; + +use error::Result; + +use element::{Element, ElementBuilder}; + +/// A node in an element tree. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Node { + /// An `Element`. + Element(Element), + /// A text node. + Text(String), + /// A comment node. + Comment(String), +} + +impl Node { + /// Turns this into a reference to an `Element` if this is an element node. + /// Else this returns `None`. + /// + /// # Examples + /// + /// ```rust + /// use minidom::Node; + /// + /// let elm = Node::Element("".parse().unwrap()); + /// let txt = Node::Text("meow".to_owned()); + /// + /// assert_eq!(elm.as_element().unwrap().name(), "meow"); + /// assert_eq!(txt.as_element(), None); + /// ``` + pub fn as_element(&self) -> Option<&Element> { + match *self { + Node::Element(ref e) => Some(e), + Node::Text(_) => None, + Node::Comment(_) => None, + } + } + + /// Turns this into a mutable reference of an `Element` if this is an element node. + /// Else this returns `None`. + /// + /// # Examples + /// + /// ```rust + /// use minidom::Node; + /// + /// let mut elm = Node::Element("".parse().unwrap()); + /// let mut txt = Node::Text("meow".to_owned()); + /// + /// assert_eq!(elm.as_element_mut().unwrap().name(), "meow"); + /// assert_eq!(txt.as_element_mut(), None); + /// ``` + pub fn as_element_mut(&mut self) -> Option<&mut Element> { + match *self { + Node::Element(ref mut e) => Some(e), + Node::Text(_) => None, + Node::Comment(_) => None, + } + } + + /// Turns this into an `Element`, consuming self, if this is an element node. + /// Else this returns `None`. + /// + /// # Examples + /// + /// ```rust + /// use minidom::Node; + /// + /// let elm = Node::Element("".parse().unwrap()); + /// let txt = Node::Text("meow".to_owned()); + /// + /// assert_eq!(elm.into_element().unwrap().name(), "meow"); + /// assert_eq!(txt.into_element(), None); + /// ``` + pub fn into_element(self) -> Option { + match self { + Node::Element(e) => Some(e), + Node::Text(_) => None, + Node::Comment(_) => None, + } + } + + /// Turns this into an `&str` if this is a text node. + /// Else this returns `None`. + /// + /// # Examples + /// + /// ```rust + /// use minidom::Node; + /// + /// let elm = Node::Element("".parse().unwrap()); + /// let txt = Node::Text("meow".to_owned()); + /// + /// assert_eq!(elm.as_text(), None); + /// assert_eq!(txt.as_text().unwrap(), "meow"); + /// ``` + pub fn as_text(&self) -> Option<&str> { + match *self { + Node::Element(_) => None, + Node::Text(ref s) => Some(s), + Node::Comment(_) => None, + } + } + + /// Turns this into an `&mut String` if this is a text node. + /// Else this returns `None`. + /// + /// # Examples + /// + /// ```rust + /// use minidom::Node; + /// + /// let mut elm = Node::Element("".parse().unwrap()); + /// let mut txt = Node::Text("meow".to_owned()); + /// + /// assert_eq!(elm.as_text_mut(), None); + /// { + /// let text_mut = txt.as_text_mut().unwrap(); + /// assert_eq!(text_mut, "meow"); + /// text_mut.push_str("zies"); + /// assert_eq!(text_mut, "meowzies"); + /// } + /// assert_eq!(txt.as_text().unwrap(), "meowzies"); + /// ``` + pub fn as_text_mut(&mut self) -> Option<&mut String> { + match *self { + Node::Element(_) => None, + Node::Text(ref mut s) => Some(s), + Node::Comment(_) => None, + } + } + + /// Turns this into an `String`, consuming self, if this is a text node. + /// Else this returns `None`. + /// + /// # Examples + /// + /// ```rust + /// use minidom::Node; + /// + /// let elm = Node::Element("".parse().unwrap()); + /// let txt = Node::Text("meow".to_owned()); + /// + /// assert_eq!(elm.into_text(), None); + /// assert_eq!(txt.into_text().unwrap(), "meow"); + /// ``` + pub fn into_text(self) -> Option { + match self { + Node::Element(_) => None, + Node::Text(s) => Some(s), + Node::Comment(_) => None, + } + } + + #[doc(hidden)] + pub(crate) fn write_to_inner(&self, writer: &mut EventWriter) -> Result<()>{ + match *self { + Node::Element(ref elmt) => elmt.write_to_inner(writer)?, + Node::Text(ref s) => { + writer.write_event(Event::Text(BytesText::from_plain_str(s)))?; + () + }, + Node::Comment(ref s) => { + writer.write_event(Event::Comment(BytesText::from_plain_str(s)))?; + () + }, + }; + + Ok(()) + } +} + +impl From for Node { + fn from(elm: Element) -> Node { + Node::Element(elm) + } +} + +impl From for Node { + fn from(s: String) -> Node { + Node::Text(s) + } +} + +impl<'a> From<&'a str> for Node { + fn from(s: &'a str) -> Node { + Node::Text(s.to_owned()) + } +} + +impl From for Node { + fn from(builder: ElementBuilder) -> Node { + Node::Element(builder.build()) + } +}