utoipa_gen/path/
example.rs1use proc_macro2::{Ident, TokenStream};
2use quote::{quote, ToTokens};
3use syn::parse::{Parse, ParseStream};
4use syn::token::Comma;
5use syn::{parenthesized, Error, LitStr, Token};
6
7use crate::{parse_utils, AnyValue};
8
9#[derive(Default)]
11#[cfg_attr(feature = "debug", derive(Debug))]
12pub(super) struct Example {
13 pub(super) name: String,
14 pub(super) summary: Option<String>,
15 pub(super) description: Option<String>,
16 pub(super) value: Option<AnyValue>,
17 pub(super) external_value: Option<String>,
18}
19
20impl Parse for Example {
21 fn parse(input: ParseStream) -> syn::Result<Self> {
22 let example_stream;
23 parenthesized!(example_stream in input);
24 let mut example = Example {
25 name: example_stream.parse::<LitStr>()?.value(),
26 ..Default::default()
27 };
28 example_stream.parse::<Token![=]>()?;
29
30 let content;
31 parenthesized!(content in example_stream);
32
33 while !content.is_empty() {
34 let ident = content.parse::<Ident>()?;
35 let attribute_name = &*ident.to_string();
36 match attribute_name {
37 "summary" => {
38 example.summary = Some(
39 parse_utils::parse_next(&content, || content.parse::<LitStr>())?
40 .value(),
41 )
42 }
43 "description" => {
44 example.description = Some(
45 parse_utils::parse_next(&content, || content.parse::<LitStr>())?
46 .value(),
47 )
48 }
49 "value" => {
50 example.value = Some(parse_utils::parse_next(&content, || {
51 AnyValue::parse_json(&content)
52 })?)
53 }
54 "external_value" => {
55 example.external_value = Some(
56 parse_utils::parse_next(&content, || content.parse::<LitStr>())?
57 .value(),
58 )
59 }
60 _ => {
61 return Err(
62 Error::new(
63 ident.span(),
64 format!("unexpected attribute: {attribute_name}, expected one of: summary, description, value, external_value")
65 )
66 )
67 }
68 }
69
70 if !content.is_empty() {
71 content.parse::<Comma>()?;
72 }
73 }
74
75 Ok(example)
76 }
77}
78
79impl ToTokens for Example {
80 fn to_tokens(&self, tokens: &mut TokenStream) {
81 let summary = self
82 .summary
83 .as_ref()
84 .map(|summary| quote!(.summary(#summary)));
85 let description = self
86 .description
87 .as_ref()
88 .map(|description| quote!(.description(#description)));
89 let value = self
90 .value
91 .as_ref()
92 .map(|value| quote!(.value(Some(#value))));
93 let external_value = self
94 .external_value
95 .as_ref()
96 .map(|external_value| quote!(.external_value(#external_value)));
97
98 tokens.extend(quote! {
99 utoipa::openapi::example::ExampleBuilder::new()
100 #summary
101 #description
102 #value
103 #external_value
104 })
105 }
106}