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}