xml_stinks/lib.rs
1//! XML is awful.
2//!
3//! # Examples
4//! ```
5//! use std::convert::Infallible;
6//!
7//! use xml_stinks::deserializer::buffered::Buffered as BufferedDeserializer;
8//! use xml_stinks::deserializer::{Deserializer, IgnoreEnd};
9//! use xml_stinks::tagged::TagStart;
10//! use xml_stinks::DeserializeTagged;
11//!
12//! let mut deserializer =
13//! BufferedDeserializer::new("<foo>Baz<bar>DF</bar></foo>".as_bytes());
14//!
15//! let foo = deserializer.de_tag::<Foo>("foo", IgnoreEnd::No).unwrap();
16//!
17//! assert_eq!(&foo.name, "Baz");
18//! assert_eq!(foo.bar.num, 223);
19//!
20//! struct Foo
21//! {
22//! name: String,
23//! bar: Bar,
24//! }
25//!
26//! impl DeserializeTagged for Foo
27//! {
28//! type Error = Infallible;
29//!
30//! fn deserialize<TDeserializer: Deserializer>(
31//! start: &TagStart,
32//! deserializer: &mut TDeserializer,
33//! ) -> Result<Self, Self::Error>
34//! {
35//! let name = deserializer.de_text().unwrap();
36//!
37//! let bar = deserializer.de_tag::<Bar>("bar", IgnoreEnd::No).unwrap();
38//!
39//! Ok(Self { name, bar })
40//! }
41//! }
42//!
43//! struct Bar
44//! {
45//! num: u32,
46//! }
47//!
48//! impl DeserializeTagged for Bar
49//! {
50//! type Error = Infallible;
51//!
52//! fn deserialize<TDeserializer: Deserializer>(
53//! start: &TagStart,
54//! deserializer: &mut TDeserializer,
55//! ) -> Result<Self, Self::Error>
56//! {
57//! let num = u32::from_str_radix(&deserializer.de_text().unwrap(), 16).unwrap();
58//!
59//! Ok(Self { num })
60//! }
61//! }
62//! ```
63#![deny(clippy::all, clippy::pedantic, unsafe_code, missing_docs)]
64use crate::deserializer::{Deserializer, Error as DeserializerError, MaybeStatic};
65use crate::tagged::TagStart;
66
67pub mod attribute;
68pub mod deserializer;
69pub mod escape;
70pub mod tagged;
71
72mod event;
73mod util;
74
75/// Trait implemented by types that want to be deserializable from tagged XML elements.
76pub trait DeserializeTagged: Sized + MaybeStatic
77{
78 /// Error type.
79 type Error: std::error::Error + Send + Sync + 'static;
80
81 /// Deserializes into a new `Self`.
82 ///
83 /// # Errors
84 /// When or if a error is returned is decided by the type implementing this trait.
85 fn deserialize<TDeserializer: Deserializer>(
86 start: &TagStart,
87 deserializer: &mut TDeserializer,
88 ) -> Result<Self, Self::Error>;
89}
90
91/// Result extension.
92pub trait ResultExt<Value, DeError>
93{
94 /// Returns `Ok(None)` if `Err` is `DeserializerError::UnexpectedEvent`.
95 ///
96 /// # Errors
97 /// Returns `Err` if a `Deserializer` error occurs.
98 fn try_event(self) -> Result<Option<Value>, DeserializerError<DeError>>;
99}
100
101impl<Value, DeError> ResultExt<Value, DeError>
102 for Result<Value, DeserializerError<DeError>>
103{
104 fn try_event(self) -> Result<Option<Value>, DeserializerError<DeError>>
105 {
106 self.map_or_else(
107 |err| {
108 if let DeserializerError::UnexpectedEvent {
109 expected_event_name: _,
110 found_event: _,
111 } = err
112 {
113 return Ok(None);
114 }
115
116 Err(err)
117 },
118 |value| Ok(Some(value)),
119 )
120 }
121}