From 8818a94ad79ebdebdf4c7819bd42e363c63bd630 Mon Sep 17 00:00:00 2001 From: HampusM Date: Tue, 9 May 2023 20:38:46 +0200 Subject: feat: add optional deserializer generics static bounds --- src/deserializer/buffered.rs | 34 +++++++++++++++++----------------- src/deserializer/mod.rs | 35 +++++++++++++++++++++++++++++------ src/lib.rs | 5 +++-- src/util.rs | 13 +++++++++++++ 4 files changed, 62 insertions(+), 25 deletions(-) create mode 100644 src/util.rs (limited to 'src') diff --git a/src/deserializer/buffered.rs b/src/deserializer/buffered.rs index 7a6058b..6568910 100644 --- a/src/deserializer/buffered.rs +++ b/src/deserializer/buffered.rs @@ -5,25 +5,29 @@ use std::io::BufRead; use quick_xml::events::Event; use quick_xml::Reader; -use crate::deserializer::{Deserializer, Error, IgnoreEnd}; +use crate::deserializer::{Deserializer, Error, IgnoreEnd, MaybeStatic}; use crate::event::EventExt; use crate::tagged::TagStart; +use crate::util::trait_alias; use crate::DeserializeTagged; +trait_alias! { + /// A XML deserializer source with an internal buffer. + pub Source: BufRead + MaybeStatic; +} + /// XML deserializer using a source which has an internal buffer. -pub struct Buffered +pub struct Buffered { - reader: Reader, + reader: Reader, leftover_event: Option>, buf: Vec, } -impl Buffered -where - Source: BufRead, +impl Buffered { /// Returns a new [`Buffered`]. - pub fn new(source: Source) -> Self + pub fn new(source: TSource) -> Self { let mut reader = Reader::from_reader(source); @@ -38,9 +42,7 @@ where } } -impl Deserializer for Buffered -where - Source: BufRead, +impl Deserializer for Buffered { fn de_tag( &mut self, @@ -84,9 +86,9 @@ where Ok(deserialized) } - fn de_tag_list( + fn de_tag_list>( &mut self, - tag_name: Option<&str>, + tag_name: Option, ) -> Result, Error> { let mut deserialized_items = Vec::new(); @@ -94,10 +96,10 @@ where loop { let start = match self.read_event()? { Event::Start(start) - if tag_name.map_or_else( + if tag_name.as_ref().map_or_else( || true, |expected_tag_name| { - start.name().as_ref() == expected_tag_name.as_bytes() + start.name().as_ref() == expected_tag_name.as_ref().as_bytes() }, ) => { @@ -174,9 +176,7 @@ where } } -impl Buffered -where - Source: BufRead, +impl Buffered { fn read_end_event(&mut self, tag_name: &[u8]) -> Result<(), Error> { diff --git a/src/deserializer/mod.rs b/src/deserializer/mod.rs index bd0c0e4..e0c5f6d 100644 --- a/src/deserializer/mod.rs +++ b/src/deserializer/mod.rs @@ -2,6 +2,7 @@ use std::convert::Infallible; use crate::tagged::TagStart; +use crate::util::trait_alias; use crate::DeserializeTagged; pub mod buffered; @@ -23,24 +24,28 @@ pub trait Deserializer /// /// # Errors /// Returns `Err` if deserialization fails. - fn de_tag_with( + fn de_tag_with( &mut self, tag_name: &str, ignore_end: IgnoreEnd, - deserialize: DeserializeFn, + deserialize: Func, ) -> Result> where + Output: MaybeStatic, Err: std::error::Error + Send + Sync + 'static, - DeserializeFn: FnOnce(&TagStart, &mut Self) -> Result; + Func: FnOnce(&TagStart, &mut Self) -> Result + MaybeStatic; /// Deserializes a list of tagged elements. /// /// # Errors /// Returns `Err` if deserialization fails. - fn de_tag_list( + fn de_tag_list( &mut self, - tag_name: Option<&str>, - ) -> Result, Error>; + tag_name: Option, + ) -> Result, Error> + where + De: DeserializeTagged, + TagName: AsRef + MaybeStatic; /// Deserializes a text element. /// @@ -63,6 +68,24 @@ pub trait Deserializer fn skip_to_tag_end(&mut self, tag_name: &str) -> Result<(), Error>; } +macro_rules! maybe_static_doc { + () => { + "Bound to `'static` if the `deserializer-static-generics` feature is enabled." + }; +} + +#[cfg(any(not(feature = "deserializer-static-generics"), doc))] +trait_alias! { + #[doc = maybe_static_doc!()] + pub MaybeStatic; +} + +#[cfg(all(feature = "deserializer-static-generics", not(doc)))] +trait_alias! { + #[doc = maybe_static_doc!()] + pub MaybeStatic: 'static; +} + /// Whether or not to skip the end tag of a tagged element. /// /// **Should be `No`**. diff --git a/src/lib.rs b/src/lib.rs index e5086bc..9cf3716 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ //! XML is awful. #![deny(clippy::all, clippy::pedantic, unsafe_code, missing_docs)] -use crate::deserializer::{Deserializer, Error as DeserializerError}; +use crate::deserializer::{Deserializer, Error as DeserializerError, MaybeStatic}; use crate::tagged::TagStart; pub mod attribute; @@ -8,9 +8,10 @@ pub mod deserializer; pub mod tagged; mod event; +mod util; /// Trait implemented by types that want to be deserializable from tagged XML elements. -pub trait DeserializeTagged: Sized +pub trait DeserializeTagged: Sized + MaybeStatic { /// Error type. type Error: std::error::Error + Send + Sync + 'static; diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..78d2cd4 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,13 @@ +macro_rules! trait_alias { + ( + $(#[$attr: meta])* + $visibility: vis $name: ident$(<$($type_param: ident),*>)?$(: $first_bound: tt $(+ $bound: tt)*)?; + ) => { + $(#[$attr])* + $visibility trait $name $(<$($type_param),*>)? $(: $first_bound $(+ $bound)*)? {} + + impl $name$(<$($type_param),*>)? for T {} + }; +} + +pub(crate) use trait_alias; -- cgit v1.2.3-18-g5258