use proc_macro2::{Ident, TokenStream};
use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream};
use syn::token::Comma;
use syn::{parenthesized, Error, LitStr, Token};
use crate::{parse_utils, AnyValue};
#[derive(Default)]
#[cfg_attr(feature = "debug", derive(Debug))]
pub(super) struct Example {
pub(super) name: String,
pub(super) summary: Option<String>,
pub(super) description: Option<String>,
pub(super) value: Option<AnyValue>,
pub(super) external_value: Option<String>,
}
impl Parse for Example {
fn parse(input: ParseStream) -> syn::Result<Self> {
let example_stream;
parenthesized!(example_stream in input);
let mut example = Example {
name: example_stream.parse::<LitStr>()?.value(),
..Default::default()
};
example_stream.parse::<Token![=]>()?;
let content;
parenthesized!(content in example_stream);
while !content.is_empty() {
let ident = content.parse::<Ident>()?;
let attribute_name = &*ident.to_string();
match attribute_name {
"summary" => {
example.summary = Some(
parse_utils::parse_next(&content, || content.parse::<LitStr>())?
.value(),
)
}
"description" => {
example.description = Some(
parse_utils::parse_next(&content, || content.parse::<LitStr>())?
.value(),
)
}
"value" => {
example.value = Some(parse_utils::parse_next(&content, || {
AnyValue::parse_json(&content)
})?)
}
"external_value" => {
example.external_value = Some(
parse_utils::parse_next(&content, || content.parse::<LitStr>())?
.value(),
)
}
_ => {
return Err(
Error::new(
ident.span(),
format!("unexpected attribute: {attribute_name}, expected one of: summary, description, value, external_value")
)
)
}
}
if !content.is_empty() {
content.parse::<Comma>()?;
}
}
Ok(example)
}
}
impl ToTokens for Example {
fn to_tokens(&self, tokens: &mut TokenStream) {
let summary = self
.summary
.as_ref()
.map(|summary| quote!(.summary(#summary)));
let description = self
.description
.as_ref()
.map(|description| quote!(.description(#description)));
let value = self
.value
.as_ref()
.map(|value| quote!(.value(Some(#value))));
let external_value = self
.external_value
.as_ref()
.map(|external_value| quote!(.external_value(#external_value)));
tokens.extend(quote! {
utoipa::openapi::example::ExampleBuilder::new()
#summary
#description
#value
#external_value
})
}
}