From 1ffc8cbafc4439435307831e87d6f3c265ad819c Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 13 May 2023 21:15:52 +0200 Subject: feat: add deserializer error conversion utilities --- examples/simple.rs | 26 ++--------------- src/deserializer/mod.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ 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), } -impl> From> for DataError -{ - fn from(err: DeserializerError) -> 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), } -impl> From> for FavoritesError -{ - fn from(err: DeserializerError) -> 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>> for Error } } +impl Error +{ + /// Converts `Self` into `Err`. + pub fn into_error(self) -> Err + where + Err: From + From>, + { + 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>`. +/// +/// # 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), +/// +/// #[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::::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> From<::xml_stinks::deserializer::Error> + for $err + { + fn from(err: ::xml_stinks::deserializer::Error) -> Self + { + if let ::xml_stinks::deserializer::Error::DeserializeFailed(de_err) = err + { + return de_err.into(); + } + + err.into_never_de_err().into() + } + } + }; +} -- cgit v1.2.3-18-g5258