aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2023-05-09 20:38:46 +0200
committerHampusM <hampus@hampusmat.com>2023-05-11 21:05:53 +0200
commit8818a94ad79ebdebdf4c7819bd42e363c63bd630 (patch)
tree0a757ff271bf9d4d15be1a3a947f58b613961cbf
parente762babd9e69400ccd178ba8946168640093eb63 (diff)
feat: add optional deserializer generics static bounds
-rw-r--r--Cargo.toml3
-rw-r--r--src/deserializer/buffered.rs34
-rw-r--r--src/deserializer/mod.rs35
-rw-r--r--src/lib.rs5
-rw-r--r--src/util.rs13
5 files changed, 65 insertions, 25 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 721ab10..516e5d2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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`**.
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<T: $($first_bound $(+ $bound)*)?, $($($type_param),*)?> $name$(<$($type_param),*>)? for T {}
+ };
+}
+
+pub(crate) use trait_alias;