diff options
Diffstat (limited to 'src/deserialization')
-rw-r--r-- | src/deserialization/buffer_deserializer.rs | 240 | ||||
-rw-r--r-- | src/deserialization/mod.rs | 127 |
2 files changed, 0 insertions, 367 deletions
diff --git a/src/deserialization/buffer_deserializer.rs b/src/deserialization/buffer_deserializer.rs deleted file mode 100644 index a4e7b2f..0000000 --- a/src/deserialization/buffer_deserializer.rs +++ /dev/null @@ -1,240 +0,0 @@ -use std::any::type_name; -use std::error::Error; -use std::io::BufRead; - -use quick_xml::events::{BytesStart, Event}; -use quick_xml::Reader; - -use crate::deserialization::{ - Deserialize, - Deserializer, - DeserializerError, - IgnoreEnd, - WrappedDeserializeError, -}; - -macro_rules! read_event { - ($self: ident) => {{ - let event = if let Some(leftover_event) = $self.leftover_event.take() { - leftover_event - } else { - $self.reader.read_event_into(&mut $self.buf)?.into_owned() - }; - - if let Event::Eof = &event { - return Err(DeserializerError::UnexpectedEndOfFile); - } - - event - }}; -} - -pub struct BufferDeserializer<Source> -{ - reader: Reader<Source>, - leftover_event: Option<Event<'static>>, - buf: Vec<u8>, -} - -impl<Source> BufferDeserializer<Source> -where - Source: BufRead, -{ - pub fn new(source: Source) -> Self - { - let mut reader = Reader::from_reader(source); - - reader.trim_text(true); - reader.expand_empty_elements(true); - - Self { - reader, - leftover_event: None, - buf: Vec::new(), - } - } -} - -impl<Source> Deserializer for BufferDeserializer<Source> -where - Source: BufRead, -{ - fn de_tag<De: Deserialize>( - &mut self, - tag_name: &str, - ignore_end: IgnoreEnd, - ) -> Result<De, DeserializerError> - { - self.de_tag_with(tag_name, ignore_end, De::deserialize) - } - - fn de_tag_with<Output, Err, DeserializeFn>( - &mut self, - tag_name: &str, - ignore_end: IgnoreEnd, - deserialize: DeserializeFn, - ) -> Result<Output, DeserializerError> - where - Err: Error + Send + Sync + 'static, - DeserializeFn: FnOnce(&BytesStart, &mut Self) -> Result<Output, Err>, - { - let deserialized = match read_event!(self) { - Event::Start(start) if start.name().as_ref() == tag_name.as_bytes() => { - deserialize(&start, self).map_err(|err| { - DeserializerError::DeserializeFailed( - type_name::<Output>(), - WrappedDeserializeError::new(err), - ) - })? - } - event => { - self.leftover_event = Some(event.clone().into_owned()); - - return Err(DeserializerError::UnexpectedEvent { - expected_event_name: format!("start({tag_name})"), - found_event: event, - }); - } - }; - - if let IgnoreEnd::No = ignore_end { - self.read_end_event(tag_name.as_bytes())?; - } - - Ok(deserialized) - } - - fn de_tag_list<De: Deserialize>( - &mut self, - tag_name: &str, - ) -> Result<Vec<De>, DeserializerError> - { - let mut deserialized_items = Vec::new(); - - loop { - let start = match read_event!(self) { - Event::Start(start) if start.name().as_ref() == tag_name.as_bytes() => { - start - } - Event::Comment(_) => { - continue; - } - event => { - self.leftover_event = Some(event.into_owned()); - break; - } - }; - - let deserialized = De::deserialize(&start, self).map_err(|err| { - DeserializerError::DeserializeFailed( - type_name::<De>(), - WrappedDeserializeError::new(err), - ) - })?; - - self.read_end_event(tag_name.as_bytes())?; - - deserialized_items.push(deserialized); - } - - Ok(deserialized_items) - } - - fn de_list<De: Deserialize>(&mut self) -> Result<Vec<De>, DeserializerError> - { - let mut deserialized_items = Vec::new(); - - loop { - let start = match read_event!(self) { - Event::Start(start) => start, - Event::Comment(_) => { - continue; - } - event => { - self.leftover_event = Some(event.into_owned()); - break; - } - }; - - let deserialized = De::deserialize(&start, self).map_err(|err| { - DeserializerError::DeserializeFailed( - type_name::<De>(), - WrappedDeserializeError::new(err), - ) - })?; - - self.read_end_event(start.name().as_ref())?; - - deserialized_items.push(deserialized); - } - - Ok(deserialized_items) - } - - fn de_text(&mut self) -> Result<String, DeserializerError> - { - let text = match read_event!(self) { - Event::Text(text) => Ok(text), - event => { - self.leftover_event = Some(event.clone().into_owned()); - - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "text".to_string(), - found_event: event, - }) - } - }? - .unescape()?; - - Ok(text.to_string()) - } - - fn skip_to_tag_start(&mut self, tag_name: &str) -> Result<(), DeserializerError> - { - loop { - match read_event!(self) { - Event::Start(start) if start.name().as_ref() == tag_name.as_bytes() => { - self.leftover_event = Some(Event::Start(start).into_owned()); - - break; - } - _ => {} - } - } - - Ok(()) - } - - fn skip_to_tag_end(&mut self, tag_name: &str) -> Result<(), DeserializerError> - { - loop { - match read_event!(self) { - Event::End(end) if end.name().as_ref() == tag_name.as_bytes() => { - self.leftover_event = Some(Event::End(end).into_owned()); - - return Ok(()); - } - _ => {} - } - } - } -} - -impl<Source> BufferDeserializer<Source> -where - Source: BufRead, -{ - fn read_end_event(&mut self, tag_name: &[u8]) -> Result<(), DeserializerError> - { - let event = read_event!(self); - - if matches!(&event, Event::End(end) if end.name().as_ref() == tag_name) { - return Ok(()); - } - - Err(DeserializerError::UnexpectedEvent { - expected_event_name: "end".to_string(), - found_event: event.into_owned(), - }) - } -} diff --git a/src/deserialization/mod.rs b/src/deserialization/mod.rs deleted file mode 100644 index b86c2af..0000000 --- a/src/deserialization/mod.rs +++ /dev/null @@ -1,127 +0,0 @@ -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<TDeserializer: Deserializer>( - start: &BytesStart, - deserializer: &mut TDeserializer, - ) -> Result<Self, Self::Error>; -} - -#[cfg_attr(test, ridicule::automock)] -pub trait Deserializer -{ - fn de_tag<De: Deserialize>( - &mut self, - tag_name: &str, - ignore_end: IgnoreEnd, - ) -> Result<De, DeserializerError>; - - fn de_tag_with<Output, Err, DeserializeFn>( - &mut self, - tag_name: &str, - ignore_end: IgnoreEnd, - deserialize: DeserializeFn, - ) -> Result<Output, DeserializerError> - where - Err: Error + Send + Sync + 'static, - DeserializeFn: FnOnce(&BytesStart, &mut Self) -> Result<Output, Err>; - - fn de_tag_list<De: Deserialize>( - &mut self, - tag_name: &str, - ) -> Result<Vec<De>, DeserializerError>; - - fn de_list<De: Deserialize>(&mut self) -> Result<Vec<De>, DeserializerError>; - - fn de_text(&mut self) -> Result<String, DeserializerError>; - - 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<Output, Err, Deserializer> = - fn(&BytesStart, &mut Deserializer) -> Result<Output, Err>; - -#[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<dyn Error + Send + Sync>); - -impl WrappedDeserializeError -{ - fn new<Err: Error + Send + Sync + 'static>(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<Value> -{ - fn try_event(self) -> Result<Option<Value>, DeserializerError>; -} - -impl<Value> ResultExt<Value> for Result<Value, DeserializerError> -{ - fn try_event(self) -> Result<Option<Value>, 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)), - ) - } -} |