aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2023-05-13 21:15:52 +0200
committerHampusM <hampus@hampusmat.com>2023-05-13 21:15:52 +0200
commit1ffc8cbafc4439435307831e87d6f3c265ad819c (patch)
tree6d080deda22bc9c467672f60256024d68dabe3e9
parentbdce3a36f72de6097fb78a917e29b7e093a6ef58 (diff)
feat: add deserializer error conversion utilities
-rw-r--r--examples/simple.rs26
-rw-r--r--src/deserializer/mod.rs78
2 files changed, 81 insertions, 23 deletions
diff --git a/examples/simple.rs b/examples/simple.rs
index a4b76f2..563530c 100644
--- a/examples/simple.rs
+++ b/examples/simple.rs
@@ -8,7 +8,7 @@ use std::path::Path;
use xml_stinks::deserializer::buffered::Buffered as BufferedDeserializer;
use xml_stinks::deserializer::{Deserializer, Error as DeserializerError, IgnoreEnd};
use xml_stinks::tagged::TagStart;
-use xml_stinks::DeserializeTagged;
+use xml_stinks::{impl_from_deserializer_error, DeserializeTagged};
const MANIFEST_DIR: &str = std::env!("CARGO_MANIFEST_DIR");
@@ -81,17 +81,7 @@ enum DataError
DeserializeFailed(#[from] DeserializerError<Infallible>),
}
-impl<DeError: Into<Self>> From<DeserializerError<DeError>> for DataError
-{
- fn from(err: DeserializerError<DeError>) -> Self
- {
- if let DeserializerError::DeserializeFailed(de_err) = err {
- return de_err.into();
- }
-
- err.into_never_de_err().into()
- }
-}
+impl_from_deserializer_error!(DataError);
#[derive(Debug)]
struct Favorites
@@ -130,14 +120,4 @@ enum FavoritesError
DeserializeFailed(#[from] DeserializerError<Infallible>),
}
-impl<DeError: Into<Self>> From<DeserializerError<DeError>> for FavoritesError
-{
- fn from(err: DeserializerError<DeError>) -> Self
- {
- if let DeserializerError::DeserializeFailed(de_err) = err {
- return de_err.into();
- }
-
- err.into_never_de_err().into()
- }
-}
+impl_from_deserializer_error!(FavoritesError);
diff --git a/src/deserializer/mod.rs b/src/deserializer/mod.rs
index d6af9c1..918136f 100644
--- a/src/deserializer/mod.rs
+++ b/src/deserializer/mod.rs
@@ -196,7 +196,85 @@ impl From<Error<Error<Infallible>>> for Error<Infallible>
}
}
+impl<DeError> Error<DeError>
+{
+ /// Converts `Self` into `Err`.
+ 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()
+ }
+}
+
/// XML error.
#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct XMLError(#[from] quick_xml::Error);
+
+/// Implements conversion from [`Error`] with [`From`] for the given error type.
+///
+/// Allows for custom error types with source error types to easily be converted into with
+/// `?`.
+///
+/// The given error type should implement `From<Error<Infallible>>`.
+///
+/// # Examples
+/// ```
+/// use std::convert::Infallible;
+///
+/// use xml_stinks::deserializer::Error as DeserializerError;
+/// use xml_stinks::impl_from_deserializer_error;
+///
+/// #[derive(Debug, thiserror::Error)]
+/// enum FooError
+/// {
+/// #[error("Deserialization failed")]
+/// DeserializeFailed(#[from] DeserializerError<Infallible>),
+///
+/// #[error("Invalid bar")]
+/// InvalidBar(#[from] BarError),
+/// }
+///
+/// impl_from_deserializer_error!(FooError);
+///
+/// #[derive(Debug, thiserror::Error)]
+/// enum BarError
+/// {
+/// #[error("Oops")]
+/// Oops,
+/// }
+///
+/// let err_a: FooError = DeserializerError::<Infallible>::UnexpectedEndOfFile.into();
+///
+/// assert!(matches!(
+/// err_a,
+/// FooError::DeserializeFailed(DeserializerError::UnexpectedEndOfFile)
+/// ));
+///
+/// let err_b: FooError = DeserializerError::DeserializeFailed(BarError::Oops).into();
+///
+/// assert!(matches!(err_b, FooError::InvalidBar(BarError::Oops)));
+/// ```
+#[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()
+ }
+ }
+ };
+}