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 {
|
pub fn derive_responder(input: proc_macro::TokenStream) -> TokenStream {
|
||||||
DeriveGenerator::build_for(input, quote!(impl<'__r, '__o: '__r> ::rocket::response::Responder<'__r, '__o>))
|
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)
|
.replace_generic(1, 0)
|
||||||
|
.type_bound(quote!(::rocket::response::Responder<'__r, '__o>))
|
||||||
.validator(ValidatorBuild::new()
|
.validator(ValidatorBuild::new()
|
||||||
.input_validate(|_, i| match i.generics().lifetimes().count() > 1 {
|
.input_validate(|_, i| match i.generics().lifetimes().count() > 1 {
|
||||||
true => Err(i.generics().span().error("only one lifetime is supported")),
|
true => Err(i.generics().span().error("only one lifetime is supported")),
|
||||||
false => Ok(())
|
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() {
|
.fields_validate(|_, fields| match fields.is_empty() {
|
||||||
true => return Err(fields.span().error("need at least one field")),
|
true => return Err(fields.span().error("need at least one field")),
|
||||||
false => Ok(())
|
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
|
/// The derive generates an implementation of the [`Responder`] trait for the
|
||||||
/// decorated enum or structure. The derive uses the _first_ field of a variant
|
/// 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
|
/// 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.
|
/// Decorating the first field with `#[response(ignore)]` has no effect.
|
||||||
///
|
///
|
||||||
|
/// # Field Attribute
|
||||||
|
///
|
||||||
/// Additionally, the `response` attribute can be used on named structures and
|
/// Additionally, the `response` attribute can be used on named structures and
|
||||||
/// enum variants to override the status and/or content-type of the [`Response`]
|
/// enum variants to override the status and/or content-type of the [`Response`]
|
||||||
/// produced by the generated implementation. The `response` attribute used in
|
/// 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`]: ../rocket/struct.Response.html
|
||||||
/// [`Response::set_header()`]: ../rocket/response/struct.Response.html#method.set_header
|
/// [`Response::set_header()`]: ../rocket/response/struct.Response.html#method.set_header
|
||||||
/// [`ContentType::parse_flexible()`]: ../rocket/http/struct.ContentType.html#method.parse_flexible
|
/// [`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))]
|
#[proc_macro_derive(Responder, attributes(response))]
|
||||||
pub fn derive_responder(input: TokenStream) -> TokenStream {
|
pub fn derive_responder(input: TokenStream) -> TokenStream {
|
||||||
emit!(derive::responder::derive_responder(input))
|
emit!(derive::responder::derive_responder(input))
|
||||||
|
|
Loading…
Reference in New Issue