node.rs

  1// Copyright (c) 2020 lumi <lumi@pew.im>
  2// Copyright (c) 2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  3// Copyright (c) 2020 Maxime “pep” Buquet <pep@bouah.net>
  4//
  5// This Source Code Form is subject to the terms of the Mozilla Public
  6// License, v. 2.0. If a copy of the MPL was not distributed with this
  7// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8
  9//! Provides the `Node` struct, which represents a node in the DOM.
 10
 11use crate::element::{Element, ElementBuilder, ItemWriter};
 12use crate::error::Result;
 13
 14use rxml::writer::Item;
 15
 16use std::io::Write;
 17
 18/// A node in an element tree.
 19#[derive(Clone, Debug, Eq)]
 20pub enum Node {
 21    /// An `Element`.
 22    Element(Element),
 23    /// A text node.
 24    Text(String),
 25}
 26
 27impl Node {
 28    /// Turns this into a reference to an `Element` if this is an element node.
 29    /// Else this returns `None`.
 30    ///
 31    /// # Examples
 32    ///
 33    /// ```rust
 34    /// use minidom::Node;
 35    ///
 36    /// let elm = Node::Element("<meow xmlns=\"ns1\"/>".parse().unwrap());
 37    /// let txt = Node::Text("meow".to_owned());
 38    ///
 39    /// assert_eq!(elm.as_element().unwrap().name(), "meow");
 40    /// assert_eq!(txt.as_element(), None);
 41    /// ```
 42    pub fn as_element(&self) -> Option<&Element> {
 43        match *self {
 44            Node::Element(ref e) => Some(e),
 45            Node::Text(_) => None,
 46        }
 47    }
 48
 49    /// Turns this into a mutable reference of an `Element` if this is an element node.
 50    /// Else this returns `None`.
 51    ///
 52    /// # Examples
 53    ///
 54    /// ```rust
 55    /// use minidom::Node;
 56    ///
 57    /// let mut elm = Node::Element("<meow xmlns=\"ns1\"/>".parse().unwrap());
 58    /// let mut txt = Node::Text("meow".to_owned());
 59    ///
 60    /// assert_eq!(elm.as_element_mut().unwrap().name(), "meow");
 61    /// assert_eq!(txt.as_element_mut(), None);
 62    /// ```
 63    pub fn as_element_mut(&mut self) -> Option<&mut Element> {
 64        match *self {
 65            Node::Element(ref mut e) => Some(e),
 66            Node::Text(_) => None,
 67        }
 68    }
 69
 70    /// Turns this into an `Element`, consuming self, if this is an element node.
 71    /// Else this returns `None`.
 72    ///
 73    /// # Examples
 74    ///
 75    /// ```rust
 76    /// use minidom::Node;
 77    ///
 78    /// let elm = Node::Element("<meow xmlns=\"ns1\"/>".parse().unwrap());
 79    /// let txt = Node::Text("meow".to_owned());
 80    ///
 81    /// assert_eq!(elm.into_element().unwrap().name(), "meow");
 82    /// assert_eq!(txt.into_element(), None);
 83    /// ```
 84    pub fn into_element(self) -> Option<Element> {
 85        match self {
 86            Node::Element(e) => Some(e),
 87            Node::Text(_) => None,
 88        }
 89    }
 90
 91    /// Turns this into an `&str` if this is a text node.
 92    /// Else this returns `None`.
 93    ///
 94    /// # Examples
 95    ///
 96    /// ```rust
 97    /// use minidom::Node;
 98    ///
 99    /// let elm = Node::Element("<meow xmlns=\"ns1\"/>".parse().unwrap());
100    /// let txt = Node::Text("meow".to_owned());
101    ///
102    /// assert_eq!(elm.as_text(), None);
103    /// assert_eq!(txt.as_text().unwrap(), "meow");
104    /// ```
105    pub fn as_text(&self) -> Option<&str> {
106        match *self {
107            Node::Element(_) => None,
108            Node::Text(ref s) => Some(s),
109        }
110    }
111
112    /// Turns this into an `&mut String` if this is a text node.
113    /// Else this returns `None`.
114    ///
115    /// # Examples
116    ///
117    /// ```rust
118    /// use minidom::Node;
119    ///
120    /// let mut elm = Node::Element("<meow xmlns=\"ns1\"/>".parse().unwrap());
121    /// let mut txt = Node::Text("meow".to_owned());
122    ///
123    /// assert_eq!(elm.as_text_mut(), None);
124    /// {
125    ///     let text_mut = txt.as_text_mut().unwrap();
126    ///     assert_eq!(text_mut, "meow");
127    ///     text_mut.push_str("zies");
128    ///     assert_eq!(text_mut, "meowzies");
129    /// }
130    /// assert_eq!(txt.as_text().unwrap(), "meowzies");
131    /// ```
132    pub fn as_text_mut(&mut self) -> Option<&mut String> {
133        match *self {
134            Node::Element(_) => None,
135            Node::Text(ref mut s) => Some(s),
136        }
137    }
138
139    /// Turns this into an `String`, consuming self, if this is a text node.
140    /// Else this returns `None`.
141    ///
142    /// # Examples
143    ///
144    /// ```rust
145    /// use minidom::Node;
146    ///
147    /// let elm = Node::Element("<meow xmlns=\"ns1\"/>".parse().unwrap());
148    /// let txt = Node::Text("meow".to_owned());
149    ///
150    /// assert_eq!(elm.into_text(), None);
151    /// assert_eq!(txt.into_text().unwrap(), "meow");
152    /// ```
153    pub fn into_text(self) -> Option<String> {
154        match self {
155            Node::Element(_) => None,
156            Node::Text(s) => Some(s),
157        }
158    }
159
160    #[doc(hidden)]
161    pub(crate) fn write_to_inner<W: Write>(&self, writer: &mut ItemWriter<W>) -> Result<()> {
162        match self {
163            Node::Element(elmt) => elmt.write_to_inner(writer)?,
164            Node::Text(s) => {
165                writer.write(Item::Text(s))?;
166            }
167        }
168
169        Ok(())
170    }
171}
172
173impl<I> From<I> for Node
174where
175    I: Into<Element>,
176{
177    fn from(elm: I) -> Node {
178        Node::Element(elm.into())
179    }
180}
181
182impl From<String> for Node {
183    fn from(s: String) -> Node {
184        Node::Text(s)
185    }
186}
187
188impl<'a> From<&'a str> for Node {
189    fn from(s: &'a str) -> Node {
190        Node::Text(s.to_owned())
191    }
192}
193
194impl From<ElementBuilder> for Node {
195    fn from(builder: ElementBuilder) -> Node {
196        Node::Element(builder.build())
197    }
198}
199
200impl PartialEq for Node {
201    fn eq(&self, other: &Self) -> bool {
202        match (self, other) {
203            (Node::Element(elem1), Node::Element(elem2)) => elem1 == elem2,
204            (Node::Text(text1), Node::Text(text2)) => text1 == text2,
205            _ => false,
206        }
207    }
208}