use std::error::Error; use std::ops::Deref; use quick_xml::events::{BytesStart, Event}; pub mod buffer_deserializer; pub trait Deserialize: Sized { type Error: Error + Send + Sync + 'static; fn deserialize( start: &BytesStart, deserializer: &mut TDeserializer, ) -> Result; } #[cfg_attr(test, ridicule::automock)] pub trait Deserializer { fn de_tag( &mut self, tag_name: &str, ignore_end: IgnoreEnd, ) -> Result; fn de_tag_with( &mut self, tag_name: &str, ignore_end: IgnoreEnd, deserialize: DeserializeFn, ) -> Result where Err: Error + Send + Sync + 'static, DeserializeFn: FnOnce(&BytesStart, &mut Self) -> Result; fn de_tag_list( &mut self, tag_name: &str, ) -> Result, DeserializerError>; fn de_list(&mut self) -> Result, DeserializerError>; fn de_text(&mut self) -> Result; fn skip_to_tag_start(&mut self, tag_name: &str) -> Result<(), DeserializerError>; fn skip_to_tag_end(&mut self, tag_name: &str) -> Result<(), DeserializerError>; } pub enum IgnoreEnd { Yes, No, } /// Function pointer type passable to [`Deserializer::de_tag_with`]. pub type DeserializeWithFn = fn(&BytesStart, &mut Deserializer) -> Result; #[derive(Debug, thiserror::Error)] pub enum DeserializerError { #[error("Failed to read")] ReadFailed(#[from] quick_xml::Error), #[error("Failed to deserialize {0}")] DeserializeFailed(&'static str, #[source] WrappedDeserializeError), #[error("Expected {expected_event_name} event. Found {found_event:?}")] UnexpectedEvent { expected_event_name: String, found_event: Event<'static>, }, #[error("Unexpected end of file")] UnexpectedEndOfFile, } #[derive(Debug, thiserror::Error)] #[error(transparent)] pub struct WrappedDeserializeError(Box); impl WrappedDeserializeError { fn new(err: Err) -> Self { Self(Box::new(err)) } } impl Deref for WrappedDeserializeError { type Target = dyn Error; fn deref(&self) -> &Self::Target { self.0.as_ref() } } pub trait ResultExt { fn try_event(self) -> Result, DeserializerError>; } impl ResultExt for Result { fn try_event(self) -> Result, DeserializerError> { self.map_or_else( |err| { if let DeserializerError::UnexpectedEvent { expected_event_name: _, found_event: _, } = err { return Ok(None); } Err(err) }, |value| Ok(Some(value)), ) } }