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