mirror of https://gitlab.com/xmpp-rs/xmpp-rs.git
xso_proc: implement normalize_with option on attribute enums
Needed for the `http_upload::Header` enum, because HTTP headers are case-insensitive.
This commit is contained in:
parent
cac4e08484
commit
57b72e5a27
|
@ -1,3 +1,4 @@
|
|||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::core::{
|
||||
|
@ -837,3 +838,28 @@ fn attribute_switched_enum_fallback() {
|
|||
other => panic!("unexpected result: {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_lower(v: &str) -> Cow<'_, str> {
|
||||
let mut v = v.to_owned();
|
||||
v.make_ascii_lowercase();
|
||||
v.into()
|
||||
}
|
||||
|
||||
#[derive(FromXml, IntoXml, PartialEq, Clone, Debug)]
|
||||
#[xml(namespace = self::TEST_NS1, name = "attr-switched-enum-norm", attribute = "key", exhaustive, normalize_with = to_lower)]
|
||||
pub enum AttributeSwitchedEnumNormalized {
|
||||
#[xml(value = "variant-1")]
|
||||
Variant1,
|
||||
#[xml(value = "variant-2")]
|
||||
Variant2,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attribute_switched_enum_normalized() {
|
||||
match crate::util::test::parse_str::<AttributeSwitchedEnumNormalized>(
|
||||
"<attr-switched-enum-norm xmlns='urn:uuid:41854041-fa04-4e2b-94ae-ffaefb6b24e2' key='VarIaNT-2'/>",
|
||||
) {
|
||||
Ok(v) => assert_eq!(v, AttributeSwitchedEnumNormalized::Variant2),
|
||||
other => panic!("unexpected result: {:?}", other),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -453,6 +453,10 @@ struct XmlAttributeSwitched {
|
|||
/// The name of the XML attribute to read.
|
||||
attribute_name: LitStr,
|
||||
|
||||
/// Function, if any, to normalize the attribute value with, before
|
||||
/// matching.
|
||||
normalize_with: Option<Path>,
|
||||
|
||||
/// The enum's variants.
|
||||
variants: Vec<StrMatchedVariant>,
|
||||
}
|
||||
|
@ -472,6 +476,7 @@ impl XmlAttributeSwitched {
|
|||
namespace: StaticNamespace,
|
||||
name: Name,
|
||||
attribute_name: LitStr,
|
||||
normalize_with: Option<Path>,
|
||||
input: I,
|
||||
) -> Result<Self> {
|
||||
let mut variants = Vec::with_capacity(input.size_hint().1.unwrap_or(0));
|
||||
|
@ -507,6 +512,7 @@ impl XmlAttributeSwitched {
|
|||
namespace,
|
||||
name,
|
||||
attribute_name,
|
||||
normalize_with,
|
||||
variants,
|
||||
})
|
||||
}
|
||||
|
@ -584,9 +590,19 @@ impl XmlAttributeSwitched {
|
|||
attribute_name, enum_ident,
|
||||
);
|
||||
|
||||
let normalize = match self.normalize_with {
|
||||
Some(normalize_with) => quote! {
|
||||
let attr_value = attr_value.map(|value| #normalize_with(value));
|
||||
let attr_value = attr_value.as_ref().map(|value| ::std::borrow::Borrow::<str>::borrow(value));
|
||||
},
|
||||
None => quote! {},
|
||||
};
|
||||
|
||||
Ok(quote! {
|
||||
if #residual.is(#xml_name, #xml_namespace) {
|
||||
match #residual.attr(#attribute_name) {
|
||||
let attr_value = #residual.attr(#attribute_name);
|
||||
#normalize
|
||||
match attr_value {
|
||||
Some(v) => match v {
|
||||
#iter
|
||||
#fallback
|
||||
|
@ -886,6 +902,13 @@ impl EnumDef {
|
|||
));
|
||||
}
|
||||
|
||||
if let Some(normalize_with) = meta.normalize_with {
|
||||
return Err(syn::Error::new_spanned(
|
||||
normalize_with,
|
||||
"`normalize_with` option is only allowed on attribute value switched enums",
|
||||
));
|
||||
};
|
||||
|
||||
return Ok(Self {
|
||||
validate,
|
||||
prepare,
|
||||
|
@ -912,6 +935,12 @@ impl EnumDef {
|
|||
|
||||
let name = match meta.name {
|
||||
None => {
|
||||
if let Some(normalize_with) = meta.normalize_with {
|
||||
return Err(syn::Error::new_spanned(
|
||||
normalize_with,
|
||||
"`normalize_with` option is only allowed on attribute value switched enums",
|
||||
));
|
||||
};
|
||||
return Ok(Self {
|
||||
prepare,
|
||||
validate,
|
||||
|
@ -940,6 +969,7 @@ impl EnumDef {
|
|||
namespace,
|
||||
name.into(),
|
||||
attribute_name,
|
||||
meta.normalize_with,
|
||||
input,
|
||||
)?),
|
||||
})
|
||||
|
|
|
@ -351,6 +351,9 @@ pub(crate) struct XmlCompoundMeta {
|
|||
/// The value assigned to `prepare` inside `#[xml(..)]`, if any.
|
||||
pub(crate) prepare: Option<Path>,
|
||||
|
||||
/// The value assigned to `normalize_with` inside `#[xml(..)]`, if any.
|
||||
pub(crate) normalize_with: Option<Path>,
|
||||
|
||||
/// Flag indicating the presence of `debug` inside `#[xml(..)]`
|
||||
pub(crate) debug: Flag,
|
||||
}
|
||||
|
@ -371,6 +374,7 @@ impl XmlCompoundMeta {
|
|||
let mut debug = Flag::Absent;
|
||||
let mut validate: Option<Path> = None;
|
||||
let mut prepare: Option<Path> = None;
|
||||
let mut normalize_with: Option<Path> = None;
|
||||
|
||||
attr.parse_nested_meta(|meta| {
|
||||
parse_meta!(
|
||||
|
@ -385,6 +389,8 @@ impl XmlCompoundMeta {
|
|||
ParseFlag("debug", &mut debug),
|
||||
ParseValue("validate", &mut validate),
|
||||
ParseValue("prepare", &mut prepare),
|
||||
ParseValue("normalize_with", &mut normalize_with),
|
||||
ParseValue("normalise_with", &mut normalize_with),
|
||||
)
|
||||
})?;
|
||||
|
||||
|
@ -408,6 +414,7 @@ impl XmlCompoundMeta {
|
|||
exhaustive,
|
||||
prepare,
|
||||
debug,
|
||||
normalize_with,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ impl StructInner {
|
|||
assert!(!meta.exhaustive.is_set());
|
||||
assert!(meta.validate.is_none());
|
||||
assert!(meta.prepare.is_none());
|
||||
assert!(meta.normalize_with.is_none());
|
||||
assert!(!meta.debug.is_set());
|
||||
assert!(!meta.fallback.is_set());
|
||||
assert!(meta.attribute.is_none());
|
||||
|
@ -449,6 +450,13 @@ impl StructDef {
|
|||
));
|
||||
}
|
||||
|
||||
if let Some(normalize_with) = meta.normalize_with.take() {
|
||||
return Err(syn::Error::new_spanned(
|
||||
normalize_with,
|
||||
"`normalize_with` is not allowed on structs",
|
||||
));
|
||||
}
|
||||
|
||||
let validate = meta.validate.take();
|
||||
let prepare = meta.prepare.take();
|
||||
let debug = meta.debug.take();
|
||||
|
|
|
@ -181,6 +181,11 @@ XML attribute matched enums support the following attributes:
|
|||
This attribute has no relation to the Rust standard `#[non_exhaustive]`
|
||||
attribute.
|
||||
|
||||
- `normalize_with = ..`: Optional path to a thing which can be called with a
|
||||
`&str` and which returns a [`std::borrow::Cow`]. If present, the attribute
|
||||
value will be passed through that callable before it will be matched against
|
||||
the enum variants.
|
||||
|
||||
#### XML attribute matched enum variants
|
||||
|
||||
XML attribute matched enum variants support the following attributes:
|
||||
|
|
Loading…
Reference in New Issue