Remove Response lifetime generation code in ruma_api macro
… and enforce that there are no lifetimes in response {}
This commit is contained in:
parent
0cd87a6c07
commit
f455d4c8ab
@ -7,6 +7,7 @@ use quote::{quote, ToTokens};
|
|||||||
use syn::{
|
use syn::{
|
||||||
braced,
|
braced,
|
||||||
parse::{Parse, ParseStream},
|
parse::{Parse, ParseStream},
|
||||||
|
spanned::Spanned,
|
||||||
Field, FieldValue, Token, Type,
|
Field, FieldValue, Token, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,12 +101,6 @@ impl ToTokens for Api {
|
|||||||
quote!(Request)
|
quote!(Request)
|
||||||
};
|
};
|
||||||
|
|
||||||
let response_try_from_type = if self.response.contains_lifetimes() {
|
|
||||||
quote!(IncomingResponse)
|
|
||||||
} else {
|
|
||||||
quote!(Response)
|
|
||||||
};
|
|
||||||
|
|
||||||
let extract_request_path = if self.request.has_path_fields() {
|
let extract_request_path = if self.request.has_path_fields() {
|
||||||
quote! {
|
quote! {
|
||||||
let path_segments: ::std::vec::Vec<&::std::primitive::str> =
|
let path_segments: ::std::vec::Vec<&::std::primitive::str> =
|
||||||
@ -195,29 +190,19 @@ impl ToTokens for Api {
|
|||||||
TokenStream::new()
|
TokenStream::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
let typed_response_body_decl = if self.response.has_body_fields()
|
let typed_response_body_decl =
|
||||||
|| self.response.newtype_body_field().is_some()
|
if self.response.has_body_fields() || self.response.newtype_body_field().is_some() {
|
||||||
{
|
quote! {
|
||||||
let body_lifetimes = if self.response.has_body_lifetimes() {
|
let response_body: <ResponseBody as ::ruma_api::Outgoing>::Incoming =
|
||||||
// duplicate the anonymous lifetime as many times as needed
|
::ruma_api::try_deserialize!(
|
||||||
let lifetimes =
|
response,
|
||||||
std::iter::repeat(quote! { '_ }).take(self.response.body_lifetime_count());
|
::ruma_api::exports::serde_json::from_slice(response.body().as_slice()),
|
||||||
quote! { < #( #lifetimes, )* >}
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
TokenStream::new()
|
TokenStream::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
quote! {
|
|
||||||
let response_body: <ResponseBody #body_lifetimes as ::ruma_api::Outgoing>::Incoming =
|
|
||||||
::ruma_api::try_deserialize!(
|
|
||||||
response,
|
|
||||||
::ruma_api::exports::serde_json::from_slice(response.body().as_slice()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TokenStream::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
let response_init_fields = self.response.init_fields();
|
let response_init_fields = self.response.init_fields();
|
||||||
|
|
||||||
let serialize_response_headers = self.response.apply_header_fields();
|
let serialize_response_headers = self.response.apply_header_fields();
|
||||||
@ -233,7 +218,6 @@ impl ToTokens for Api {
|
|||||||
|
|
||||||
let error = &self.error;
|
let error = &self.error;
|
||||||
|
|
||||||
let response_lifetimes = self.response.combine_lifetimes();
|
|
||||||
let request_lifetimes = self.request.combine_lifetimes();
|
let request_lifetimes = self.request.combine_lifetimes();
|
||||||
|
|
||||||
let non_auth_endpoint_impl = if requires_authentication.value {
|
let non_auth_endpoint_impl = if requires_authentication.value {
|
||||||
@ -250,9 +234,7 @@ impl ToTokens for Api {
|
|||||||
#[doc = #request_doc]
|
#[doc = #request_doc]
|
||||||
#request_type
|
#request_type
|
||||||
|
|
||||||
impl ::std::convert::TryFrom<::ruma_api::exports::http::Request<Vec<u8>>>
|
impl ::std::convert::TryFrom<::ruma_api::exports::http::Request<Vec<u8>>> for #request_try_from_type {
|
||||||
for #request_try_from_type
|
|
||||||
{
|
|
||||||
type Error = ::ruma_api::error::FromHttpRequestError;
|
type Error = ::ruma_api::error::FromHttpRequestError;
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
@ -276,15 +258,11 @@ impl ToTokens for Api {
|
|||||||
#[doc = #response_doc]
|
#[doc = #response_doc]
|
||||||
#response_type
|
#response_type
|
||||||
|
|
||||||
impl #response_lifetimes ::std::convert::TryFrom<Response #response_lifetimes>
|
impl ::std::convert::TryFrom<Response> for ::ruma_api::exports::http::Response<Vec<u8>> {
|
||||||
for ::ruma_api::exports::http::Response<Vec<u8>>
|
|
||||||
{
|
|
||||||
type Error = ::ruma_api::error::IntoHttpError;
|
type Error = ::ruma_api::error::IntoHttpError;
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn try_from(
|
fn try_from(response: Response) -> ::std::result::Result<Self, Self::Error> {
|
||||||
response: Response #response_lifetimes,
|
|
||||||
) -> ::std::result::Result<Self, Self::Error> {
|
|
||||||
let response = ::ruma_api::exports::http::Response::builder()
|
let response = ::ruma_api::exports::http::Response::builder()
|
||||||
.header(::ruma_api::exports::http::header::CONTENT_TYPE, "application/json")
|
.header(::ruma_api::exports::http::header::CONTENT_TYPE, "application/json")
|
||||||
#serialize_response_headers
|
#serialize_response_headers
|
||||||
@ -296,9 +274,7 @@ impl ToTokens for Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::convert::TryFrom<::ruma_api::exports::http::Response<Vec<u8>>>
|
impl ::std::convert::TryFrom<::ruma_api::exports::http::Response<Vec<u8>>> for Response {
|
||||||
for #response_try_from_type
|
|
||||||
{
|
|
||||||
type Error = ::ruma_api::error::FromHttpResponseError<#error>;
|
type Error = ::ruma_api::error::FromHttpResponseError<#error>;
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
@ -325,7 +301,7 @@ impl ToTokens for Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl #request_lifetimes ::ruma_api::Endpoint for Request #request_lifetimes {
|
impl #request_lifetimes ::ruma_api::Endpoint for Request #request_lifetimes {
|
||||||
type Response = Response #response_lifetimes;
|
type Response = Response;
|
||||||
type ResponseError = #error;
|
type ResponseError = #error;
|
||||||
|
|
||||||
/// Metadata for the `#name` endpoint.
|
/// Metadata for the `#name` endpoint.
|
||||||
@ -465,7 +441,17 @@ impl Parse for RawResponse {
|
|||||||
fields: fields
|
fields: fields
|
||||||
.parse_terminated::<Field, Token![,]>(Field::parse_named)?
|
.parse_terminated::<Field, Token![,]>(Field::parse_named)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.map(|f| {
|
||||||
|
if util::has_lifetime(&f.ty) {
|
||||||
|
Err(syn::Error::new(
|
||||||
|
f.ident.span(),
|
||||||
|
"Lifetimes on Response fields cannot be supported until GAT are stable",
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ impl Request {
|
|||||||
|
|
||||||
/// The combination of every fields unique lifetime annotation.
|
/// The combination of every fields unique lifetime annotation.
|
||||||
pub fn combine_lifetimes(&self) -> TokenStream {
|
pub fn combine_lifetimes(&self) -> TokenStream {
|
||||||
util::generics_to_tokens(
|
util::unique_lifetimes_to_tokens(
|
||||||
self.lifetimes
|
self.lifetimes
|
||||||
.body
|
.body
|
||||||
.iter()
|
.iter()
|
||||||
@ -151,12 +151,12 @@ impl Request {
|
|||||||
|
|
||||||
/// The lifetimes on fields with the `query` attribute.
|
/// The lifetimes on fields with the `query` attribute.
|
||||||
pub fn query_lifetimes(&self) -> TokenStream {
|
pub fn query_lifetimes(&self) -> TokenStream {
|
||||||
util::generics_to_tokens(self.lifetimes.query.iter())
|
util::unique_lifetimes_to_tokens(self.lifetimes.query.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The lifetimes on fields with the `body` attribute.
|
/// The lifetimes on fields with the `body` attribute.
|
||||||
pub fn body_lifetimes(&self) -> TokenStream {
|
pub fn body_lifetimes(&self) -> TokenStream {
|
||||||
util::generics_to_tokens(self.lifetimes.body.iter())
|
util::unique_lifetimes_to_tokens(self.lifetimes.body.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// The lifetimes on fields with the `header` attribute.
|
// /// The lifetimes on fields with the `header` attribute.
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
//! Details of the `response` section of the procedural macro.
|
//! Details of the `response` section of the procedural macro.
|
||||||
|
|
||||||
use std::{collections::BTreeSet, convert::TryFrom, mem};
|
use std::{convert::TryFrom, mem};
|
||||||
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{quote, quote_spanned, ToTokens};
|
use quote::{quote, quote_spanned, ToTokens};
|
||||||
use syn::{spanned::Spanned, Field, Ident, Lifetime};
|
use syn::{spanned::Spanned, Field, Ident};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{
|
api::{
|
||||||
@ -14,19 +14,10 @@ use crate::{
|
|||||||
util,
|
util,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
|
||||||
pub struct ResponseLifetimes {
|
|
||||||
body: BTreeSet<Lifetime>,
|
|
||||||
header: BTreeSet<Lifetime>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The result of processing the `response` section of the macro.
|
/// The result of processing the `response` section of the macro.
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
/// The fields of the response.
|
/// The fields of the response.
|
||||||
fields: Vec<ResponseField>,
|
fields: Vec<ResponseField>,
|
||||||
|
|
||||||
/// The collected lifetime identifiers from the declared fields.
|
|
||||||
lifetimes: ResponseLifetimes,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
@ -40,36 +31,6 @@ impl Response {
|
|||||||
self.fields.iter().any(|field| field.is_header())
|
self.fields.iter().any(|field| field.is_header())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether any `body` field has a lifetime annotation.
|
|
||||||
pub fn has_body_lifetimes(&self) -> bool {
|
|
||||||
!self.lifetimes.body.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The number of unique lifetime annotations for `body` fields.
|
|
||||||
pub fn body_lifetime_count(&self) -> usize {
|
|
||||||
self.lifetimes.body.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether any field has a lifetime annotation.
|
|
||||||
pub fn contains_lifetimes(&self) -> bool {
|
|
||||||
!(self.lifetimes.body.is_empty() && self.lifetimes.header.is_empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn combine_lifetimes(&self) -> TokenStream {
|
|
||||||
util::generics_to_tokens(
|
|
||||||
self.lifetimes
|
|
||||||
.body
|
|
||||||
.iter()
|
|
||||||
.chain(self.lifetimes.header.iter())
|
|
||||||
.collect::<BTreeSet<_>>()
|
|
||||||
.into_iter(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn body_lifetimes(&self) -> TokenStream {
|
|
||||||
util::generics_to_tokens(self.lifetimes.body.iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Produces code for a response struct initializer.
|
/// Produces code for a response struct initializer.
|
||||||
pub fn init_fields(&self) -> TokenStream {
|
pub fn init_fields(&self) -> TokenStream {
|
||||||
let mut fields = vec![];
|
let mut fields = vec![];
|
||||||
@ -196,7 +157,6 @@ impl TryFrom<RawResponse> for Response {
|
|||||||
|
|
||||||
fn try_from(raw: RawResponse) -> syn::Result<Self> {
|
fn try_from(raw: RawResponse) -> syn::Result<Self> {
|
||||||
let mut newtype_body_field = None;
|
let mut newtype_body_field = None;
|
||||||
let mut lifetimes = ResponseLifetimes::default();
|
|
||||||
|
|
||||||
let fields = raw
|
let fields = raw
|
||||||
.fields
|
.fields
|
||||||
@ -247,22 +207,12 @@ impl TryFrom<RawResponse> for Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(match field_kind.unwrap_or(ResponseFieldKind::Body) {
|
Ok(match field_kind.unwrap_or(ResponseFieldKind::Body) {
|
||||||
ResponseFieldKind::Body => {
|
ResponseFieldKind::Body => ResponseField::Body(field),
|
||||||
util::collect_lifetime_ident(&mut lifetimes.body, &field.ty);
|
|
||||||
ResponseField::Body(field)
|
|
||||||
}
|
|
||||||
ResponseFieldKind::Header => {
|
ResponseFieldKind::Header => {
|
||||||
util::collect_lifetime_ident(&mut lifetimes.header, &field.ty);
|
|
||||||
ResponseField::Header(field, header.expect("missing header name"))
|
ResponseField::Header(field, header.expect("missing header name"))
|
||||||
}
|
}
|
||||||
ResponseFieldKind::NewtypeBody => {
|
ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field),
|
||||||
util::collect_lifetime_ident(&mut lifetimes.body, &field.ty);
|
ResponseFieldKind::NewtypeRawBody => ResponseField::NewtypeRawBody(field),
|
||||||
ResponseField::NewtypeBody(field)
|
|
||||||
}
|
|
||||||
ResponseFieldKind::NewtypeRawBody => {
|
|
||||||
util::collect_lifetime_ident(&mut lifetimes.body, &field.ty);
|
|
||||||
ResponseField::NewtypeRawBody(field)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<syn::Result<Vec<_>>>()?;
|
.collect::<syn::Result<Vec<_>>>()?;
|
||||||
@ -275,7 +225,7 @@ impl TryFrom<RawResponse> for Response {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self { fields, lifetimes })
|
Ok(Self { fields })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,52 +240,35 @@ impl ToTokens for Response {
|
|||||||
quote! { { #(#fields),* } }
|
quote! { { #(#fields),* } }
|
||||||
};
|
};
|
||||||
|
|
||||||
let (derive_deserialize, def) =
|
let def = if let Some(body_field) = self.fields.iter().find(|f| f.is_newtype_body()) {
|
||||||
if let Some(body_field) = self.fields.iter().find(|f| f.is_newtype_body()) {
|
let field = Field { ident: None, colon_token: None, ..body_field.field().clone() };
|
||||||
let field = Field { ident: None, colon_token: None, ..body_field.field().clone() };
|
|
||||||
|
|
||||||
// Though we don't track the difference between new type body and body
|
quote! { (#field); }
|
||||||
// for lifetimes, the outer check and the macro failing if it encounters
|
} else if self.has_body_fields() {
|
||||||
// an illegal combination of field attributes, is enough to guarantee
|
let fields = self.fields.iter().filter(|f| f.is_body());
|
||||||
// `body_lifetimes` correctness.
|
|
||||||
let (derive_deserialize, lifetimes) = if self.has_body_lifetimes() {
|
|
||||||
(TokenStream::new(), self.body_lifetimes())
|
|
||||||
} else {
|
|
||||||
(quote!(::ruma_api::exports::serde::Deserialize), TokenStream::new())
|
|
||||||
};
|
|
||||||
|
|
||||||
(derive_deserialize, quote! { #lifetimes (#field); })
|
let fields = fields.map(ResponseField::field);
|
||||||
} else if self.has_body_fields() {
|
|
||||||
let fields = self.fields.iter().filter(|f| f.is_body());
|
|
||||||
let (derive_deserialize, lifetimes) = if self.has_body_lifetimes() {
|
|
||||||
(TokenStream::new(), self.body_lifetimes())
|
|
||||||
} else {
|
|
||||||
(quote!(::ruma_api::exports::serde::Deserialize), TokenStream::new())
|
|
||||||
};
|
|
||||||
|
|
||||||
let fields = fields.map(ResponseField::field);
|
quote! { { #(#fields),* } }
|
||||||
|
} else {
|
||||||
(derive_deserialize, quote!( #lifetimes { #(#fields),* }))
|
quote! { {} }
|
||||||
} else {
|
};
|
||||||
(TokenStream::new(), quote!({}))
|
|
||||||
};
|
|
||||||
|
|
||||||
let response_body_struct = quote! {
|
let response_body_struct = quote! {
|
||||||
/// Data in the response body.
|
/// Data in the response body.
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
::ruma_api::Outgoing,
|
::ruma_api::Outgoing,
|
||||||
|
::ruma_api::exports::serde::Deserialize,
|
||||||
::ruma_api::exports::serde::Serialize,
|
::ruma_api::exports::serde::Serialize,
|
||||||
#derive_deserialize
|
|
||||||
)]
|
)]
|
||||||
struct ResponseBody #def
|
struct ResponseBody #def
|
||||||
};
|
};
|
||||||
|
|
||||||
let response_generics = self.combine_lifetimes();
|
|
||||||
let response = quote! {
|
let response = quote! {
|
||||||
#[derive(Debug, Clone, ::ruma_api::Outgoing)]
|
#[derive(Debug, Clone, ::ruma_api::Outgoing)]
|
||||||
#[incoming_no_deserialize]
|
#[incoming_no_deserialize]
|
||||||
pub struct Response #response_generics #response_def
|
pub struct Response #response_def
|
||||||
|
|
||||||
#response_body_struct
|
#response_body_struct
|
||||||
};
|
};
|
||||||
|
@ -68,8 +68,10 @@ pub fn collect_lifetime_ident(lifetimes: &mut BTreeSet<Lifetime>, ty: &Type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a `TokenStream` of lifetime identifiers `<'lifetime>`.
|
/// Generates a `TokenStream` of lifetime identifiers `<'lifetime>`.
|
||||||
pub fn generics_to_tokens<'a, I: Iterator<Item = &'a Lifetime>>(lifetimes: I) -> TokenStream {
|
pub fn unique_lifetimes_to_tokens<'a, I: Iterator<Item = &'a Lifetime>>(
|
||||||
let lifetimes = lifetimes.collect::<Vec<_>>();
|
lifetimes: I,
|
||||||
|
) -> TokenStream {
|
||||||
|
let lifetimes = lifetimes.collect::<BTreeSet<_>>();
|
||||||
if lifetimes.is_empty() {
|
if lifetimes.is_empty() {
|
||||||
TokenStream::new()
|
TokenStream::new()
|
||||||
} else {
|
} else {
|
||||||
@ -78,6 +80,65 @@ pub fn generics_to_tokens<'a, I: Iterator<Item = &'a Lifetime>>(lifetimes: I) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_lifetime(ty: &Type) -> bool {
|
||||||
|
match ty {
|
||||||
|
Type::Path(TypePath { path, .. }) => {
|
||||||
|
let mut found = false;
|
||||||
|
for seg in &path.segments {
|
||||||
|
match &seg.arguments {
|
||||||
|
PathArguments::AngleBracketed(AngleBracketedGenericArguments {
|
||||||
|
args, ..
|
||||||
|
}) => {
|
||||||
|
for gen in args {
|
||||||
|
if let GenericArgument::Type(ty) = gen {
|
||||||
|
if has_lifetime(&ty) {
|
||||||
|
found = true;
|
||||||
|
};
|
||||||
|
} else if let GenericArgument::Lifetime(_) = gen {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PathArguments::Parenthesized(ParenthesizedGenericArguments {
|
||||||
|
inputs, ..
|
||||||
|
}) => {
|
||||||
|
for ty in inputs {
|
||||||
|
if has_lifetime(ty) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found
|
||||||
|
}
|
||||||
|
Type::Reference(TypeReference { elem, lifetime, .. }) => {
|
||||||
|
if lifetime.is_some() {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
has_lifetime(&elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::Tuple(TypeTuple { elems, .. }) => {
|
||||||
|
let mut found = false;
|
||||||
|
for ty in elems {
|
||||||
|
if has_lifetime(ty) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found
|
||||||
|
}
|
||||||
|
Type::Paren(TypeParen { elem, .. }) => has_lifetime(&elem),
|
||||||
|
Type::Group(TypeGroup { elem, .. }) => has_lifetime(&*elem),
|
||||||
|
Type::Ptr(TypePtr { elem, .. }) => has_lifetime(&*elem),
|
||||||
|
Type::Slice(TypeSlice { elem, .. }) => has_lifetime(&*elem),
|
||||||
|
Type::Array(TypeArray { elem, .. }) => has_lifetime(&*elem),
|
||||||
|
Type::BareFn(TypeBareFn { lifetimes: Some(syn::BoundLifetimes { .. }), .. }) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The first item in the tuple generates code for the request path from
|
/// The first item in the tuple generates code for the request path from
|
||||||
/// the `Metadata` and `Request` structs. The second item in the returned tuple
|
/// the `Metadata` and `Request` structs. The second item in the returned tuple
|
||||||
/// is the code to generate a Request struct field created from any segments
|
/// is the code to generate a Request struct field created from any segments
|
||||||
|
@ -85,9 +85,9 @@ mod full_request_response {
|
|||||||
|
|
||||||
response: {
|
response: {
|
||||||
#[ruma_api(body)]
|
#[ruma_api(body)]
|
||||||
pub thing: OtherThing<'a>,
|
pub thing: Vec<String>,
|
||||||
#[ruma_api(header = CONTENT_TYPE)]
|
#[ruma_api(header = CONTENT_TYPE)]
|
||||||
pub stuff: &'a str,
|
pub stuff: String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,8 +95,6 @@ mod full_request_response {
|
|||||||
mod full_request_response_with_query_map {
|
mod full_request_response_with_query_map {
|
||||||
use ruma_api::ruma_api;
|
use ruma_api::ruma_api;
|
||||||
|
|
||||||
use super::{IncomingOtherThing, OtherThing};
|
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata: {
|
metadata: {
|
||||||
description: "Does something.",
|
description: "Does something.",
|
||||||
@ -119,9 +117,9 @@ mod full_request_response_with_query_map {
|
|||||||
|
|
||||||
response: {
|
response: {
|
||||||
#[ruma_api(body)]
|
#[ruma_api(body)]
|
||||||
pub thing: OtherThing<'a>,
|
pub thing: String,
|
||||||
#[ruma_api(header = CONTENT_TYPE)]
|
#[ruma_api(header = CONTENT_TYPE)]
|
||||||
pub stuff: &'a str,
|
pub stuff: String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user