use std::convert::Infallible;
use crate::tagged::TagStart;
use crate::util::{feature_alternate, trait_alias};
use crate::DeserializeTagged;
pub mod buffered;
pub trait Deserializer
{
fn de_tag<De: DeserializeTagged>(
&mut self,
tag_name: &str,
ignore_end: IgnoreEnd,
) -> Result<De, Error<De::Error>>;
fn de_tag_with<Output, Err, Func>(
&mut self,
tag_name: &str,
ignore_end: IgnoreEnd,
deserialize: Func,
) -> Result<Output, Error<Err>>
where
Output: MaybeStatic,
Err: std::error::Error + Send + Sync + 'static,
Func: FnOnce(&TagStart, &mut Self) -> Result<Output, Err> + MaybeStatic;
fn de_tag_list<De, TagName>(
&mut self,
tag_name: Option<TagName>,
) -> Result<Vec<De>, Error<De::Error>>
where
De: DeserializeTagged,
TagName: AsRef<str> + MaybeStatic;
fn de_text(&mut self) -> Result<String, Error<Infallible>>;
fn skip_to_tag_start(&mut self, tag_name: &str) -> Result<(), Error<Infallible>>;
fn skip_to_tag_end(&mut self, tag_name: &str) -> Result<(), Error<Infallible>>;
}
trait_alias!(
bounds_when_feature = "deserializer-static-generics",
/// Bound to `'static` if the `deserializer-static-generics` feature is enabled.
pub MaybeStatic: 'static;
);
#[derive(Debug, Default, PartialEq, Eq)]
pub enum IgnoreEnd
{
Yes,
#[default]
No,
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum Error<DeError>
{
#[error("A XML error occurred")]
XMLError(#[source] XMLError),
#[error("Failed to deserialize")]
DeserializeFailed(#[from] DeError),
#[error("Expected {expected_event_name} event. Found {found_event}")]
UnexpectedEvent
{
expected_event_name: String,
found_event: String,
},
#[error("Unexpected end of file")]
UnexpectedEndOfFile,
}
impl<DeError> Error<DeError>
{
pub fn into_never_de_err(self) -> Error<Infallible>
{
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<Infallible>
{
fn into_with_de_error<DeError>(self) -> Error<DeError>
{
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<Error<Error<Infallible>>> for Error<Infallible>
{
fn from(err: Error<Error<Infallible>>) -> 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,
}
}
}
impl<DeError> Error<DeError>
{
pub fn into_error<Err>(self) -> Err
where
Err: From<DeError> + From<Error<Infallible>>,
{
if let Error::DeserializeFailed(de_err) = self {
return de_err.into();
}
self.into_never_de_err().into()
}
}
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct XMLError(#[from] quick_xml::Error);
#[macro_export]
macro_rules! impl_from_deserializer_error {
($err: path) => {
impl<DeError: Into<Self>> From<::xml_stinks::deserializer::Error<DeError>>
for $err
{
fn from(err: ::xml_stinks::deserializer::Error<DeError>) -> Self
{
if let ::xml_stinks::deserializer::Error::DeserializeFailed(de_err) = err
{
return de_err.into();
}
err.into_never_de_err().into()
}
}
};
}
feature_alternate!(
feature = "deserializer-static-generics",
when_enabled =
#[macro_export]
macro_rules! xml_stinks_if_deserializer_static_generics {
(then { $($then: tt)* }$(else { $($else: tt)* })?) => {
$($then)*
};
},
when_disabled =
#[macro_export]
macro_rules! xml_stinks_if_deserializer_static_generics {
(then { $($then: tt)* }$(else { $($else: tt)* })?) => {
$($($else)*)?
};
}
);