2020-04-12 19:58:05 +00:00
|
|
|
use crate::util::CollectToResult;
|
2020-05-04 19:08:22 +02:00
|
|
|
use proc_macro2::{Ident, TokenStream};
|
2019-10-20 14:49:53 +00:00
|
|
|
use quote::quote;
|
2020-04-12 19:58:05 +00:00
|
|
|
use std::iter;
|
2019-10-20 14:49:53 +00:00
|
|
|
use syn::{
|
2020-05-03 23:25:48 +02:00
|
|
|
parenthesized,
|
2020-05-04 19:08:22 +02:00
|
|
|
parse::{Parse, ParseStream},
|
2019-10-20 14:49:53 +00:00
|
|
|
punctuated::Punctuated,
|
2020-05-03 23:10:19 +02:00
|
|
|
DeriveInput,
|
2019-10-20 14:49:53 +00:00
|
|
|
Generics,
|
|
|
|
Path,
|
2020-05-04 19:08:22 +02:00
|
|
|
Result,
|
2020-05-03 23:25:48 +02:00
|
|
|
Token
|
2019-10-20 14:49:53 +00:00
|
|
|
};
|
|
|
|
|
2020-05-03 23:25:48 +02:00
|
|
|
struct MimeList(Punctuated<Path, Token![,]>);
|
2019-10-20 14:49:53 +00:00
|
|
|
|
|
|
|
impl Parse for MimeList
|
|
|
|
{
|
2020-05-04 19:08:22 +02:00
|
|
|
fn parse(input: ParseStream) -> Result<Self>
|
2019-10-20 14:49:53 +00:00
|
|
|
{
|
|
|
|
let content;
|
|
|
|
let _paren = parenthesized!(content in input);
|
2020-05-03 23:25:48 +02:00
|
|
|
let list = Punctuated::parse_separated_nonempty(&content)?;
|
2019-10-20 14:49:53 +00:00
|
|
|
Ok(Self(list))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "openapi"))]
|
2020-05-04 19:08:22 +02:00
|
|
|
fn impl_openapi_type(_ident : &Ident, _generics : &Generics) -> TokenStream
|
2019-10-20 14:49:53 +00:00
|
|
|
{
|
|
|
|
quote!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "openapi")]
|
2020-05-04 19:08:22 +02:00
|
|
|
fn impl_openapi_type(ident : &Ident, generics : &Generics) -> TokenStream
|
2019-10-20 14:49:53 +00:00
|
|
|
{
|
|
|
|
let krate = super::krate();
|
|
|
|
|
|
|
|
quote! {
|
|
|
|
impl #generics #krate::OpenapiType for #ident #generics
|
|
|
|
{
|
|
|
|
fn schema() -> #krate::OpenapiSchema
|
|
|
|
{
|
|
|
|
use #krate::{export::openapi::*, OpenapiSchema};
|
|
|
|
|
|
|
|
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType {
|
|
|
|
format: VariantOrUnknownOrEmpty::Item(StringFormat::Binary),
|
2020-01-17 21:37:41 +01:00
|
|
|
..Default::default()
|
2019-10-20 14:49:53 +00:00
|
|
|
})))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-04 19:08:22 +02:00
|
|
|
pub fn expand_request_body(input : DeriveInput) -> Result<TokenStream>
|
2019-10-20 14:49:53 +00:00
|
|
|
{
|
|
|
|
let krate = super::krate();
|
|
|
|
let ident = input.ident;
|
|
|
|
let generics = input.generics;
|
|
|
|
|
2020-04-12 19:58:05 +00:00
|
|
|
let types = input.attrs.into_iter()
|
|
|
|
.filter(|attr| attr.path.segments.iter().last().map(|segment| segment.ident.to_string()) == Some("supported_types".to_string()))
|
|
|
|
.flat_map(|attr|
|
|
|
|
syn::parse2::<MimeList>(attr.tokens)
|
2020-05-04 19:08:22 +02:00
|
|
|
.map(|list| Box::new(list.0.into_iter().map(Ok)) as Box<dyn Iterator<Item = Result<Path>>>)
|
2020-04-12 19:58:05 +00:00
|
|
|
.unwrap_or_else(|err| Box::new(iter::once(Err(err)))))
|
|
|
|
.collect_to_result()?;
|
2019-10-20 14:49:53 +00:00
|
|
|
|
|
|
|
let types = match types {
|
|
|
|
ref types if types.is_empty() => quote!(None),
|
|
|
|
types => quote!(Some(vec![#(#types),*]))
|
|
|
|
};
|
|
|
|
|
|
|
|
let impl_openapi_type = impl_openapi_type(&ident, &generics);
|
|
|
|
|
2020-04-07 23:01:26 +02:00
|
|
|
Ok(quote! {
|
2019-10-20 14:49:53 +00:00
|
|
|
impl #generics #krate::RequestBody for #ident #generics
|
|
|
|
where #ident #generics : #krate::FromBody
|
|
|
|
{
|
|
|
|
fn supported_types() -> Option<Vec<#krate::Mime>>
|
|
|
|
{
|
|
|
|
#types
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#impl_openapi_type
|
2020-04-07 23:01:26 +02:00
|
|
|
})
|
|
|
|
}
|