aboutsummaryrefslogtreecommitdiff
path: root/src/deserializer/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/deserializer/mod.rs')
-rw-r--r--src/deserializer/mod.rs179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/deserializer/mod.rs b/src/deserializer/mod.rs
new file mode 100644
index 0000000..bd0c0e4
--- /dev/null
+++ b/src/deserializer/mod.rs
@@ -0,0 +1,179 @@
+//! Deserializer.
+use std::convert::Infallible;
+
+use crate::tagged::TagStart;
+use crate::DeserializeTagged;
+
+pub mod buffered;
+
+/// XML deserializer.
+pub trait Deserializer
+{
+ /// Deserializes a tagged element.
+ ///
+ /// # Errors
+ /// Returns `Err` if deserialization fails.
+ fn de_tag<De: DeserializeTagged>(
+ &mut self,
+ tag_name: &str,
+ ignore_end: IgnoreEnd,
+ ) -> Result<De, Error<De::Error>>;
+
+ /// Deserializes a tagged element using the given function.
+ ///
+ /// # Errors
+ /// Returns `Err` if deserialization fails.
+ fn de_tag_with<Output, Err, DeserializeFn>(
+ &mut self,
+ tag_name: &str,
+ ignore_end: IgnoreEnd,
+ deserialize: DeserializeFn,
+ ) -> Result<Output, Error<Err>>
+ where
+ Err: std::error::Error + Send + Sync + 'static,
+ DeserializeFn: FnOnce(&TagStart, &mut Self) -> Result<Output, Err>;
+
+ /// Deserializes a list of tagged elements.
+ ///
+ /// # Errors
+ /// Returns `Err` if deserialization fails.
+ fn de_tag_list<De: DeserializeTagged>(
+ &mut self,
+ tag_name: Option<&str>,
+ ) -> Result<Vec<De>, Error<De::Error>>;
+
+ /// Deserializes a text element.
+ ///
+ /// # Errors
+ /// Returns `Err` if deserialization fails.
+ fn de_text(&mut self) -> Result<String, Error<Infallible>>;
+
+ /// 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<Infallible>>;
+
+ /// 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<Infallible>>;
+}
+
+/// Whether or not to skip the end tag of a tagged element.
+///
+/// **Should be `No`**.
+#[derive(Debug, Default)]
+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<DeError>
+{
+ /// 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<DeError> Error<DeError>
+{
+ /// Returns `Self` with `DeError` as [`Infallible`].
+ ///
+ /// # Panics
+ /// Will panic if `Self` is the `DeserializeFailed` variant.
+ 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,
+ }
+ }
+}
+
+/// XML error.
+#[derive(Debug, thiserror::Error)]
+#[error(transparent)]
+pub struct XMLError(#[from] quick_xml::Error);