mirror of https://github.com/rwf2/Rocket.git
Allow several 'field' attributes in all derives.
In particular, 'FromFormField' and 'UriDisplayQuery' now allow any number of form 'field' attributes. For the former, multiple 'value's are allowed, all of which are used to match against incoming fields - any match wins. For the latter, multiple 'name' and 'value's are allowed; the first of each is used to render the query value. Additionally, 'UriDisplayQuery' can now be derived for C-like enums. This brings the derive to parity with 'FromFormValue' and allows their unified application on C-like enums. Resolves #843.
This commit is contained in:
parent
fd03417188
commit
c45a83897f
|
@ -19,7 +19,7 @@ proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "3ebe83" }
|
devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "df00b5" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rocket = { version = "0.5.0-dev", path = "../../core/lib" }
|
rocket = { version = "0.5.0-dev", path = "../../core/lib" }
|
||||||
|
|
|
@ -18,7 +18,7 @@ proc-macro = true
|
||||||
indexmap = "1.0"
|
indexmap = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
rocket_http = { version = "0.5.0-dev", path = "../http/" }
|
rocket_http = { version = "0.5.0-dev", path = "../http/" }
|
||||||
devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "3ebe83" }
|
devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "df00b5" }
|
||||||
unicode-xid = "0.2"
|
unicode-xid = "0.2"
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use devise::{*, ext::{TypeExt, SpanDiagnosticExt}};
|
||||||
use syn::visit_mut::VisitMut;
|
use syn::visit_mut::VisitMut;
|
||||||
use syn::visit::Visit;
|
use syn::visit::Visit;
|
||||||
|
|
||||||
use crate::proc_macro2::{TokenStream, TokenTree};
|
use crate::proc_macro2::{TokenStream, TokenTree, Span};
|
||||||
use crate::syn_ext::IdentExt;
|
use crate::syn_ext::IdentExt;
|
||||||
use crate::name::Name;
|
use crate::name::Name;
|
||||||
|
|
||||||
|
@ -26,11 +26,50 @@ impl FieldAttr {
|
||||||
pub(crate) trait FieldExt {
|
pub(crate) trait FieldExt {
|
||||||
fn ident(&self) -> &syn::Ident;
|
fn ident(&self) -> &syn::Ident;
|
||||||
fn field_names(&self) -> Result<Vec<FieldName>>;
|
fn field_names(&self) -> Result<Vec<FieldName>>;
|
||||||
fn one_field_name(&self) -> Result<FieldName>;
|
fn first_field_name(&self) -> Result<FieldName>;
|
||||||
fn stripped_ty(&self) -> syn::Type;
|
fn stripped_ty(&self) -> syn::Type;
|
||||||
fn name_view(&self) -> Result<syn::Expr>;
|
fn name_view(&self) -> Result<syn::Expr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(FromMeta)]
|
||||||
|
pub struct VariantAttr {
|
||||||
|
pub value: Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VariantAttr {
|
||||||
|
const NAME: &'static str = "field";
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait VariantExt {
|
||||||
|
fn first_form_field_value(&self) -> Result<FieldName>;
|
||||||
|
fn form_field_values(&self) -> Result<Vec<FieldName>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VariantExt for Variant<'_> {
|
||||||
|
fn first_form_field_value(&self) -> Result<FieldName> {
|
||||||
|
let first = VariantAttr::from_attrs(VariantAttr::NAME, &self.attrs)?
|
||||||
|
.into_iter()
|
||||||
|
.next();
|
||||||
|
|
||||||
|
Ok(first.map_or_else(
|
||||||
|
|| FieldName::Uncased(Name::from(&self.ident)),
|
||||||
|
|attr| FieldName::Uncased(attr.value)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn form_field_values(&self) -> Result<Vec<FieldName>> {
|
||||||
|
let attr_values = VariantAttr::from_attrs(VariantAttr::NAME, &self.attrs)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|attr| FieldName::Uncased(attr.value))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if attr_values.is_empty() {
|
||||||
|
return Ok(vec![FieldName::Uncased(Name::from(&self.ident))]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(attr_values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromMeta for FieldName {
|
impl FromMeta for FieldName {
|
||||||
fn from_meta(meta: &MetaItem) -> Result<Self> {
|
fn from_meta(meta: &MetaItem) -> Result<Self> {
|
||||||
// These are used during parsing.
|
// These are used during parsing.
|
||||||
|
@ -124,17 +163,9 @@ impl FieldExt for Field<'_> {
|
||||||
Ok(attr_names)
|
Ok(attr_names)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn one_field_name(&self) -> Result<FieldName> {
|
fn first_field_name(&self) -> Result<FieldName> {
|
||||||
let mut names = self.field_names()?.into_iter();
|
let mut names = self.field_names()?.into_iter();
|
||||||
let first = names.next().expect("always have >= 1 name");
|
Ok(names.next().expect("always have >= 1 name"))
|
||||||
|
|
||||||
if let Some(name) = names.next() {
|
|
||||||
return Err(name.span()
|
|
||||||
.error("unexpected second field name")
|
|
||||||
.note("only one field rename is allowed in this context"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(first)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stripped_ty(&self) -> syn::Type {
|
fn stripped_ty(&self) -> syn::Type {
|
||||||
|
@ -293,3 +324,31 @@ pub fn validators<'v>(
|
||||||
|
|
||||||
Ok(exprs)
|
Ok(exprs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn first_duplicate<K: Spanned, V: PartialEq + Spanned>(
|
||||||
|
keys: impl Iterator<Item = K> + Clone,
|
||||||
|
values: impl Fn(&K) -> Result<Vec<V>>,
|
||||||
|
) -> Result<Option<((usize, Span, Span), (usize, Span, Span))>> {
|
||||||
|
let (mut all_values, mut key_map) = (vec![], vec![]);
|
||||||
|
for key in keys {
|
||||||
|
all_values.append(&mut values(&key)?);
|
||||||
|
key_map.push((all_values.len(), key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the key corresponding to all_value index `k`.
|
||||||
|
let key = |k| key_map.iter().find(|(i, _)| k < *i).expect("k < *i");
|
||||||
|
|
||||||
|
for (i, a) in all_values.iter().enumerate() {
|
||||||
|
let rest = all_values.iter().enumerate().skip(i + 1);
|
||||||
|
if let Some((j, b)) = rest.filter(|(_, b)| *b == a).next() {
|
||||||
|
let (a_i, key_a) = key(i);
|
||||||
|
let (b_i, key_b) = key(j);
|
||||||
|
|
||||||
|
let a = (*a_i, key_a.span(), a.span());
|
||||||
|
let b = (*b_i, key_b.span(), b.span());
|
||||||
|
return Ok(Some((a, b)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
|
@ -70,33 +70,19 @@ pub fn derive_from_form(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
return Err(fields.span().error("at least one field is required"));
|
return Err(fields.span().error("at least one field is required"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut names = vec![];
|
if let Some(d) = first_duplicate(fields.iter(), |f| f.field_names())? {
|
||||||
let mut field_map = vec![];
|
let (field_a_i, field_a, name_a) = d.0;
|
||||||
for field in fields.iter() {
|
let (field_b_i, field_b, name_b) = d.1;
|
||||||
names.append(&mut field.field_names()?);
|
|
||||||
field_map.push((names.len(), field));
|
if field_a_i == field_b_i {
|
||||||
|
return Err(field_a.error("field has conflicting names")
|
||||||
|
.span_note(name_a, "this field name...")
|
||||||
|
.span_note(name_b, "...conflicts with this field name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the field corresponding to name index `k`.
|
return Err(name_b.error("field name conflicts with previous name")
|
||||||
let field = |k| field_map.iter().find(|(i, _)| k < *i).expect("k < *i");
|
.span_help(field_b, "declared in this field")
|
||||||
|
.span_note(field_a, "previous field with conflicting name"));
|
||||||
for (i, a) in names.iter().enumerate() {
|
|
||||||
let rest = names.iter().enumerate().skip(i + 1);
|
|
||||||
if let Some((j, b)) = rest.filter(|(_, b)| b == &a).next() {
|
|
||||||
let ((fa_i, field_a), (fb_i, field_b)) = (field(i), field(j));
|
|
||||||
|
|
||||||
if fa_i == fb_i {
|
|
||||||
return Err(field_a.span()
|
|
||||||
.error("field has conflicting names")
|
|
||||||
.span_note(a.span(), "this field name...")
|
|
||||||
.span_note(b.span(), "...conflicts with this name"));
|
|
||||||
} else {
|
|
||||||
return Err(b.span()
|
|
||||||
.error("field name conflicts with previous name")
|
|
||||||
.span_note(field_a.span(), "previous field with conflicting name")
|
|
||||||
.span_help(field_b.span(), "field name is part of this field"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -2,12 +2,7 @@ use devise::{*, ext::SpanDiagnosticExt};
|
||||||
|
|
||||||
use crate::exports::*;
|
use crate::exports::*;
|
||||||
use crate::proc_macro2::TokenStream;
|
use crate::proc_macro2::TokenStream;
|
||||||
use crate::name::Name;
|
use crate::derive::form_field::{VariantExt, first_duplicate};
|
||||||
|
|
||||||
#[derive(FromMeta)]
|
|
||||||
pub struct FieldAttr {
|
|
||||||
value: Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn derive_from_form_field(input: proc_macro::TokenStream) -> TokenStream {
|
pub fn derive_from_form_field(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
DeriveGenerator::build_for(input, quote!(impl<'__v> #_form::FromFormField<'__v>))
|
DeriveGenerator::build_for(input, quote!(impl<'__v> #_form::FromFormField<'__v>))
|
||||||
|
@ -26,47 +21,68 @@ pub fn derive_from_form_field(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
return Err(data.span().error("enum must have at least one variant"));
|
return Err(data.span().error("enum must have at least one variant"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(d) = first_duplicate(data.variants(), |v| v.form_field_values())? {
|
||||||
|
let (variant_a_i, variant_a, value_a) = d.0;
|
||||||
|
let (variant_b_i, variant_b, value_b) = d.1;
|
||||||
|
|
||||||
|
if variant_a_i == variant_b_i {
|
||||||
|
return Err(variant_a.error("variant has conflicting values")
|
||||||
|
.span_note(value_a, "this value...")
|
||||||
|
.span_note(value_b, "...conflicts with this value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(value_b.error("field value conflicts with previous value")
|
||||||
|
.span_help(variant_b, "...declared in this variant")
|
||||||
|
.span_note(variant_a, "previous field with conflicting name"));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
// TODO: Devise should have a try_variant_map.
|
.outer_mapper(quote! {
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use #_http::uncased::AsUncased;
|
||||||
|
})
|
||||||
.inner_mapper(MapperBuild::new()
|
.inner_mapper(MapperBuild::new()
|
||||||
.try_enum_map(|_, data| {
|
.with_output(|_, output| quote! {
|
||||||
let variant_name_sources = data.variants()
|
|
||||||
.map(|v| FieldAttr::one_from_attrs("field", &v.attrs).map(|o| {
|
|
||||||
o.map(|f| f.value).unwrap_or_else(|| Name::from(&v.ident))
|
|
||||||
}))
|
|
||||||
.collect::<Result<Vec<Name>>>()?;
|
|
||||||
|
|
||||||
let variant_name = variant_name_sources.iter()
|
|
||||||
.map(|n| n.as_str())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let builder = data.variants()
|
|
||||||
.map(|v| v.builder(|_| unreachable!("fieldless")));
|
|
||||||
|
|
||||||
let (_ok, _cow) = (std::iter::repeat(_Ok), std::iter::repeat(_Cow));
|
|
||||||
Ok(quote! {
|
|
||||||
fn from_value(
|
fn from_value(
|
||||||
__f: #_form::ValueField<'__v>
|
__f: #_form::ValueField<'__v>
|
||||||
) -> Result<Self, #_form::Errors<'__v>> {
|
) -> Result<Self, #_form::Errors<'__v>> {
|
||||||
#[allow(unused_imports)]
|
|
||||||
use #_http::uncased::AsUncased;
|
|
||||||
|
|
||||||
#(
|
#output
|
||||||
if __f.value.as_uncased() == #variant_name {
|
|
||||||
return #_ok(#builder);
|
|
||||||
}
|
}
|
||||||
)*
|
})
|
||||||
|
.try_enum_map(|mapper, data| {
|
||||||
|
let mut variant_value = vec![];
|
||||||
|
for v in data.variants().map(|v| v.form_field_values()) {
|
||||||
|
variant_value.append(&mut v?);
|
||||||
|
}
|
||||||
|
|
||||||
|
let variant_condition = data.variants()
|
||||||
|
.map(|v| mapper.map_variant(v))
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
|
let (_ok, _cow) = (std::iter::repeat(_Ok), std::iter::repeat(_Cow));
|
||||||
|
Ok(quote! {
|
||||||
|
#(#variant_condition)*
|
||||||
|
|
||||||
const OPTS: &'static [#_Cow<'static, str>] =
|
const OPTS: &'static [#_Cow<'static, str>] =
|
||||||
&[#(#_cow::Borrowed(#variant_name)),*];
|
&[#(#_cow::Borrowed(#variant_value)),*];
|
||||||
|
|
||||||
let _error = #_form::Error::from(OPTS)
|
let _error = #_form::Error::from(OPTS)
|
||||||
.with_name(__f.name)
|
.with_name(__f.name)
|
||||||
.with_value(__f.value);
|
.with_value(__f.value);
|
||||||
|
|
||||||
#_Err(_error)?
|
#_Err(_error)?
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.try_variant_map(|_, variant| {
|
||||||
|
let builder = variant.builder(|_| unreachable!("fieldless"));
|
||||||
|
let value = variant.form_field_values()?;
|
||||||
|
|
||||||
|
Ok(quote_spanned! { variant.span() =>
|
||||||
|
if #(__f.value.as_uncased() == #value)||* {
|
||||||
|
return #_Ok(#builder);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,35 +3,15 @@ use devise::{*, ext::SpanDiagnosticExt};
|
||||||
use rocket_http::uri;
|
use rocket_http::uri;
|
||||||
|
|
||||||
use crate::exports::*;
|
use crate::exports::*;
|
||||||
use crate::derive::form_field::FieldExt;
|
use crate::derive::form_field::{FieldExt, VariantExt};
|
||||||
use crate::proc_macro2::TokenStream;
|
use crate::proc_macro2::TokenStream;
|
||||||
|
|
||||||
const NO_EMPTY_FIELDS: &str = "fieldless structs or variants are not supported";
|
const NO_EMPTY_FIELDS: &str = "fieldless structs are not supported";
|
||||||
const NO_NULLARY: &str = "nullary items are not supported";
|
const NO_NULLARY: &str = "nullary items are not supported";
|
||||||
const NO_EMPTY_ENUMS: &str = "empty enums are not supported";
|
const NO_EMPTY_ENUMS: &str = "empty enums are not supported";
|
||||||
const ONLY_ONE_UNNAMED: &str = "tuple structs or variants must have exactly one field";
|
const ONLY_ONE_UNNAMED: &str = "tuple structs or variants must have exactly one field";
|
||||||
const EXACTLY_ONE_FIELD: &str = "struct must have exactly one field";
|
const EXACTLY_ONE_FIELD: &str = "struct must have exactly one field";
|
||||||
|
|
||||||
fn validate_fields(fields: Fields<'_>) -> Result<()> {
|
|
||||||
if fields.count() == 0 {
|
|
||||||
return Err(fields.parent.span().error(NO_EMPTY_FIELDS))
|
|
||||||
} else if fields.are_unnamed() && fields.count() > 1 {
|
|
||||||
return Err(fields.span().error(ONLY_ONE_UNNAMED));
|
|
||||||
} else if fields.are_unit() {
|
|
||||||
return Err(fields.span().error(NO_NULLARY));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_enum(data: Enum<'_>) -> Result<()> {
|
|
||||||
if data.variants().count() == 0 {
|
|
||||||
return Err(data.brace_token.span.error(NO_EMPTY_ENUMS));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn derive_uri_display_query(input: proc_macro::TokenStream) -> TokenStream {
|
pub fn derive_uri_display_query(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
use crate::http::uri::Query;
|
use crate::http::uri::Query;
|
||||||
|
|
||||||
|
@ -41,8 +21,30 @@ pub fn derive_uri_display_query(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
let uri_display = DeriveGenerator::build_for(input.clone(), quote!(impl #URI_DISPLAY))
|
let uri_display = DeriveGenerator::build_for(input.clone(), quote!(impl #URI_DISPLAY))
|
||||||
.support(Support::Struct | Support::Enum | Support::Type | Support::Lifetime)
|
.support(Support::Struct | Support::Enum | Support::Type | Support::Lifetime)
|
||||||
.validator(ValidatorBuild::new()
|
.validator(ValidatorBuild::new()
|
||||||
.enum_validate(|_, v| validate_enum(v))
|
.enum_validate(|_, data| {
|
||||||
.fields_validate(|_, v| validate_fields(v))
|
if data.variants().count() == 0 {
|
||||||
|
return Err(data.brace_token.span.error(NO_EMPTY_ENUMS));
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.struct_validate(|_, data| {
|
||||||
|
let fields = data.fields();
|
||||||
|
if fields.is_empty() {
|
||||||
|
Err(data.span().error(NO_EMPTY_FIELDS))
|
||||||
|
} else if fields.are_unit() {
|
||||||
|
Err(data.span().error(NO_NULLARY))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.fields_validate(|_, fields| {
|
||||||
|
if fields.are_unnamed() && fields.count() > 1 {
|
||||||
|
Err(fields.span().error(ONLY_ONE_UNNAMED))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
})
|
||||||
)
|
)
|
||||||
.type_bound(URI_DISPLAY)
|
.type_bound(URI_DISPLAY)
|
||||||
.inner_mapper(MapperBuild::new()
|
.inner_mapper(MapperBuild::new()
|
||||||
|
@ -52,11 +54,21 @@ pub fn derive_uri_display_query(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.try_variant_map(|mapper, variant| {
|
||||||
|
if !variant.fields().is_empty() {
|
||||||
|
return mapper::variant_default(mapper, variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = variant.first_form_field_value()?;
|
||||||
|
Ok(quote_spanned! { variant.span() =>
|
||||||
|
f.write_value(#value)?;
|
||||||
|
})
|
||||||
|
})
|
||||||
.try_field_map(|_, field| {
|
.try_field_map(|_, field| {
|
||||||
let span = field.span().into();
|
let span = field.span().into();
|
||||||
let accessor = field.accessor();
|
let accessor = field.accessor();
|
||||||
let tokens = if field.ident.is_some() {
|
let tokens = if field.ident.is_some() {
|
||||||
let name = field.one_field_name()?;
|
let name = field.first_field_name()?;
|
||||||
quote_spanned!(span => f.write_named_value(#name, &#accessor)?;)
|
quote_spanned!(span => f.write_named_value(#name, &#accessor)?;)
|
||||||
} else {
|
} else {
|
||||||
quote_spanned!(span => f.write_value(&#accessor)?;)
|
quote_spanned!(span => f.write_value(&#accessor)?;)
|
||||||
|
|
|
@ -394,8 +394,8 @@ pub fn launch(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
///
|
///
|
||||||
/// As an example, for the `enum` above, the form values `"first"`, `"FIRST"`,
|
/// As an example, for the `enum` above, the form values `"first"`, `"FIRST"`,
|
||||||
/// `"fiRSt"`, and so on would parse as `MyValue::First`, while `"second"` and
|
/// `"fiRSt"`, and so on would parse as `MyValue::First`, while `"second"` and
|
||||||
/// `"third"` would parse as `MyValue::Second` and `MyValue::Third`,
|
/// `"third"` (in any casing) would parse as `MyValue::Second` and
|
||||||
/// respectively.
|
/// `MyValue::Third`, respectively.
|
||||||
///
|
///
|
||||||
/// The `field` field attribute can be used to change the string value that is
|
/// The `field` field attribute can be used to change the string value that is
|
||||||
/// compared against for a given variant:
|
/// compared against for a given variant:
|
||||||
|
@ -408,10 +408,16 @@ pub fn launch(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
/// First,
|
/// First,
|
||||||
/// Second,
|
/// Second,
|
||||||
/// #[field(value = "fourth")]
|
/// #[field(value = "fourth")]
|
||||||
|
/// #[field(value = "fifth")]
|
||||||
/// Third,
|
/// Third,
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// When more than one `value` is specified, matching _any_ value will result in
|
||||||
|
/// parsing the decorated variant. Declaring any two values that are
|
||||||
|
/// case-insensitively equal to any other value or variant name is a
|
||||||
|
/// compile-time error.
|
||||||
|
///
|
||||||
/// The `#[field]` attribute's grammar is:
|
/// The `#[field]` attribute's grammar is:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
|
@ -422,8 +428,8 @@ pub fn launch(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
///
|
///
|
||||||
/// The attribute accepts a single string parameter of name `value`
|
/// The attribute accepts a single string parameter of name `value`
|
||||||
/// corresponding to the string to use to match against for the decorated
|
/// corresponding to the string to use to match against for the decorated
|
||||||
/// variant. In the example above, the the strings `"fourth"`, `"FOUrth"` and so
|
/// variant. In the example above, the the strings `"fourth"`, `"FOUrth"`,
|
||||||
/// on would parse as `MyValue::Third`.
|
/// `"fiFTH"` and so on would parse as `MyValue::Third`.
|
||||||
///
|
///
|
||||||
/// [`FromFormField`]: rocket::form::FromFormField
|
/// [`FromFormField`]: rocket::form::FromFormField
|
||||||
/// [`FromFormField::Error`]: rocket::form::FromFormField::Error
|
/// [`FromFormField::Error`]: rocket::form::FromFormField::Error
|
||||||
|
@ -648,8 +654,8 @@ pub fn derive_responder(input: TokenStream) -> TokenStream {
|
||||||
/// Derive for the [`UriDisplay<Query>`] trait.
|
/// Derive for the [`UriDisplay<Query>`] trait.
|
||||||
///
|
///
|
||||||
/// The [`UriDisplay<Query>`] derive can be applied to enums and structs. When
|
/// The [`UriDisplay<Query>`] derive can be applied to enums and structs. When
|
||||||
/// applied to enums, variants must have at least one field. When applied to
|
/// applied to an enum, the enum must have at least one variant. When applied to
|
||||||
/// structs, the struct must have at least one field.
|
/// a struct, the struct must have at least one field.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
|
@ -678,12 +684,15 @@ pub fn derive_responder(input: TokenStream) -> TokenStream {
|
||||||
/// The derive accepts one field attribute: `field`, with the following syntax:
|
/// The derive accepts one field attribute: `field`, with the following syntax:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// field := 'name' '=' '"' IDENT '"'
|
/// field := 'name' '=' '"' FIELD_NAME '"'
|
||||||
|
/// | 'value' '=' '"' FIELD_VALUE '"'
|
||||||
///
|
///
|
||||||
/// IDENT := valid identifier, as defined by Rust
|
/// FIELD_NAME := valid HTTP field name
|
||||||
|
/// FIELD_VALUE := valid HTTP field value
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// When applied, the attribute looks as follows:
|
/// When applied to a struct, the attribute can only contain `name` and looks
|
||||||
|
/// as follows:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
|
@ -694,15 +703,39 @@ pub fn derive_responder(input: TokenStream) -> TokenStream {
|
||||||
/// name: String,
|
/// name: String,
|
||||||
/// id: usize,
|
/// id: usize,
|
||||||
/// #[field(name = "type")]
|
/// #[field(name = "type")]
|
||||||
|
/// #[field(name = "kind")]
|
||||||
/// kind: Kind,
|
/// kind: Kind,
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The field attribute directs that a different field name be used when calling
|
/// The field attribute directs that a different field name be used when calling
|
||||||
/// [`Formatter::write_named_value()`] for the given field. The value of the
|
/// [`Formatter::write_named_value()`] for the given field. The value of the
|
||||||
/// `name` attribute is used instead of the structure's actual field name. In
|
/// `name` attribute is used instead of the structure's actual field name. If
|
||||||
/// the example above, the field `MyStruct::kind` is rendered with a name of
|
/// more than one `field` attribute is applied to a field, the _first_ name is
|
||||||
/// `type`.
|
/// used. In the example above, the field `MyStruct::kind` is rendered with a
|
||||||
|
/// name of `type`.
|
||||||
|
///
|
||||||
|
/// The attribute can slso be applied to variants of C-like enums; it may only
|
||||||
|
/// contain `value` and looks as follows:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #[macro_use] extern crate rocket;
|
||||||
|
/// #[derive(UriDisplayQuery)]
|
||||||
|
/// enum Kind {
|
||||||
|
/// File,
|
||||||
|
/// #[field(value = "str")]
|
||||||
|
/// #[field(value = "string")]
|
||||||
|
/// String,
|
||||||
|
/// Other
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The field attribute directs that a different value be used when calling
|
||||||
|
/// [`Formatter::write_named_value()`] for the given variant. The value of the
|
||||||
|
/// `value` attribute is used instead of the variant's actual name. If more than
|
||||||
|
/// one `field` attribute is applied to a variant, the _first_ value is used. In
|
||||||
|
/// the example above, the variant `Kind::String` will render with a value of
|
||||||
|
/// `str`.
|
||||||
///
|
///
|
||||||
/// [`UriDisplay<Query>`]: ../rocket/http/uri/trait.UriDisplay.html
|
/// [`UriDisplay<Query>`]: ../rocket/http/uri/trait.UriDisplay.html
|
||||||
/// [`Formatter::write_named_value()`]: ../rocket/http/uri/struct.Formatter.html#method.write_named_value
|
/// [`Formatter::write_named_value()`]: ../rocket/http/uri/struct.Formatter.html#method.write_named_value
|
||||||
|
|
|
@ -62,12 +62,13 @@ fn from_form_value_renames() {
|
||||||
#[derive(Debug, FromFormField)]
|
#[derive(Debug, FromFormField)]
|
||||||
enum Foo {
|
enum Foo {
|
||||||
#[field(value = "foo")]
|
#[field(value = "foo")]
|
||||||
|
#[field(value = "bark")]
|
||||||
Bar,
|
Bar,
|
||||||
#[field(value = ":book")]
|
#[field(value = ":book")]
|
||||||
Book
|
Book
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_parse!("foo", "FOO", "FoO" => Foo::Bar);
|
assert_parse!("foo", "FOO", "FoO", "bark", "BARK", "BaRk" => Foo::Bar);
|
||||||
assert_parse!(":book", ":BOOK", ":bOOk", ":booK" => Foo::Book);
|
assert_parse!(":book", ":BOOK", ":bOOk", ":booK" => Foo::Book);
|
||||||
assert_no_parse!("book", "bar" => Foo);
|
assert_no_parse!("book", "bar" => Foo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,17 +83,17 @@ error: field name conflicts with previous name
|
||||||
33 | foo: usize,
|
33 | foo: usize,
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
|
help: declared in this field
|
||||||
|
--> $DIR/from_form.rs:33:5
|
||||||
|
|
|
||||||
|
33 | foo: usize,
|
||||||
|
| ^^^^^^^^^^
|
||||||
note: previous field with conflicting name
|
note: previous field with conflicting name
|
||||||
--> $DIR/from_form.rs:31:5
|
--> $DIR/from_form.rs:31:5
|
||||||
|
|
|
|
||||||
31 | / #[field(name = "foo")]
|
31 | / #[field(name = "foo")]
|
||||||
32 | | field: String,
|
32 | | field: String,
|
||||||
| |_________________^
|
| |_________________^
|
||||||
help: field name is part of this field
|
|
||||||
--> $DIR/from_form.rs:33:5
|
|
||||||
|
|
|
||||||
33 | foo: usize,
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
note: error occurred while deriving `FromForm`
|
note: error occurred while deriving `FromForm`
|
||||||
--> $DIR/from_form.rs:29:10
|
--> $DIR/from_form.rs:29:10
|
||||||
|
|
|
|
||||||
|
@ -107,18 +107,18 @@ error: field name conflicts with previous name
|
||||||
40 | #[field(name = "hello")]
|
40 | #[field(name = "hello")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
|
help: declared in this field
|
||||||
|
--> $DIR/from_form.rs:40:5
|
||||||
|
|
|
||||||
|
40 | / #[field(name = "hello")]
|
||||||
|
41 | | other: String,
|
||||||
|
| |_________________^
|
||||||
note: previous field with conflicting name
|
note: previous field with conflicting name
|
||||||
--> $DIR/from_form.rs:38:5
|
--> $DIR/from_form.rs:38:5
|
||||||
|
|
|
|
||||||
38 | / #[field(name = "hello")]
|
38 | / #[field(name = "hello")]
|
||||||
39 | | first: String,
|
39 | | first: String,
|
||||||
| |_________________^
|
| |_________________^
|
||||||
help: field name is part of this field
|
|
||||||
--> $DIR/from_form.rs:40:5
|
|
||||||
|
|
|
||||||
40 | / #[field(name = "hello")]
|
|
||||||
41 | | other: String,
|
|
||||||
| |_________________^
|
|
||||||
note: error occurred while deriving `FromForm`
|
note: error occurred while deriving `FromForm`
|
||||||
--> $DIR/from_form.rs:36:10
|
--> $DIR/from_form.rs:36:10
|
||||||
|
|
|
|
||||||
|
@ -132,17 +132,17 @@ error: field name conflicts with previous name
|
||||||
47 | #[field(name = "first")]
|
47 | #[field(name = "first")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
note: previous field with conflicting name
|
help: declared in this field
|
||||||
--> $DIR/from_form.rs:46:5
|
|
||||||
|
|
|
||||||
46 | first: String,
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
help: field name is part of this field
|
|
||||||
--> $DIR/from_form.rs:47:5
|
--> $DIR/from_form.rs:47:5
|
||||||
|
|
|
|
||||||
47 | / #[field(name = "first")]
|
47 | / #[field(name = "first")]
|
||||||
48 | | other: String,
|
48 | | other: String,
|
||||||
| |_________________^
|
| |_________________^
|
||||||
|
note: previous field with conflicting name
|
||||||
|
--> $DIR/from_form.rs:46:5
|
||||||
|
|
|
||||||
|
46 | first: String,
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
note: error occurred while deriving `FromForm`
|
note: error occurred while deriving `FromForm`
|
||||||
--> $DIR/from_form.rs:44:10
|
--> $DIR/from_form.rs:44:10
|
||||||
|
|
|
|
||||||
|
@ -228,7 +228,7 @@ note: this field name...
|
||||||
|
|
|
|
||||||
83 | #[field(name = "blah")]
|
83 | #[field(name = "blah")]
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
note: ...conflicts with this name
|
note: ...conflicts with this field name
|
||||||
--> $DIR/from_form.rs:84:20
|
--> $DIR/from_form.rs:84:20
|
||||||
|
|
|
|
||||||
84 | #[field(name = "blah")]
|
84 | #[field(name = "blah")]
|
||||||
|
|
|
@ -104,100 +104,199 @@ note: error occurred while deriving `FromFormField`
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: field has conflicting names
|
error: variant has conflicting values
|
||||||
--> $DIR/from_form_field.rs:41:5
|
--> $DIR/from_form_field.rs:41:5
|
||||||
|
|
|
|
||||||
41 | / #[field(name = "foo")]
|
41 | / #[field(value = "bar")]
|
||||||
42 | | #[field(name = uncased("FOO"))]
|
42 | | #[field(value = "bar")]
|
||||||
43 | | single: usize,
|
43 | | A,
|
||||||
| |_________________^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: this field name...
|
note: this value...
|
||||||
--> $DIR/from_form_field.rs:41:20
|
--> $DIR/from_form_field.rs:41:21
|
||||||
|
|
|
|
||||||
41 | #[field(name = "foo")]
|
41 | #[field(value = "bar")]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
note: ...conflicts with this name
|
note: ...conflicts with this value
|
||||||
--> $DIR/from_form_field.rs:42:28
|
--> $DIR/from_form_field.rs:42:21
|
||||||
|
|
|
|
||||||
42 | #[field(name = uncased("FOO"))]
|
42 | #[field(value = "bar")]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
note: error occurred while deriving `FromForm`
|
note: error occurred while deriving `FromFormField`
|
||||||
--> $DIR/from_form_field.rs:39:10
|
--> $DIR/from_form_field.rs:39:10
|
||||||
|
|
|
|
||||||
39 | #[derive(FromForm)]
|
39 | #[derive(FromFormField)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: field name conflicts with previous name
|
error: field value conflicts with previous value
|
||||||
--> $DIR/from_form_field.rs:50:20
|
--> $DIR/from_form_field.rs:50:21
|
||||||
|
|
|
|
||||||
50 | #[field(name = "foo")]
|
50 | #[field(value = "BAr")]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
|
help: ...declared in this variant
|
||||||
|
--> $DIR/from_form_field.rs:50:5
|
||||||
|
|
|
||||||
|
50 | / #[field(value = "BAr")]
|
||||||
|
51 | | B,
|
||||||
|
| |_____^
|
||||||
note: previous field with conflicting name
|
note: previous field with conflicting name
|
||||||
--> $DIR/from_form_field.rs:48:5
|
--> $DIR/from_form_field.rs:48:5
|
||||||
|
|
|
|
||||||
48 | / #[field(name = "foo")]
|
48 | / #[field(value = "bar")]
|
||||||
49 | | single: usize,
|
49 | | A,
|
||||||
| |_________________^
|
| |_____^
|
||||||
help: field name is part of this field
|
note: error occurred while deriving `FromFormField`
|
||||||
--> $DIR/from_form_field.rs:50:5
|
|
||||||
|
|
|
||||||
50 | / #[field(name = "foo")]
|
|
||||||
51 | | other: usize,
|
|
||||||
| |________________^
|
|
||||||
note: error occurred while deriving `FromForm`
|
|
||||||
--> $DIR/from_form_field.rs:46:10
|
--> $DIR/from_form_field.rs:46:10
|
||||||
|
|
|
|
||||||
46 | #[derive(FromForm)]
|
46 | #[derive(FromFormField)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: field name conflicts with previous name
|
error: field value conflicts with previous value
|
||||||
--> $DIR/from_form_field.rs:58:5
|
--> $DIR/from_form_field.rs:57:21
|
||||||
|
|
|
|
||||||
58 | hello_there: usize,
|
57 | #[field(value = "a")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^
|
||||||
|
|
|
|
||||||
|
help: ...declared in this variant
|
||||||
|
--> $DIR/from_form_field.rs:57:5
|
||||||
|
|
|
||||||
|
57 | / #[field(value = "a")]
|
||||||
|
58 | | B,
|
||||||
|
| |_____^
|
||||||
note: previous field with conflicting name
|
note: previous field with conflicting name
|
||||||
--> $DIR/from_form_field.rs:56:5
|
--> $DIR/from_form_field.rs:56:5
|
||||||
|
|
|
|
||||||
56 | / #[field(name = uncased("HELLO_THERE"))]
|
56 | A,
|
||||||
57 | | single: usize,
|
| ^
|
||||||
| |_________________^
|
note: error occurred while deriving `FromFormField`
|
||||||
help: field name is part of this field
|
|
||||||
--> $DIR/from_form_field.rs:58:5
|
|
||||||
|
|
|
||||||
58 | hello_there: usize,
|
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
|
||||||
note: error occurred while deriving `FromForm`
|
|
||||||
--> $DIR/from_form_field.rs:54:10
|
--> $DIR/from_form_field.rs:54:10
|
||||||
|
|
|
|
||||||
54 | #[derive(FromForm)]
|
54 | #[derive(FromFormField)]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: variant has conflicting values
|
||||||
|
--> $DIR/from_form_field.rs:80:5
|
||||||
|
|
|
||||||
|
80 | / #[field(value = "FoO")]
|
||||||
|
81 | | #[field(value = "foo")]
|
||||||
|
82 | | A,
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
note: this value...
|
||||||
|
--> $DIR/from_form_field.rs:80:21
|
||||||
|
|
|
||||||
|
80 | #[field(value = "FoO")]
|
||||||
|
| ^^^^^
|
||||||
|
note: ...conflicts with this value
|
||||||
|
--> $DIR/from_form_field.rs:81:21
|
||||||
|
|
|
||||||
|
81 | #[field(value = "foo")]
|
||||||
|
| ^^^^^
|
||||||
|
note: error occurred while deriving `FromFormField`
|
||||||
|
--> $DIR/from_form_field.rs:78:10
|
||||||
|
|
|
||||||
|
78 | #[derive(FromFormField)]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: field has conflicting names
|
||||||
|
--> $DIR/from_form_field.rs:87:5
|
||||||
|
|
|
||||||
|
87 | / #[field(name = "foo")]
|
||||||
|
88 | | #[field(name = uncased("FOO"))]
|
||||||
|
89 | | single: usize,
|
||||||
|
| |_________________^
|
||||||
|
|
|
||||||
|
note: this field name...
|
||||||
|
--> $DIR/from_form_field.rs:87:20
|
||||||
|
|
|
||||||
|
87 | #[field(name = "foo")]
|
||||||
|
| ^^^^^
|
||||||
|
note: ...conflicts with this field name
|
||||||
|
--> $DIR/from_form_field.rs:88:28
|
||||||
|
|
|
||||||
|
88 | #[field(name = uncased("FOO"))]
|
||||||
|
| ^^^^^
|
||||||
|
note: error occurred while deriving `FromForm`
|
||||||
|
--> $DIR/from_form_field.rs:85:10
|
||||||
|
|
|
||||||
|
85 | #[derive(FromForm)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: field name conflicts with previous name
|
error: field name conflicts with previous name
|
||||||
--> $DIR/from_form_field.rs:65:5
|
--> $DIR/from_form_field.rs:96:20
|
||||||
|
|
|
|
||||||
65 | hello_there: usize,
|
96 | #[field(name = "foo")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
|
help: declared in this field
|
||||||
|
--> $DIR/from_form_field.rs:96:5
|
||||||
|
|
|
||||||
|
96 | / #[field(name = "foo")]
|
||||||
|
97 | | other: usize,
|
||||||
|
| |________________^
|
||||||
note: previous field with conflicting name
|
note: previous field with conflicting name
|
||||||
--> $DIR/from_form_field.rs:63:5
|
--> $DIR/from_form_field.rs:94:5
|
||||||
|
|
|
|
||||||
63 | / #[field(name = "hello_there")]
|
94 | / #[field(name = "foo")]
|
||||||
64 | | single: usize,
|
95 | | single: usize,
|
||||||
| |_________________^
|
| |_________________^
|
||||||
help: field name is part of this field
|
|
||||||
--> $DIR/from_form_field.rs:65:5
|
|
||||||
|
|
|
||||||
65 | hello_there: usize,
|
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
|
||||||
note: error occurred while deriving `FromForm`
|
note: error occurred while deriving `FromForm`
|
||||||
--> $DIR/from_form_field.rs:61:10
|
--> $DIR/from_form_field.rs:92:10
|
||||||
|
|
|
|
||||||
61 | #[derive(FromForm)]
|
92 | #[derive(FromForm)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: field name conflicts with previous name
|
||||||
|
--> $DIR/from_form_field.rs:104:5
|
||||||
|
|
|
||||||
|
104 | hello_there: usize,
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: declared in this field
|
||||||
|
--> $DIR/from_form_field.rs:104:5
|
||||||
|
|
|
||||||
|
104 | hello_there: usize,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
note: previous field with conflicting name
|
||||||
|
--> $DIR/from_form_field.rs:102:5
|
||||||
|
|
|
||||||
|
102 | / #[field(name = uncased("HELLO_THERE"))]
|
||||||
|
103 | | single: usize,
|
||||||
|
| |_________________^
|
||||||
|
note: error occurred while deriving `FromForm`
|
||||||
|
--> $DIR/from_form_field.rs:100:10
|
||||||
|
|
|
||||||
|
100 | #[derive(FromForm)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: field name conflicts with previous name
|
||||||
|
--> $DIR/from_form_field.rs:111:5
|
||||||
|
|
|
||||||
|
111 | hello_there: usize,
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: declared in this field
|
||||||
|
--> $DIR/from_form_field.rs:111:5
|
||||||
|
|
|
||||||
|
111 | hello_there: usize,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
note: previous field with conflicting name
|
||||||
|
--> $DIR/from_form_field.rs:109:5
|
||||||
|
|
|
||||||
|
109 | / #[field(name = "hello_there")]
|
||||||
|
110 | | single: usize,
|
||||||
|
| |_________________^
|
||||||
|
note: error occurred while deriving `FromForm`
|
||||||
|
--> $DIR/from_form_field.rs:107:10
|
||||||
|
|
|
||||||
|
107 | #[derive(FromForm)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: fieldless structs or variants are not supported
|
error: fieldless structs are not supported
|
||||||
--> $DIR/uri_display.rs:4:1
|
--> $DIR/uri_display.rs:4:1
|
||||||
|
|
|
|
||||||
4 | struct Foo1;
|
4 | struct Foo1;
|
||||||
|
@ -11,7 +11,7 @@ note: error occurred while deriving `UriDisplay`
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: fieldless structs or variants are not supported
|
error: fieldless structs are not supported
|
||||||
--> $DIR/uri_display.rs:7:1
|
--> $DIR/uri_display.rs:7:1
|
||||||
|
|
|
|
||||||
7 | struct Foo2();
|
7 | struct Foo2();
|
||||||
|
@ -37,19 +37,6 @@ note: error occurred while deriving `UriDisplay`
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: fieldless structs or variants are not supported
|
|
||||||
--> $DIR/uri_display.rs:14:5
|
|
||||||
|
|
|
||||||
14 | Variant,
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
|
||||||
note: error occurred while deriving `UriDisplay`
|
|
||||||
--> $DIR/uri_display.rs:12:10
|
|
||||||
|
|
|
||||||
12 | #[derive(UriDisplayQuery)]
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error: tuple structs or variants must have exactly one field
|
error: tuple structs or variants must have exactly one field
|
||||||
--> $DIR/uri_display.rs:18:12
|
--> $DIR/uri_display.rs:18:12
|
||||||
|
|
|
|
||||||
|
|
|
@ -89,18 +89,18 @@ error: field name conflicts with previous name
|
||||||
33 | foo: usize,
|
33 | foo: usize,
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
|
error: [help] declared in this field
|
||||||
|
--> $DIR/from_form.rs:33:5
|
||||||
|
|
|
||||||
|
33 | foo: usize,
|
||||||
|
| ^^^
|
||||||
|
|
||||||
error: [note] previous field with conflicting name
|
error: [note] previous field with conflicting name
|
||||||
--> $DIR/from_form.rs:31:5
|
--> $DIR/from_form.rs:31:5
|
||||||
|
|
|
|
||||||
31 | #[field(name = "foo")]
|
31 | #[field(name = "foo")]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: [help] field name is part of this field
|
|
||||||
--> $DIR/from_form.rs:33:5
|
|
||||||
|
|
|
||||||
33 | foo: usize,
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: [note] error occurred while deriving `FromForm`
|
error: [note] error occurred while deriving `FromForm`
|
||||||
--> $DIR/from_form.rs:29:10
|
--> $DIR/from_form.rs:29:10
|
||||||
|
|
|
|
||||||
|
@ -115,18 +115,18 @@ error: field name conflicts with previous name
|
||||||
40 | #[field(name = "hello")]
|
40 | #[field(name = "hello")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: [help] declared in this field
|
||||||
|
--> $DIR/from_form.rs:40:5
|
||||||
|
|
|
||||||
|
40 | #[field(name = "hello")]
|
||||||
|
| ^
|
||||||
|
|
||||||
error: [note] previous field with conflicting name
|
error: [note] previous field with conflicting name
|
||||||
--> $DIR/from_form.rs:38:5
|
--> $DIR/from_form.rs:38:5
|
||||||
|
|
|
|
||||||
38 | #[field(name = "hello")]
|
38 | #[field(name = "hello")]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: [help] field name is part of this field
|
|
||||||
--> $DIR/from_form.rs:40:5
|
|
||||||
|
|
|
||||||
40 | #[field(name = "hello")]
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: [note] error occurred while deriving `FromForm`
|
error: [note] error occurred while deriving `FromForm`
|
||||||
--> $DIR/from_form.rs:36:10
|
--> $DIR/from_form.rs:36:10
|
||||||
|
|
|
|
||||||
|
@ -141,18 +141,18 @@ error: field name conflicts with previous name
|
||||||
47 | #[field(name = "first")]
|
47 | #[field(name = "first")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: [help] declared in this field
|
||||||
|
--> $DIR/from_form.rs:47:5
|
||||||
|
|
|
||||||
|
47 | #[field(name = "first")]
|
||||||
|
| ^
|
||||||
|
|
||||||
error: [note] previous field with conflicting name
|
error: [note] previous field with conflicting name
|
||||||
--> $DIR/from_form.rs:46:5
|
--> $DIR/from_form.rs:46:5
|
||||||
|
|
|
|
||||||
46 | first: String,
|
46 | first: String,
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: [help] field name is part of this field
|
|
||||||
--> $DIR/from_form.rs:47:5
|
|
||||||
|
|
|
||||||
47 | #[field(name = "first")]
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: [note] error occurred while deriving `FromForm`
|
error: [note] error occurred while deriving `FromForm`
|
||||||
--> $DIR/from_form.rs:44:10
|
--> $DIR/from_form.rs:44:10
|
||||||
|
|
|
|
||||||
|
@ -243,7 +243,7 @@ error: [note] this field name...
|
||||||
83 | #[field(name = "blah")]
|
83 | #[field(name = "blah")]
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: [note] ...conflicts with this name
|
error: [note] ...conflicts with this field name
|
||||||
--> $DIR/from_form.rs:84:20
|
--> $DIR/from_form.rs:84:20
|
||||||
|
|
|
|
||||||
84 | #[field(name = "blah")]
|
84 | #[field(name = "blah")]
|
||||||
|
|
|
@ -110,106 +110,210 @@ error: [note] error occurred while deriving `FromFormField`
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: field has conflicting names
|
error: variant has conflicting values
|
||||||
--> $DIR/from_form_field.rs:41:5
|
--> $DIR/from_form_field.rs:41:5
|
||||||
|
|
|
|
||||||
41 | #[field(name = "foo")]
|
41 | #[field(value = "bar")]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: [note] this field name...
|
error: [note] this value...
|
||||||
--> $DIR/from_form_field.rs:41:20
|
--> $DIR/from_form_field.rs:41:21
|
||||||
|
|
|
|
||||||
41 | #[field(name = "foo")]
|
41 | #[field(value = "bar")]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: [note] ...conflicts with this name
|
error: [note] ...conflicts with this value
|
||||||
--> $DIR/from_form_field.rs:42:28
|
--> $DIR/from_form_field.rs:42:21
|
||||||
|
|
|
|
||||||
42 | #[field(name = uncased("FOO"))]
|
42 | #[field(value = "bar")]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: [note] error occurred while deriving `FromForm`
|
error: [note] error occurred while deriving `FromFormField`
|
||||||
--> $DIR/from_form_field.rs:39:10
|
--> $DIR/from_form_field.rs:39:10
|
||||||
|
|
|
|
||||||
39 | #[derive(FromForm)]
|
39 | #[derive(FromFormField)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: field name conflicts with previous name
|
error: field value conflicts with previous value
|
||||||
--> $DIR/from_form_field.rs:50:20
|
--> $DIR/from_form_field.rs:50:21
|
||||||
|
|
|
|
||||||
50 | #[field(name = "foo")]
|
50 | #[field(value = "BAr")]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
|
error: [help] ...declared in this variant
|
||||||
|
--> $DIR/from_form_field.rs:50:5
|
||||||
|
|
|
||||||
|
50 | #[field(value = "BAr")]
|
||||||
|
| ^
|
||||||
|
|
||||||
error: [note] previous field with conflicting name
|
error: [note] previous field with conflicting name
|
||||||
--> $DIR/from_form_field.rs:48:5
|
--> $DIR/from_form_field.rs:48:5
|
||||||
|
|
|
|
||||||
48 | #[field(name = "foo")]
|
48 | #[field(value = "bar")]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: [help] field name is part of this field
|
error: [note] error occurred while deriving `FromFormField`
|
||||||
--> $DIR/from_form_field.rs:50:5
|
|
||||||
|
|
|
||||||
50 | #[field(name = "foo")]
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: [note] error occurred while deriving `FromForm`
|
|
||||||
--> $DIR/from_form_field.rs:46:10
|
--> $DIR/from_form_field.rs:46:10
|
||||||
|
|
|
|
||||||
46 | #[derive(FromForm)]
|
46 | #[derive(FromFormField)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: field name conflicts with previous name
|
error: field value conflicts with previous value
|
||||||
--> $DIR/from_form_field.rs:58:5
|
--> $DIR/from_form_field.rs:57:21
|
||||||
|
|
|
|
||||||
58 | hello_there: usize,
|
57 | #[field(value = "a")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^
|
||||||
|
|
||||||
|
error: [help] ...declared in this variant
|
||||||
|
--> $DIR/from_form_field.rs:57:5
|
||||||
|
|
|
||||||
|
57 | #[field(value = "a")]
|
||||||
|
| ^
|
||||||
|
|
||||||
error: [note] previous field with conflicting name
|
error: [note] previous field with conflicting name
|
||||||
--> $DIR/from_form_field.rs:56:5
|
--> $DIR/from_form_field.rs:56:5
|
||||||
|
|
|
|
||||||
56 | #[field(name = uncased("HELLO_THERE"))]
|
56 | A,
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: [help] field name is part of this field
|
error: [note] error occurred while deriving `FromFormField`
|
||||||
--> $DIR/from_form_field.rs:58:5
|
|
||||||
|
|
|
||||||
58 | hello_there: usize,
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: [note] error occurred while deriving `FromForm`
|
|
||||||
--> $DIR/from_form_field.rs:54:10
|
--> $DIR/from_form_field.rs:54:10
|
||||||
|
|
|
|
||||||
54 | #[derive(FromForm)]
|
54 | #[derive(FromFormField)]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: variant has conflicting values
|
||||||
|
--> $DIR/from_form_field.rs:80:5
|
||||||
|
|
|
||||||
|
80 | #[field(value = "FoO")]
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: [note] this value...
|
||||||
|
--> $DIR/from_form_field.rs:80:21
|
||||||
|
|
|
||||||
|
80 | #[field(value = "FoO")]
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: [note] ...conflicts with this value
|
||||||
|
--> $DIR/from_form_field.rs:81:21
|
||||||
|
|
|
||||||
|
81 | #[field(value = "foo")]
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: [note] error occurred while deriving `FromFormField`
|
||||||
|
--> $DIR/from_form_field.rs:78:10
|
||||||
|
|
|
||||||
|
78 | #[derive(FromFormField)]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: field has conflicting names
|
||||||
|
--> $DIR/from_form_field.rs:87:5
|
||||||
|
|
|
||||||
|
87 | #[field(name = "foo")]
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: [note] this field name...
|
||||||
|
--> $DIR/from_form_field.rs:87:20
|
||||||
|
|
|
||||||
|
87 | #[field(name = "foo")]
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: [note] ...conflicts with this field name
|
||||||
|
--> $DIR/from_form_field.rs:88:28
|
||||||
|
|
|
||||||
|
88 | #[field(name = uncased("FOO"))]
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: [note] error occurred while deriving `FromForm`
|
||||||
|
--> $DIR/from_form_field.rs:85:10
|
||||||
|
|
|
||||||
|
85 | #[derive(FromForm)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: field name conflicts with previous name
|
error: field name conflicts with previous name
|
||||||
--> $DIR/from_form_field.rs:65:5
|
--> $DIR/from_form_field.rs:96:20
|
||||||
|
|
|
|
||||||
65 | hello_there: usize,
|
96 | #[field(name = "foo")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: [note] previous field with conflicting name
|
error: [help] declared in this field
|
||||||
--> $DIR/from_form_field.rs:63:5
|
--> $DIR/from_form_field.rs:96:5
|
||||||
|
|
|
|
||||||
63 | #[field(name = "hello_there")]
|
96 | #[field(name = "foo")]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: [help] field name is part of this field
|
error: [note] previous field with conflicting name
|
||||||
--> $DIR/from_form_field.rs:65:5
|
--> $DIR/from_form_field.rs:94:5
|
||||||
|
|
|
|
||||||
65 | hello_there: usize,
|
94 | #[field(name = "foo")]
|
||||||
| ^^^^^^^^^^^
|
| ^
|
||||||
|
|
||||||
error: [note] error occurred while deriving `FromForm`
|
error: [note] error occurred while deriving `FromForm`
|
||||||
--> $DIR/from_form_field.rs:61:10
|
--> $DIR/from_form_field.rs:92:10
|
||||||
|
|
|
|
||||||
61 | #[derive(FromForm)]
|
92 | #[derive(FromForm)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: field name conflicts with previous name
|
||||||
|
--> $DIR/from_form_field.rs:104:5
|
||||||
|
|
|
||||||
|
104 | hello_there: usize,
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: [help] declared in this field
|
||||||
|
--> $DIR/from_form_field.rs:104:5
|
||||||
|
|
|
||||||
|
104 | hello_there: usize,
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: [note] previous field with conflicting name
|
||||||
|
--> $DIR/from_form_field.rs:102:5
|
||||||
|
|
|
||||||
|
102 | #[field(name = uncased("HELLO_THERE"))]
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: [note] error occurred while deriving `FromForm`
|
||||||
|
--> $DIR/from_form_field.rs:100:10
|
||||||
|
|
|
||||||
|
100 | #[derive(FromForm)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: field name conflicts with previous name
|
||||||
|
--> $DIR/from_form_field.rs:111:5
|
||||||
|
|
|
||||||
|
111 | hello_there: usize,
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: [help] declared in this field
|
||||||
|
--> $DIR/from_form_field.rs:111:5
|
||||||
|
|
|
||||||
|
111 | hello_there: usize,
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: [note] previous field with conflicting name
|
||||||
|
--> $DIR/from_form_field.rs:109:5
|
||||||
|
|
|
||||||
|
109 | #[field(name = "hello_there")]
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: [note] error occurred while deriving `FromForm`
|
||||||
|
--> $DIR/from_form_field.rs:107:10
|
||||||
|
|
|
||||||
|
107 | #[derive(FromForm)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: fieldless structs or variants are not supported
|
error: fieldless structs are not supported
|
||||||
--> $DIR/uri_display.rs:4:1
|
--> $DIR/uri_display.rs:4:1
|
||||||
|
|
|
|
||||||
4 | struct Foo1;
|
4 | struct Foo1;
|
||||||
|
@ -12,7 +12,7 @@ error: [note] error occurred while deriving `UriDisplay`
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: fieldless structs or variants are not supported
|
error: fieldless structs are not supported
|
||||||
--> $DIR/uri_display.rs:7:1
|
--> $DIR/uri_display.rs:7:1
|
||||||
|
|
|
|
||||||
7 | struct Foo2();
|
7 | struct Foo2();
|
||||||
|
@ -40,20 +40,6 @@ error: [note] error occurred while deriving `UriDisplay`
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: fieldless structs or variants are not supported
|
|
||||||
--> $DIR/uri_display.rs:14:5
|
|
||||||
|
|
|
||||||
14 | Variant,
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
error: [note] error occurred while deriving `UriDisplay`
|
|
||||||
--> $DIR/uri_display.rs:12:10
|
|
||||||
|
|
|
||||||
12 | #[derive(UriDisplayQuery)]
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error: tuple structs or variants must have exactly one field
|
error: tuple structs or variants must have exactly one field
|
||||||
--> $DIR/uri_display.rs:18:12
|
--> $DIR/uri_display.rs:18:12
|
||||||
|
|
|
|
||||||
|
|
|
@ -36,6 +36,52 @@ enum Bar2 {
|
||||||
A,
|
A,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(FromFormField)]
|
||||||
|
enum Dup1 {
|
||||||
|
#[field(value = "bar")]
|
||||||
|
#[field(value = "bar")]
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromFormField)]
|
||||||
|
enum Dup2 {
|
||||||
|
#[field(value = "bar")]
|
||||||
|
A,
|
||||||
|
#[field(value = "BAr")]
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromFormField)]
|
||||||
|
enum Dup3 {
|
||||||
|
A,
|
||||||
|
#[field(value = "a")]
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromFormField)]
|
||||||
|
enum Dup4 {
|
||||||
|
A,
|
||||||
|
#[field(value = "c")] // this shouldn't error
|
||||||
|
B,
|
||||||
|
#[field(value = "b")] // this shouldn't error
|
||||||
|
C,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromFormField)]
|
||||||
|
enum Dup5 {
|
||||||
|
#[field(value = "a")] // this shouldn't error
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromFormField)]
|
||||||
|
enum Dup6 {
|
||||||
|
#[field(value = "FoO")]
|
||||||
|
#[field(value = "foo")]
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct Renamed0 {
|
struct Renamed0 {
|
||||||
#[field(name = "foo")]
|
#[field(name = "foo")]
|
||||||
|
|
|
@ -112,6 +112,55 @@ fn uri_display_bam() {
|
||||||
assert_uri_display_query!(bam, "foo=hi%20hi&baz=tony");
|
assert_uri_display_query!(bam, "foo=hi%20hi&baz=tony");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uri_display_c_like() {
|
||||||
|
#[derive(UriDisplayQuery)]
|
||||||
|
enum CLike { A, B, C }
|
||||||
|
|
||||||
|
assert_uri_display_query!(CLike::A, "A");
|
||||||
|
assert_uri_display_query!(CLike::B, "B");
|
||||||
|
assert_uri_display_query!(CLike::C, "C");
|
||||||
|
|
||||||
|
#[derive(UriDisplayQuery)]
|
||||||
|
enum CLikeV {
|
||||||
|
#[field(value = "a")]
|
||||||
|
A,
|
||||||
|
#[field(value = "tomato")]
|
||||||
|
#[field(value = "juice")]
|
||||||
|
B,
|
||||||
|
#[field(value = "carrot")]
|
||||||
|
C
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_uri_display_query!(CLikeV::A, "a");
|
||||||
|
assert_uri_display_query!(CLikeV::B, "tomato");
|
||||||
|
assert_uri_display_query!(CLikeV::C, "carrot");
|
||||||
|
|
||||||
|
#[derive(UriDisplayQuery)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
enum CLikeR { r#for, r#type, r#async, #[field(value = "stop")] r#yield }
|
||||||
|
|
||||||
|
assert_uri_display_query!(CLikeR::r#for, "for");
|
||||||
|
assert_uri_display_query!(CLikeR::r#type, "type");
|
||||||
|
assert_uri_display_query!(CLikeR::r#async, "async");
|
||||||
|
assert_uri_display_query!(CLikeR::r#yield, "stop");
|
||||||
|
|
||||||
|
#[derive(UriDisplayQuery)]
|
||||||
|
struct Nested {
|
||||||
|
foo: CLike,
|
||||||
|
bar: CLikeV,
|
||||||
|
last: CLikeR
|
||||||
|
}
|
||||||
|
|
||||||
|
let nested = Nested {
|
||||||
|
foo: CLike::B,
|
||||||
|
bar: CLikeV::B,
|
||||||
|
last: CLikeR::r#type,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_uri_display_query!(nested, "foo=B&bar=tomato&last=type");
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! assert_uri_display_path {
|
macro_rules! assert_uri_display_path {
|
||||||
($v:expr, $s:expr) => (
|
($v:expr, $s:expr) => (
|
||||||
let uri_string = format!("{}", &$v as &dyn UriDisplay<Path>);
|
let uri_string = format!("{}", &$v as &dyn UriDisplay<Path>);
|
||||||
|
|
Loading…
Reference in New Issue