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}