mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-06-26 17:08:26 +02:00
parsers-macros: wrap Extend trait into TryExtend for flexibility
This allows containers to reject items based on their content, without having to resort to a panic. The use case is containers which are polymorphic, but don't support different item types, as encountered e.g. in XEP-0060 PubSub publish vs. retract events.
This commit is contained in:
parent
5135065690
commit
d623b6ab9b
|
@ -800,3 +800,25 @@ impl<T> ElementCodec<T> for T {
|
|||
value
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for fallible extension.
|
||||
///
|
||||
/// You probably won't need to implement this---it is automatically implemented
|
||||
/// for all containers which implement [`std::iter::Extend`].
|
||||
///
|
||||
/// The only useful case are containers where an extension may fail because of
|
||||
/// data reasons, e.g. if you collect elements of multiple types but it can
|
||||
/// only contain a single type at a time.
|
||||
pub trait TryExtend<A> {
|
||||
/// Attempt extending the container with the given iterator.
|
||||
///
|
||||
/// Upon error, the container may be partially extended.
|
||||
fn try_extend<T: IntoIterator<Item = A>>(&mut self, iter: T) -> Result<(), self::error::Error>;
|
||||
}
|
||||
|
||||
impl<A, T: Extend<A>> TryExtend<A> for T {
|
||||
fn try_extend<I: IntoIterator<Item = A>>(&mut self, iter: I) -> Result<(), self::error::Error> {
|
||||
self.extend(iter);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -501,8 +501,7 @@ impl Field for ChildField {
|
|||
<#ty as IntoIterator>::Item
|
||||
})
|
||||
.expect("failed to construct item type");
|
||||
let ty_extend =
|
||||
quote_spanned! {ty_span=> <#ty as ::std::iter::Extend<#item_ty>>::extend};
|
||||
let ty_try_extend = quote_spanned! {ty_span=> <#ty as ::xmpp_parsers_core::TryExtend<#item_ty>>::try_extend};
|
||||
match self.extract {
|
||||
Some(ref extract) => {
|
||||
let extract = extract.build_extract(
|
||||
|
@ -517,7 +516,7 @@ impl Field for ChildField {
|
|||
childiter: quote! {
|
||||
residual = match #extract {
|
||||
Ok(v) => {
|
||||
#ty_extend(&mut #tempname, [v]);
|
||||
#ty_try_extend(&mut #tempname, [v])?;
|
||||
continue;
|
||||
},
|
||||
Err(residual) => residual,
|
||||
|
@ -552,7 +551,7 @@ impl Field for ChildField {
|
|||
let mut residual = match #codec_ty_from_tree(residual) {
|
||||
Ok(item) => {
|
||||
let item = #codec_ty_decode(item);
|
||||
#ty_extend(&mut #tempname, [item]);
|
||||
#ty_try_extend(&mut #tempname, [item])?;
|
||||
continue;
|
||||
},
|
||||
Err(::xmpp_parsers_core::error::Error::TypeMismatch(_, _, e)) => e,
|
||||
|
|
Loading…
Reference in New Issue
Block a user