//! Deserializer. use std::convert::Infallible; use crate::tagged::TagStart; use crate::util::trait_alias; use crate::DeserializeTagged; pub mod buffered; /// XML deserializer. pub trait Deserializer { /// Deserializes a tagged element. /// /// # Errors /// Returns `Err` if deserialization fails. fn de_tag( &mut self, tag_name: &str, ignore_end: IgnoreEnd, ) -> Result>; /// Deserializes a tagged element using the given function. /// /// # Errors /// Returns `Err` if deserialization fails. fn de_tag_with( &mut self, tag_name: &str, ignore_end: IgnoreEnd, deserialize: Func, ) -> Result> where Output: MaybeStatic, Err: std::error::Error + Send + Sync + 'static, Func: FnOnce(&TagStart, &mut Self) -> Result + MaybeStatic; /// Deserializes a list of tagged elements. /// /// # Errors /// Returns `Err` if deserialization fails. fn de_tag_list( &mut self, tag_name: Option, ) -> Result, Error> where De: DeserializeTagged, TagName: AsRef + MaybeStatic; /// Deserializes a text element. /// /// # Errors /// Returns `Err` if deserialization fails. fn de_text(&mut self) -> Result>; /// Skips past all elements until a tagged element with the name `tag_name` is /// reached. /// /// # Errors /// Returns `Err` if unsuccessful. fn skip_to_tag_start(&mut self, tag_name: &str) -> Result<(), Error>; /// Skips past all elements until the end of a tagged element with the name `tag_name` /// is reached. /// /// # Errors /// Returns `Err` if unsuccessful. fn skip_to_tag_end(&mut self, tag_name: &str) -> Result<(), Error>; } macro_rules! maybe_static_doc { () => { "Bound to `'static` if the `deserializer-static-generics` feature is enabled." }; } #[cfg(any(not(feature = "deserializer-static-generics"), doc))] trait_alias! { #[doc = maybe_static_doc!()] pub MaybeStatic; } #[cfg(all(feature = "deserializer-static-generics", not(doc)))] trait_alias! { #[doc = maybe_static_doc!()] pub MaybeStatic: 'static; } /// Whether or not to skip the end tag of a tagged element. /// /// **Should be `No`**. #[derive(Debug, Default, PartialEq, Eq)] pub enum IgnoreEnd { /// Skip the end tag. /// /// **Will cause problems in most cases and should be used very carefully**. Yes, /// Don't skip the end tag. #[default] No, } /// [`Deserializer`] error. #[derive(Debug, thiserror::Error)] #[non_exhaustive] pub enum Error { /// A XML error occurred. #[error("A XML error occurred")] XMLError(#[source] XMLError), /// Failed to deserialize. #[error("Failed to deserialize")] DeserializeFailed(#[from] DeError), /// Unexpected event. #[error("Expected {expected_event_name} event. Found {found_event}")] UnexpectedEvent { /// The name of the expected event. expected_event_name: String, /// The found event. found_event: String, }, /// Unexpected end of file. #[error("Unexpected end of file")] UnexpectedEndOfFile, } impl Error { /// Returns `Self` with `DeError` as [`Infallible`]. /// /// # Panics /// Will panic if `Self` is the `DeserializeFailed` variant. pub fn into_never_de_err(self) -> Error { match self { Self::XMLError(xml_err) => Error::XMLError(xml_err), Self::DeserializeFailed(_) => { panic!("is a deserialization error"); } Self::UnexpectedEvent { expected_event_name, found_event, } => Error::UnexpectedEvent { expected_event_name, found_event, }, Self::UnexpectedEndOfFile => Error::UnexpectedEndOfFile, } } } impl Error { fn into_with_de_error(self) -> Error { match self { Self::XMLError(xml_err) => Error::XMLError(xml_err), Self::DeserializeFailed(_) => { unreachable!(); } Self::UnexpectedEvent { expected_event_name, found_event, } => Error::UnexpectedEvent { expected_event_name, found_event, }, Self::UnexpectedEndOfFile => Error::UnexpectedEndOfFile, } } } impl From>> for Error { fn from(err: Error>) -> Self { match err { Error::XMLError(xml_err) => Self::XMLError(xml_err), Error::DeserializeFailed(de_err) => de_err, Error::UnexpectedEvent { expected_event_name, found_event, } => Self::UnexpectedEvent { expected_event_name, found_event, }, Error::UnexpectedEndOfFile => Self::UnexpectedEndOfFile, } } } /// XML error. #[derive(Debug, thiserror::Error)] #[error(transparent)] pub struct XMLError(#[from] quick_xml::Error);