1use core::{fmt, str};
2use std::borrow::Cow;
3use std::collections::{HashMap, VecDeque};
4use std::io::{BufRead, Cursor, Write};
5use std::str::FromStr;
6
7#[cfg(feature = "log")]
8use log::{error, info, trace, warn};
9use quick_xml::events::attributes::Attribute;
10use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
11use quick_xml::name::QName;
12use quick_xml::{Reader, Writer};
13
14use crate::error::Error;
15use crate::error::ParseNodeError;
16use crate::error::Result;
17
18#[derive(Debug, Default, Clone, PartialEq, Eq)]
20pub struct Node {
21 name: String,
22 content: String,
23 attributes: HashMap<String, String>,
24 childs: Vec<Node>,
25}
26
27#[derive(Debug, Default, Clone)]
29pub struct NodeBuilder<'a> {
30 name: &'a str,
31 content: &'a str,
32 attributes: HashMap<String, String>,
33 childs: Vec<Node>,
34}
35
36impl Node {
37 #[must_use]
39 pub fn builder(name: &str) -> NodeBuilder {
40 #[cfg(feature = "log")]
41 trace!("new builder for {}", name);
42 NodeBuilder::new(name)
43 }
44
45 #[must_use]
47 pub fn name(&self) -> &str {
48 self.name.as_str()
49 }
50
51 #[must_use]
53 pub fn content(&self) -> &str {
54 self.content.as_str()
55 }
56
57 pub fn attribute(&self, key: &str) -> Result<&str> {
63 #[cfg(feature = "log")]
64 trace!("searching for attribute '{}' in <{}>", key, self.name());
65 self.attributes
66 .get(key)
67 .map(std::string::String::as_str)
68 .ok_or_else(|| {
69 ParseNodeError::MissingAttribute(key.to_owned(), self.name.clone()).into()
70 })
71 }
72
73 pub fn childs(&self) -> impl Iterator<Item = &Self> {
75 self.childs.iter()
76 }
77
78 #[must_use]
80 pub fn has_attribute(&self, key: &str) -> bool {
81 #[cfg(feature = "log")]
82 trace!("searching for attribute '{}' in <{}>", key, self.name());
83 self.attributes.contains_key(key)
84 }
85
86 #[must_use]
88 pub fn has_childs(&self) -> bool {
89 !self.childs.is_empty()
90 }
91
92 #[must_use]
94 pub fn child_count(&self) -> usize {
95 self.childs.len()
96 }
97
98 pub fn child_by_name<'a, 'n: 'a>(&'a self, name: &'n str) -> Result<&'a Self> {
104 #[cfg(feature = "log")]
105 trace!("searching for child <{}> inside of <{}>", name, self.name());
106 self.childs_by_name(name)
107 .next()
108 .ok_or_else(|| ParseNodeError::MissingChild(name.to_owned(), self.name.clone()).into())
109 }
110
111 pub fn childs_by_name<'a, 'n: 'a>(
113 &'a self,
114 name: &'n str,
115 ) -> impl Iterator<Item = &'a Self> + 'a {
116 #[cfg(feature = "log")]
117 trace!(
118 "construct iterator from all childs <{}> from parent <{}>",
119 name,
120 self.name()
121 );
122 self.childs.iter().filter(move |c| c.name == name)
123 }
124
125 fn write_to_impl<W>(&self, writer: &mut Writer<W>) -> Result<()>
131 where
132 W: std::io::Write,
133 {
134 let start = BytesStart::from(self);
135
136 if self.childs.is_empty() && self.content.is_empty() {
137 writer.write_event(Event::Empty(start))?;
138 } else {
139 writer.write_event(Event::Start(start))?;
140
141 if !self.content.is_empty() {
142 writer.write_event(Event::Text(BytesText::new(&self.content)))?;
143 }
144
145 if !self.childs.is_empty() {
146 for child in &self.childs {
147 child.write_to(writer)?;
148 }
149 }
150
151 writer.write_event(Event::End(BytesEnd::new(&self.name)))?;
152 }
153
154 Ok(())
155 }
156
157 pub fn write_to<W>(&self, writer: &mut Writer<W>) -> Result<()>
163 where
164 W: Write,
165 {
166 #[cfg(feature = "log")]
167 trace!("writing <{}>", self.name());
168 self.write_to_impl(writer)?;
169 writer.get_mut().flush()?;
170
171 Ok(())
172 }
173
174 pub fn read_from<R>(reader: &mut Reader<R>) -> Result<Self>
180 where
181 R: BufRead,
182 {
183 let mut node_stack = VecDeque::<Self>::new();
184 let mut buf = Vec::new();
185
186 let node = loop {
187 match reader.read_event_into(&mut buf) {
188 Ok(Event::Start(ref start)) => {
189 #[cfg(feature = "log")]
190 trace!("Read start event");
191 let node = Self::try_from(start)?;
192 node_stack.push_back(node);
193 }
194 Ok(Event::Empty(ref start)) => {
195 #[cfg(feature = "log")]
196 trace!("Read empty event");
197 let node = Self::try_from(start)?;
198 if let Some(mut parent) = node_stack.pop_back() {
199 parent.childs.push(node);
200 node_stack.push_back(parent);
201 } else {
202 break Ok(node);
203 }
204 }
205 Ok(Event::End(ref end)) => {
206 #[cfg(feature = "log")]
207 trace!("Read end event");
208 #[cfg(not(feature = "log"))]
209 let _ = end;
210 if let Some(node) = node_stack.pop_back() {
211 if let Some(mut parent) = node_stack.pop_back() {
212 parent.childs.push(node);
213 node_stack.push_back(parent);
214 } else {
215 break Ok(node);
216 }
217 } else {
218 #[cfg(feature = "log")]
219 error!(
220 "Found closing element </{}> without an opening element before",
221 str::from_utf8(end.name().as_ref())?
222 );
223 }
224 }
225 Ok(Event::Text(ref t)) => {
226 #[cfg(feature = "log")]
227 trace!("Read text event");
228 let content = str::from_utf8(t)?.trim();
229 if !content.is_empty() {
230 if let Some(node) = node_stack.back_mut() {
231 node.content += content;
232 } else {
233 #[cfg(feature = "log")]
234 warn!("Found characters {} outside of any node", content);
235 }
236 }
237 }
238 Ok(Event::Eof) => break Err(Error::Eof),
239 Err(e) => break Err(Error::from(e)),
240 #[cfg(feature = "log")]
241 ev => info!("Read other event: {:?}", ev),
242 #[cfg(not(feature = "log"))]
243 _ => {}
244 }
245 }?;
246
247 Ok(node)
248 }
249}
250
251impl<'a> TryFrom<&BytesStart<'a>> for Node {
252 type Error = Error;
253
254 fn try_from(value: &BytesStart<'a>) -> Result<Self> {
255 Ok(Self {
256 name: str::from_utf8(value.name().as_ref())?.to_owned(),
257 content: String::new(),
258 attributes: value
259 .attributes()
260 .map(|res| {
261 let attribute = res?;
262 let key = str::from_utf8(attribute.key.as_ref())?.to_owned();
263 let value = str::from_utf8(&attribute.value)?.to_owned();
264 Ok((key, value))
265 })
266 .collect::<Result<HashMap<_, _>>>()?,
267 childs: Vec::new(),
268 })
269 }
270}
271
272impl<'a> From<&'a Node> for BytesStart<'a> {
273 fn from(node: &'a Node) -> Self {
274 BytesStart::new(&node.name).with_attributes(node.attributes.iter().map(|(k, v)| {
275 Attribute {
276 key: QName(k.as_bytes()),
277 value: Cow::Borrowed(v.as_bytes()),
278 }
279 }))
280 }
281}
282
283impl fmt::Display for Node {
284 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285 let mut writer = Writer::new(Cursor::new(Vec::new()));
286 self.write_to(&mut writer).map_err(|_| fmt::Error)?;
287 write!(
288 f,
289 "{}",
290 str::from_utf8(&writer.into_inner().into_inner()).map_err(|_| fmt::Error)?
291 )
292 }
293}
294
295impl FromStr for Node {
296 type Err = Error;
297
298 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
299 Self::read_from(&mut Reader::from_str(s))
300 }
301}
302
303impl<'a> NodeBuilder<'a> {
304 #[must_use]
306 pub fn new(name: &'a str) -> Self {
307 Self {
308 name,
309 content: "",
310 attributes: HashMap::new(),
311 childs: Vec::new(),
312 }
313 }
314
315 #[must_use]
317 pub const fn name(mut self, name: &'a str) -> Self {
318 self.name = name;
319 self
320 }
321
322 #[must_use]
324 pub const fn content(mut self, data: &'a str) -> Self {
325 self.content = data;
326 self
327 }
328
329 #[must_use]
331 pub fn attributes(mut self, attributes: impl IntoIterator<Item = (String, String)>) -> Self {
332 self.attributes.extend(attributes);
333 self
334 }
335
336 #[must_use]
338 pub fn attribute(
339 mut self,
340 key: &(impl ToString + ?Sized),
341 value: &(impl ToString + ?Sized),
342 ) -> Self {
343 self.attributes.insert(key.to_string(), value.to_string());
344 self
345 }
346
347 #[must_use]
349 pub fn childs(mut self, childs: impl IntoIterator<Item = Node>) -> Self {
350 self.childs.extend(childs);
351 self
352 }
353
354 #[must_use]
356 pub fn child(mut self, child: impl Into<Node>) -> Self {
357 self.childs.push(child.into());
358 self
359 }
360
361 #[must_use]
363 pub fn option_child(mut self, child: Option<impl Into<Node>>) -> Self {
364 if let Some(child) = child {
365 self.childs.push(child.into());
366 }
367 self
368 }
369
370 pub fn try_child(mut self, child: impl TryInto<Node, Error = Error>) -> Result<Self> {
376 self.childs.push(child.try_into()?);
377 Ok(self)
378 }
379
380 #[must_use]
382 pub fn build(self) -> Node {
383 Node {
384 name: self.name.to_owned(),
385 content: self.content.to_owned(),
386 attributes: self.attributes,
387 childs: self.childs,
388 }
389 }
390}
391
392impl<'a> From<NodeBuilder<'a>> for Node {
393 fn from(builder: NodeBuilder<'a>) -> Self {
394 builder.build()
395 }
396}