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