mirror of https://github.com/rwf2/Rocket.git
Support type generics in 'Responder' derive.
This commit is contained in:
parent
fe4d0425e6
commit
1872818570
|
@ -18,13 +18,18 @@ struct FieldAttr {
|
|||
|
||||
pub fn derive_responder(input: proc_macro::TokenStream) -> TokenStream {
|
||||
DeriveGenerator::build_for(input, quote!(impl<'__r, '__o: '__r> ::rocket::response::Responder<'__r, '__o>))
|
||||
.support(Support::Struct | Support::Enum | Support::Lifetime)
|
||||
.support(Support::Struct | Support::Enum | Support::Lifetime | Support::Type)
|
||||
.replace_generic(1, 0)
|
||||
.type_bound(quote!(::rocket::response::Responder<'__r, '__o>))
|
||||
.validator(ValidatorBuild::new()
|
||||
.input_validate(|_, i| match i.generics().lifetimes().count() > 1 {
|
||||
true => Err(i.generics().span().error("only one lifetime is supported")),
|
||||
false => Ok(())
|
||||
})
|
||||
.input_validate(|_, i| match i.generics().type_params().count() > 1 {
|
||||
true => Err(i.generics().span().error("only one type generic is supported")),
|
||||
false => Ok(())
|
||||
})
|
||||
.fields_validate(|_, fields| match fields.is_empty() {
|
||||
true => return Err(fields.span().error("need at least one field")),
|
||||
false => Ok(())
|
||||
|
|
|
@ -545,6 +545,8 @@ pub fn derive_from_form(input: TokenStream) -> TokenStream {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Semantics
|
||||
///
|
||||
/// The derive generates an implementation of the [`Responder`] trait for the
|
||||
/// decorated enum or structure. The derive uses the _first_ field of a variant
|
||||
/// or structure to generate a [`Response`]. As such, the type of the first
|
||||
|
@ -580,6 +582,8 @@ pub fn derive_from_form(input: TokenStream) -> TokenStream {
|
|||
///
|
||||
/// Decorating the first field with `#[response(ignore)]` has no effect.
|
||||
///
|
||||
/// # Field Attribute
|
||||
///
|
||||
/// Additionally, the `response` attribute can be used on named structures and
|
||||
/// enum variants to override the status and/or content-type of the [`Response`]
|
||||
/// produced by the generated implementation. The `response` attribute used in
|
||||
|
@ -646,6 +650,39 @@ pub fn derive_from_form(input: TokenStream) -> TokenStream {
|
|||
/// [`Response`]: ../rocket/struct.Response.html
|
||||
/// [`Response::set_header()`]: ../rocket/response/struct.Response.html#method.set_header
|
||||
/// [`ContentType::parse_flexible()`]: ../rocket/http/struct.ContentType.html#method.parse_flexible
|
||||
///
|
||||
/// # Generics
|
||||
///
|
||||
/// The derive accepts at most one type generic and at most one lifetime
|
||||
/// generic. If a type generic is present, the generated implementation will
|
||||
/// require a bound of `Responder` for the generic. As such, the generic should
|
||||
/// be used as a `Responder`:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate rocket;
|
||||
/// #[derive(Responder)]
|
||||
/// #[response(status = 404, content_type = "html")]
|
||||
/// struct NotFoundHtml<T>(T);
|
||||
/// ```
|
||||
///
|
||||
/// If a lifetime generic is present, it will be used as the second lifetime
|
||||
/// paramter `'o` parameter in `impl Responder<'r, 'o>`:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate rocket;
|
||||
/// #[derive(Responder)]
|
||||
/// #[response(status = 404, content_type = "html")]
|
||||
/// struct NotFoundHtmlString<'o>(&'o str);
|
||||
/// ```
|
||||
///
|
||||
/// Both a type generic and lifetime generic may be used:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate rocket;
|
||||
/// # use rocket::response::Responder;
|
||||
/// #[derive(Responder)]
|
||||
/// struct SomeResult<'o, T>(Result<T, &'o str>);
|
||||
/// ```
|
||||
#[proc_macro_derive(Responder, attributes(response))]
|
||||
pub fn derive_responder(input: TokenStream) -> TokenStream {
|
||||
emit!(derive::responder::derive_responder(input))
|
||||
|
|
Loading…
Reference in New Issue