use crate::utoipa::config::OpenApiConfig;
use proc_macro2::TokenStream;
use quote::quote;
#[derive(Debug, Clone)]
pub enum HttpMethod {
Get,
Post,
Put,
Delete,
Patch,
Head,
Options,
Trace,
}
impl HttpMethod {
pub fn to_token(&self) -> TokenStream {
match self {
HttpMethod::Get => quote!(get),
HttpMethod::Post => quote!(post),
HttpMethod::Put => quote!(put),
HttpMethod::Delete => quote!(delete),
HttpMethod::Patch => quote!(patch),
HttpMethod::Head => quote!(head),
HttpMethod::Options => quote!(options),
HttpMethod::Trace => quote!(trace),
}
}
pub fn from_hyper_method(method: &hyper::Method) -> Self {
match method.as_str() {
"GET" => HttpMethod::Get,
"POST" => HttpMethod::Post,
"PUT" => HttpMethod::Put,
"DELETE" => HttpMethod::Delete,
"PATCH" => HttpMethod::Patch,
"HEAD" => HttpMethod::Head,
"OPTIONS" => HttpMethod::Options,
"TRACE" => HttpMethod::Trace,
_ => HttpMethod::Get,
}
}
}
pub fn generate_utoipa_path_attr(
method: &HttpMethod,
path: &str,
config: &OpenApiConfig,
) -> TokenStream {
let method_token = method.to_token();
let summary = config.final_summary().map(|s| quote!(summary = #s,));
let description = config
.final_description()
.map(|d| quote!(description = #d,));
let tags = if !config.final_tags().is_empty() {
let tag_list = config.final_tags();
quote!(tag = #(#tag_list),*,)
} else {
quote!()
};
let deprecated = if config.deprecated {
quote!(deprecated,)
} else {
quote!()
};
let params = generate_params_tokens(config);
let request_body = generate_request_body_tokens(config);
let responses = generate_responses_tokens(config);
quote! {
#[::miko::utoipa::path(
#method_token,
path = #path,
#summary
#description
#tags
#deprecated
#params
#request_body
#responses
)]
}
}
fn generate_params_tokens(config: &OpenApiConfig) -> TokenStream {
let params = config.final_params();
if params.is_empty() {
return quote!();
}
let param_defs = params.iter().map(|p| {
let name = &p.name;
let ty = &p.ty; let location = &p.location;
let desc = p.description.as_ref().map(|d| quote!(description = #d,));
let deprecated = if p.deprecated {
quote!(deprecated,)
} else {
quote!()
};
let example = p.example.as_ref().map(|e| quote!(example = #e,));
quote! {
(#name = #ty, #location, #desc #deprecated #example)
}
});
quote! {
params(
#(#param_defs),*
),
}
}
fn generate_request_body_tokens(config: &OpenApiConfig) -> TokenStream {
if let Some(body) = config.final_request_body() {
let ty = &body.ty;
let content_type = &body.content_type;
let desc = body.description.as_ref().map(|d| quote!(description = #d,));
quote! {
request_body(
content = #ty,
#desc
content_type = #content_type
),
}
} else {
quote!()
}
}
fn generate_responses_tokens(config: &OpenApiConfig) -> TokenStream {
let responses = config.final_responses();
if responses.is_empty() {
return quote!();
}
let resp_defs = responses.iter().map(|r| {
let status = r.status;
let desc = &r.description;
if let Some(ref body) = r.body {
if let Some(ref content_type) = r.content_type {
quote! {
(status = #status, description = #desc, body = #body, content_type = #content_type)
}
} else {
quote! {
(status = #status, description = #desc, body = #body)
}
}
} else {
quote! {
(status = #status, description = #desc)
}
}
});
quote! {
responses(
#(#resp_defs),*
),
}
}