1
0
mirror of https://gitlab.com/xmpp-rs/xmpp-rs.git synced 2024-06-09 09:44:03 +02:00

parsers-core, parsers-macros: Remove XmlDataCollection trait

This can be represented appropriately using Extend<T>, IntoIterator and
Default from the standard library. We keep the XmlDataItem trait for
flexibility though.
This commit is contained in:
Jonas Schäfer 2024-03-23 17:42:39 +01:00
parent e0b528ceb7
commit f1dc7594e0
2 changed files with 20 additions and 65 deletions

View File

@ -13,8 +13,6 @@ a full reference on the supported attributes.
[^serde-note]: Though it should be said that you can combine serde and this
crate on the same struct, no problem with that!
*/
use std::collections::BTreeMap;
pub mod error;
mod text;
@ -213,9 +211,14 @@ The following field kinds are available:
- More than one clause inside `extract(..)` are allowed.
- More than one matching child is allowed
- The field type must implement `XmlDataCollection<T>`, where T is a tuple
of N strings, where N is the number of clauses in the `extract(..)`
attribute.
- The field type must implement [`Default`][`std::default::Default`],
[`Extend<T>`][`std::iter::Extend`] and
[`IntoIterator<Item = T>`][`std::iter::IntoIterator`], where `T`
implements [`XmlDataItem<U>`][`XmlDataItem`].
`U`, in turn, must be a tuple type matching the types provided by the
extracted parts. Text and attributes map to [`String`], `elements` maps
to `Vec<minidom::Element>`.
- `children`: Extract zero or more entire child elements. The field type must
implement [`Default`][`std::default::Default`],
@ -473,59 +476,3 @@ impl<A: FromText + IntoText, B: FromText + IntoText> XmlDataItem<(String, String
(self.0.into_text(), self.1.into_text())
}
}
/// TODO: remove this
pub trait XmlDataCollection {
/// TODO: remove this
type Input;
/// TODO: remove this
type Item: XmlDataItem<Self::Input>;
/// TODO: remove this
type IntoIter: Iterator<Item = Self::Item>;
/// TODO: remove this
fn new_empty() -> Self;
/// TODO: remove this
fn append_data(&mut self, item: Self::Item);
/// TODO: remove this
fn into_data_iterator(self) -> Self::IntoIter;
}
impl<T: XmlDataItem<String>> XmlDataCollection for Vec<T> {
type Input = String;
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn new_empty() -> Self {
Vec::new()
}
fn append_data(&mut self, item: Self::Item) {
self.push(item);
}
fn into_data_iterator(self) -> Self::IntoIter {
self.into_iter()
}
}
impl<K: Ord, V> XmlDataCollection for BTreeMap<K, V>
where
(K, V): XmlDataItem<(String, String)>,
{
type Input = (String, String);
type Item = (K, V);
type IntoIter = std::collections::btree_map::IntoIter<K, V>;
fn new_empty() -> Self {
BTreeMap::new()
}
fn append_data(&mut self, item: Self::Item) {
self.insert(item.0, item.1);
}
fn into_data_iterator(self) -> Self::IntoIter {
self.into_iter()
}
}

View File

@ -440,15 +440,19 @@ impl ChildField {
Some(extract) => {
let extract =
extract.build_extract(&Ident::new("residual", Span::call_site()), None)?;
let item_ty: Type = syn::parse2(quote! {
<#ty as IntoIterator>::Item
})
.expect("failed to construct item type");
Ok(FieldParsePart {
tempinit: quote! {
let mut #tempname = <#ty as ::xmpp_parsers_core::XmlDataCollection>::new_empty();
let mut #tempname = <#ty as ::std::default::Default>::default();
},
childiter: quote! {
residual = match #extract {
Ok(v) => {
let v = <<#ty as ::xmpp_parsers_core::XmlDataCollection>::Item as ::xmpp_parsers_core::XmlDataItem<<#ty as ::xmpp_parsers_core::XmlDataCollection>::Input>>::from_raw(v)?;
<#ty as ::xmpp_parsers_core::XmlDataCollection>::append_data(&mut #tempname, v);
let v = <#item_ty as ::xmpp_parsers_core::XmlDataItem<_>>::from_raw(v)?;
<#ty as ::std::iter::Extend<#item_ty>>::extend(&mut #tempname, [v]);
continue;
},
Err(residual) => residual,
@ -521,10 +525,14 @@ impl ChildField {
}),
None,
)?;
let item_ty: Type = syn::parse2(quote! {
<#ty as IntoIterator>::Item
})
.expect("failed to construct item type");
Ok(quote! {
builder.append_all(
#ident.into_iter().filter_map(|item| {
let data = <<#ty as ::xmpp_parsers_core::XmlDataCollection>::Item as ::xmpp_parsers_core::XmlDataItem<<#ty as ::xmpp_parsers_core::XmlDataCollection>::Input>>::into_raw(item);
let data = <#item_ty as ::xmpp_parsers_core::XmlDataItem<_>>::into_raw(item);
#assemble
})
)