diff options
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | src/deserializer/buffered.rs | 34 | ||||
| -rw-r--r-- | src/deserializer/mod.rs | 35 | ||||
| -rw-r--r-- | src/lib.rs | 5 | ||||
| -rw-r--r-- | src/util.rs | 13 | 
5 files changed, 65 insertions, 25 deletions
| @@ -4,6 +4,9 @@ version = "0.1.0"  edition = "2021"  license = "MIT OR Apache-2.0" +[features] +deserializer-static-generics = [] +  [dependencies]  quick-xml = "0.27.1"  thiserror = "1.0.38" 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<Source: BufRead> +pub struct Buffered<TSource: Source>  { -    reader: Reader<Source>, +    reader: Reader<TSource>,      leftover_event: Option<Event<'static>>,      buf: Vec<u8>,  } -impl<Source> Buffered<Source> -where -    Source: BufRead, +impl<TSource: Source> Buffered<TSource>  {      /// 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<Source> Deserializer for Buffered<Source> -where -    Source: BufRead, +impl<TSource: Source> Deserializer for Buffered<TSource>  {      fn de_tag<De: DeserializeTagged>(          &mut self, @@ -84,9 +86,9 @@ where          Ok(deserialized)      } -    fn de_tag_list<De: DeserializeTagged>( +    fn de_tag_list<De: DeserializeTagged, Name: AsRef<str>>(          &mut self, -        tag_name: Option<&str>, +        tag_name: Option<Name>,      ) -> Result<Vec<De>, Error<De::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<Source> Buffered<Source> -where -    Source: BufRead, +impl<TSource: Source> Buffered<TSource>  {      fn read_end_event(&mut self, tag_name: &[u8]) -> Result<(), Error<Infallible>>      { 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<Output, Err, DeserializeFn>( +    fn de_tag_with<Output, Err, Func>(          &mut self,          tag_name: &str,          ignore_end: IgnoreEnd, -        deserialize: DeserializeFn, +        deserialize: Func,      ) -> Result<Output, Error<Err>>      where +        Output: MaybeStatic,          Err: std::error::Error + Send + Sync + 'static, -        DeserializeFn: FnOnce(&TagStart, &mut Self) -> Result<Output, Err>; +        Func: FnOnce(&TagStart, &mut Self) -> Result<Output, Err> + MaybeStatic;      /// Deserializes a list of tagged elements.      ///      /// # Errors      /// Returns `Err` if deserialization fails. -    fn de_tag_list<De: DeserializeTagged>( +    fn de_tag_list<De, TagName>(          &mut self, -        tag_name: Option<&str>, -    ) -> Result<Vec<De>, Error<De::Error>>; +        tag_name: Option<TagName>, +    ) -> Result<Vec<De>, Error<De::Error>> +    where +        De: DeserializeTagged, +        TagName: AsRef<str> + MaybeStatic;      /// Deserializes a text element.      /// @@ -63,6 +68,24 @@ pub trait Deserializer      fn skip_to_tag_end(&mut self, tag_name: &str) -> Result<(), Error<Infallible>>;  } +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`**. @@ -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<T: $($first_bound $(+ $bound)*)?, $($($type_param),*)?> $name$(<$($type_param),*>)? for T {} +    }; +} + +pub(crate) use trait_alias; | 
