utoipa_gen/
lib.rs

1//! This is **private** utoipa codegen library and is not used alone.
2//!
3//! The library contains macro implementations for utoipa library. Content
4//! of the library documentation is available through **utoipa** library itself.
5//! Consider browsing via the **utoipa** crate so all links will work correctly.
6
7#![warn(missing_docs)]
8#![warn(rustdoc::broken_intra_doc_links)]
9
10use std::{mem, ops::Deref};
11
12use component::schema::Schema;
13use doc_comment::CommentAttributes;
14
15use component::into_params::IntoParams;
16use ext::{PathOperationResolver, PathOperations, PathResolver};
17use openapi::OpenApi;
18use proc_macro::TokenStream;
19use proc_macro_error::{abort, proc_macro_error};
20use quote::{quote, ToTokens, TokenStreamExt};
21
22use proc_macro2::{Group, Ident, Punct, Span, TokenStream as TokenStream2};
23use syn::{
24    bracketed,
25    parse::{Parse, ParseStream},
26    punctuated::Punctuated,
27    token::Bracket,
28    DeriveInput, ExprPath, ItemFn, Lit, LitStr, Member, Token,
29};
30
31mod component;
32mod doc_comment;
33mod ext;
34mod openapi;
35mod path;
36mod schema_type;
37mod security_requirement;
38
39use crate::path::{Path, PathAttr};
40
41use self::{
42    component::{
43        features::{self, Feature},
44        ComponentSchema, ComponentSchemaProps, TypeTree,
45    },
46    path::response::derive::{IntoResponses, ToResponse},
47};
48
49#[proc_macro_error]
50#[proc_macro_derive(ToSchema, attributes(schema, aliases))]
51/// Generate reusable OpenAPI schema to be used
52/// together with [`OpenApi`][openapi_derive].
53///
54/// This is `#[derive]` implementation for [`ToSchema`][to_schema] trait. The macro accepts one
55/// `schema`
56/// attribute optionally which can be used to enhance generated documentation. The attribute can be placed
57/// at item level or field level in struct and enums. Currently placing this attribute to unnamed field does
58/// not have any effect.
59///
60/// You can use the Rust's own `#[deprecated]` attribute on any struct, enum or field to mark it as deprecated and it will
61/// reflect to the generated OpenAPI spec.
62///
63/// `#[deprecated]` attribute supports adding additional details such as a reason and or since version but this is is not supported in
64/// OpenAPI. OpenAPI has only a boolean flag to determine deprecation. While it is totally okay to declare deprecated with reason
65/// `#[deprecated  = "There is better way to do this"]` the reason would not render in OpenAPI spec.
66///
67/// Doc comments on fields will resolve to field descriptions in generated OpenAPI doc. On struct
68/// level doc comments will resolve to object descriptions.
69///
70/// ```rust
71/// /// This is a pet
72/// #[derive(utoipa::ToSchema)]
73/// struct Pet {
74///     /// Name for your pet
75///     name: String,
76/// }
77/// ```
78///
79/// # Struct Optional Configuration Options for `#[schema(...)]`
80/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
81///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
82/// * `xml(...)` Can be used to define [`Xml`][xml] object properties applicable to Structs.
83/// * `title = ...` Literal string value. Can be used to define title for struct in OpenAPI
84///   document. Some OpenAPI code generation libraries also use this field as a name for the
85///   struct.
86/// * `rename_all = ...` Supports same syntax as _serde_ _`rename_all`_ attribute. Will rename all fields
87///   of the structs accordingly. If both _serde_ `rename_all` and _schema_ _`rename_all`_ are defined
88///   __serde__ will take precedence.
89/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
90///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
91///   OpenAPI spec as _`path.to.Pet`_.
92/// * `default` Can be used to populate default values on all fields using the struct's
93///   [`Default`](std::default::Default) implementation.
94/// * `deprecated` Can be used to mark all fields as deprecated in the generated OpenAPI spec but
95///   not in the code. If you'd like to mark the fields as deprecated in the code as well use
96///   Rust's own `#[deprecated]` attribute instead.
97
98/// # Enum Optional Configuration Options for `#[schema(...)]`
99/// * `example = ...` Can be method reference or _`json!(...)`_.
100/// * `default = ...` Can be method reference or _`json!(...)`_.
101/// * `title = ...` Literal string value. Can be used to define title for enum in OpenAPI
102///   document. Some OpenAPI code generation libraries also use this field as a name for the
103///   enum. __Note!__  ___Complex enum (enum with other than unit variants) does not support title!___
104/// * `rename_all = ...` Supports same syntax as _serde_ _`rename_all`_ attribute. Will rename all
105///   variants of the enum accordingly. If both _serde_ `rename_all` and _schema_ _`rename_all`_
106///   are defined __serde__ will take precedence.
107/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
108///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
109///   OpenAPI spec as _`path.to.Pet`_.
110/// * `deprecated` Can be used to mark the enum as deprecated in the generated OpenAPI spec but
111///   not in the code. If you'd like to mark the enum as deprecated in the code as well use
112///   Rust's own `#[deprecated]` attribute instead.
113///
114/// # Enum Variant Optional Configuration Options for `#[schema(...)]`
115/// Supports all variant specific configuration options e.g. if variant is _`UnnamedStruct`_ then
116/// unnamed struct type configuration options are supported.
117///
118/// In addition to the variant type specific configuration options enum variants support custom
119/// _`rename`_ attribute. It behaves similarly to serde's _`rename`_ attribute. If both _serde_
120/// _`rename`_ and _schema_ _`rename`_ are defined __serde__ will take precedence.
121///
122/// # Unnamed Field Struct Optional Configuration Options for `#[schema(...)]`
123/// * `example = ...` Can be method reference or _`json!(...)`_.
124/// * `default = ...` Can be method reference or _`json!(...)`_. If no value is specified, and the struct has
125///   only one field, the field's default value in the schema will be set from the struct's
126///   [`Default`](std::default::Default) implementation.
127/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
128///   an open value as a string. By default the format is derived from the type of the property
129///   according OpenApi spec.
130/// * `value_type = ...` Can be used to override default type derived from type of the field used in OpenAPI spec.
131///   This is useful in cases where the default type does not correspond to the actual type e.g. when
132///   any third-party types are used which are not [`ToSchema`][to_schema]s nor [`primitive` types][primitive].
133///   The value can be any Rust type what normally could be used to serialize to JSON or either virtual type _`Object`_
134///   or _`Value`_, or an alias defined using `#[aliases(..)]`.
135///   _`Object`_ will be rendered as generic OpenAPI object _(`type: object`)_.
136///   _`Value`_ will be rendered as any OpenAPI value (i.e. no `type` restriction).
137/// * `title = ...` Literal string value. Can be used to define title for struct in OpenAPI
138///   document. Some OpenAPI code generation libraries also use this field as a name for the
139///   struct.
140/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
141///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
142///   OpenAPI spec as _`path.to.Pet`_.
143/// * `deprecated` Can be used to mark the field as deprecated in the generated OpenAPI spec but
144///   not in the code. If you'd like to mark the field as deprecated in the code as well use
145///   Rust's own `#[deprecated]` attribute instead.
146///
147/// # Named Fields Optional Configuration Options for `#[schema(...)]`
148/// * `example = ...` Can be method reference or _`json!(...)`_.
149/// * `default = ...` Can be method reference or _`json!(...)`_.
150/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
151///   an open value as a string. By default the format is derived from the type of the property
152///   according OpenApi spec.
153/// * `write_only` Defines property is only used in **write** operations *POST,PUT,PATCH* but not in *GET*
154/// * `read_only` Defines property is only used in **read** operations *GET* but not in *POST,PUT,PATCH*
155/// * `xml(...)` Can be used to define [`Xml`][xml] object properties applicable to named fields.
156///    See configuration options at xml attributes of [`ToSchema`][to_schema_xml]
157/// * `value_type = ...` Can be used to override default type derived from type of the field used in OpenAPI spec.
158///   This is useful in cases where the default type does not correspond to the actual type e.g. when
159///   any third-party types are used which are not [`ToSchema`][to_schema]s nor [`primitive` types][primitive].
160///   The value can be any Rust type what normally could be used to serialize to JSON, or either virtual type _`Object`_
161///   or _`Value`_, or an alias defined using `#[aliases(..)]`.
162///   _`Object`_ will be rendered as generic OpenAPI object _(`type: object`)_.
163///   _`Value`_ will be rendered as any OpenAPI value (i.e. no `type` restriction).
164/// * `inline` If the type of this field implements [`ToSchema`][to_schema], then the schema definition
165///   will be inlined. **warning:** Don't use this for recursive data types!
166/// * `required = ...` Can be used to enforce required status for the field. [See
167///   rules][derive@ToSchema#field-nullability-and-required-rules]
168/// * `nullable` Defines property is nullable (note this is different to non-required).
169/// * `rename = ...` Supports same syntax as _serde_ _`rename`_ attribute. Will rename field
170///   accordingly. If both _serde_ `rename` and _schema_ _`rename`_ are defined __serde__ will take
171///   precedence.
172/// * `multiple_of = ...` Can be used to define multiplier for a value. Value is considered valid
173///   division will result an `integer`. Value must be strictly above _`0`_.
174/// * `maximum = ...` Can be used to define inclusive upper bound to a `number` value.
175/// * `minimum = ...` Can be used to define inclusive lower bound to a `number` value.
176/// * `exclusive_maximum = ...` Can be used to define exclusive upper bound to a `number` value.
177/// * `exclusive_minimum = ...` Can be used to define exclusive lower bound to a `number` value.
178/// * `max_length = ...` Can be used to define maximum length for `string` types.
179/// * `min_length = ...` Can be used to define minimum length for `string` types.
180/// * `pattern = ...` Can be used to define valid regular expression in _ECMA-262_ dialect the field value must match.
181/// * `max_items = ...` Can be used to define maximum items allowed for `array` fields. Value must
182///   be non-negative integer.
183/// * `min_items = ...` Can be used to define minimum items allowed for `array` fields. Value must
184///   be non-negative integer.
185/// * `schema_with = ...` Use _`schema`_ created by provided function reference instead of the
186///   default derived _`schema`_. The function must match to `fn() -> Into<RefOr<Schema>>`. It does
187///   not accept arguments and must return anything that can be converted into `RefOr<Schema>`.
188/// * `additional_properties = ...` Can be used to define free form types for maps such as
189///   [`HashMap`](std::collections::HashMap) and [`BTreeMap`](std::collections::BTreeMap).
190///   Free form type enables use of arbitrary types within map values.
191///   Supports formats _`additional_properties`_ and _`additional_properties = true`_.
192/// * `deprecated` Can be used to mark the field as deprecated in the generated OpenAPI spec but
193///   not in the code. If you'd like to mark the field as deprecated in the code as well use
194///   Rust's own `#[deprecated]` attribute instead.
195///
196/// #### Field nullability and required rules
197///
198/// Field is considered _`required`_ if
199/// * it is not `Option` field
200/// * and it does not have _`skip_serializing_if`_ property
201/// * and it does not have _`serde_with`_ _[`double_option`](https://docs.rs/serde_with/latest/serde_with/rust/double_option/index.html)_
202/// * and it does not have default value provided with serde _`default`_
203///   attribute
204///
205/// Field is considered _`nullable`_ when field type is _`Option`_.
206///
207/// ## Xml attribute Configuration Options
208///
209/// * `xml(name = "...")` Will set name for property or type.
210/// * `xml(namespace = "...")` Will set namespace for xml element which needs to be valid uri.
211/// * `xml(prefix = "...")` Will set prefix for name.
212/// * `xml(attribute)` Will translate property to xml attribute instead of xml element.
213/// * `xml(wrapped)` Will make wrapped xml element.
214/// * `xml(wrapped(name = "wrap_name"))` Will override the wrapper elements name.
215///
216/// See [`Xml`][xml] for more details.
217///
218/// # Partial `#[serde(...)]` attributes support
219///
220/// ToSchema derive has partial support for [serde attributes]. These supported attributes will reflect to the
221/// generated OpenAPI doc. For example if _`#[serde(skip)]`_ is defined the attribute will not show up in the OpenAPI spec at all since it will not never
222/// be serialized anyway. Similarly the _`rename`_ and _`rename_all`_ will reflect to the generated OpenAPI doc.
223///
224/// * `rename_all = "..."` Supported at the container level.
225/// * `rename = "..."` Supported **only** at the field or variant level.
226/// * `skip = "..."` Supported  **only** at the field or variant level.
227/// * `skip_serializing = "..."` Supported  **only** at the field or variant level.
228/// * `skip_deserializing = "..."` Supported  **only** at the field or variant level.
229/// * `skip_serializing_if = "..."` Supported  **only** at the field level.
230/// * `with = ...` Supported **only at field level.**
231/// * `tag = "..."` Supported at the container level. `tag` attribute works as a [discriminator field][discriminator] for an enum.
232/// * `content = "..."` Supported at the container level, allows [adjacently-tagged enums](https://serde.rs/enum-representations.html#adjacently-tagged).
233///   This attribute requires that a `tag` is present, otherwise serde will trigger a compile-time
234///   failure.
235/// * `untagged` Supported at the container level. Allows [untagged
236/// enum representation](https://serde.rs/enum-representations.html#untagged).
237/// * `default` Supported at the container level and field level according to [serde attributes].
238/// * `flatten` Supported at the field level.
239///
240/// Other _`serde`_ attributes works as is but does not have any effect on the generated OpenAPI doc.
241///
242/// **Note!** `tag` attribute has some limitations like it cannot be used
243/// with **unnamed field structs** and **tuple types**.  See more at
244/// [enum representation docs](https://serde.rs/enum-representations.html).
245///
246/// **Note!** `with` attribute is used in tandem with [serde_with](https://github.com/jonasbb/serde_with) to recognize
247/// _[`double_option`](https://docs.rs/serde_with/latest/serde_with/rust/double_option/index.html)_ from **field value**.
248/// _`double_option`_ is **only** supported attribute from _`serde_with`_ crate.
249///
250/// ```rust
251/// # use serde::Serialize;
252/// # use utoipa::ToSchema;
253/// #[derive(Serialize, ToSchema)]
254/// struct Foo(String);
255///
256/// #[derive(Serialize, ToSchema)]
257/// #[serde(rename_all = "camelCase")]
258/// enum Bar {
259///     UnitValue,
260///     #[serde(rename_all = "camelCase")]
261///     NamedFields {
262///         #[serde(rename = "id")]
263///         named_id: &'static str,
264///         name_list: Option<Vec<String>>
265///     },
266///     UnnamedFields(Foo),
267///     #[serde(skip)]
268///     SkipMe,
269/// }
270/// ```
271///
272/// _**Add custom `tag` to change JSON representation to be internally tagged.**_
273/// ```rust
274/// # use serde::Serialize;
275/// # use utoipa::ToSchema;
276/// #[derive(Serialize, ToSchema)]
277/// struct Foo(String);
278///
279/// #[derive(Serialize, ToSchema)]
280/// #[serde(tag = "tag")]
281/// enum Bar {
282///     UnitValue,
283///     NamedFields {
284///         id: &'static str,
285///         names: Option<Vec<String>>
286///     },
287/// }
288/// ```
289///
290/// _**Add serde `default` attribute for MyValue struct. Similarly `default` could be added to
291/// individual fields as well. If `default` is given the field's affected will be treated
292/// as optional.**_
293/// ```rust
294///  #[derive(utoipa::ToSchema, serde::Deserialize, Default)]
295///  #[serde(default)]
296///  struct MyValue {
297///      field: String
298///  }
299/// ```
300///
301/// # `#[repr(...)]` attribute support
302///
303/// [Serde repr](https://github.com/dtolnay/serde-repr) allows field-less enums be represented by
304/// their numeric value.
305///
306/// * `repr(u*)` for unsigned integer.
307/// * `repr(i*)` for signed integer.
308///
309/// **Supported schema attributes**
310///
311/// * `example = ...` Can be method reference or _`json!(...)`_.
312/// * `default = ...` Can be method reference or _`json!(...)`_.
313/// * `title = ...` Literal string value. Can be used to define title for enum in OpenAPI
314///   document. Some OpenAPI code generation libraries also use this field as a name for the
315///   enum. __Note!__  ___Complex enum (enum with other than unit variants) does not support title!___
316/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
317///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
318///   OpenAPI spec as _`path.to.Pet`_.
319///
320/// _**Create enum with numeric values.**_
321/// ```rust
322/// # use utoipa::ToSchema;
323/// #[derive(ToSchema)]
324/// #[repr(u8)]
325/// #[schema(default = default_value, example = 2)]
326/// enum Mode {
327///     One = 1,
328///     Two,
329///  }
330///
331/// fn default_value() -> u8 {
332///     1
333/// }
334/// ```
335///
336/// _**You can use `skip` and `tag` attributes from serde.**_
337/// ```rust
338/// # use utoipa::ToSchema;
339/// #[derive(ToSchema, serde::Serialize)]
340/// #[repr(i8)]
341/// #[serde(tag = "code")]
342/// enum ExitCode {
343///     Error = -1,
344///     #[serde(skip)]
345///     Unknown = 0,
346///     Ok = 1,
347///  }
348/// ```
349///
350/// # Generic schemas with aliases
351///
352/// Schemas can also be generic which allows reusing types. This enables certain behaviour patters
353/// where super type declares common code for type aliases.
354///
355/// In this example we have common `Status` type which accepts one generic type. It is then defined
356/// with `#[aliases(...)]` that it is going to be used with [`String`](std::string::String) and [`i32`] values.
357/// The generic argument could also be another [`ToSchema`][to_schema] as well.
358/// ```rust
359/// # use utoipa::{ToSchema, OpenApi};
360/// #[derive(ToSchema)]
361/// #[aliases(StatusMessage = Status<String>, StatusNumber = Status<i32>)]
362/// struct Status<T> {
363///     value: T
364/// }
365///
366/// #[derive(OpenApi)]
367/// #[openapi(
368///     components(schemas(StatusMessage, StatusNumber))
369/// )]
370/// struct ApiDoc;
371/// ```
372///
373/// The `#[aliases(...)]` is just syntactic sugar and will create Rust [type aliases](https://doc.rust-lang.org/reference/items/type-aliases.html)
374/// behind the scenes which then can be later referenced anywhere in code.
375///
376/// **Note!** You should never register generic type itself in `components(...)` so according above example `Status<...>` should not be registered
377/// because it will not render the type correctly and will cause an error in generated OpenAPI spec.
378///
379/// # Examples
380///
381/// _**Simple example of a Pet with descriptions and object level example.**_
382/// ```rust
383/// # use utoipa::ToSchema;
384/// /// This is a pet.
385/// #[derive(ToSchema)]
386/// #[schema(example = json!({"name": "bob the cat", "id": 0}))]
387/// struct Pet {
388///     /// Unique id of a pet.
389///     id: u64,
390///     /// Name of a pet.
391///     name: String,
392///     /// Age of a pet if known.
393///     age: Option<i32>,
394/// }
395/// ```
396///
397/// _**The `schema` attribute can also be placed at field level as follows.**_
398/// ```rust
399/// # use utoipa::ToSchema;
400/// #[derive(ToSchema)]
401/// struct Pet {
402///     #[schema(example = 1, default = 0)]
403///     id: u64,
404///     name: String,
405///     age: Option<i32>,
406/// }
407/// ```
408///
409/// _**You can also use method reference for attribute values.**_
410/// ```rust
411/// # use utoipa::ToSchema;
412/// #[derive(ToSchema)]
413/// struct Pet {
414///     #[schema(example = u64::default, default = u64::default)]
415///     id: u64,
416///     #[schema(default = default_name)]
417///     name: String,
418///     age: Option<i32>,
419/// }
420///
421/// fn default_name() -> String {
422///     "bob".to_string()
423/// }
424/// ```
425///
426/// _**For enums and unnamed field structs you can define `schema` at type level.**_
427/// ```rust
428/// # use utoipa::ToSchema;
429/// #[derive(ToSchema)]
430/// #[schema(example = "Bus")]
431/// enum VehicleType {
432///     Rocket, Car, Bus, Submarine
433/// }
434/// ```
435///
436/// _**Also you write complex enum combining all above types.**_
437/// ```rust
438/// # use utoipa::ToSchema;
439/// #[derive(ToSchema)]
440/// enum ErrorResponse {
441///     InvalidCredentials,
442///     #[schema(default = String::default, example = "Pet not found")]
443///     NotFound(String),
444///     System {
445///         #[schema(example = "Unknown system failure")]
446///         details: String,
447///     }
448/// }
449/// ```
450///
451/// _**It is possible to specify the title of each variant to help generators create named structures.**_
452/// ```rust
453/// # use utoipa::ToSchema;
454/// #[derive(ToSchema)]
455/// enum ErrorResponse {
456///     #[schema(title = "InvalidCredentials")]
457///     InvalidCredentials,
458///     #[schema(title = "NotFound")]
459///     NotFound(String),
460/// }
461/// ```
462///
463/// _**Use `xml` attribute to manipulate xml output.**_
464/// ```rust
465/// # use utoipa::ToSchema;
466/// #[derive(ToSchema)]
467/// #[schema(xml(name = "user", prefix = "u", namespace = "https://user.xml.schema.test"))]
468/// struct User {
469///     #[schema(xml(attribute, prefix = "u"))]
470///     id: i64,
471///     #[schema(xml(name = "user_name", prefix = "u"))]
472///     username: String,
473///     #[schema(xml(wrapped(name = "linkList"), name = "link"))]
474///     links: Vec<String>,
475///     #[schema(xml(wrapped, name = "photo_url"))]
476///     photos_urls: Vec<String>
477/// }
478/// ```
479///
480/// _**Use of Rust's own `#[deprecated]` attribute will reflect to generated OpenAPI spec.**_
481/// ```rust
482/// # use utoipa::ToSchema;
483/// #[derive(ToSchema)]
484/// #[deprecated]
485/// struct User {
486///     id: i64,
487///     username: String,
488///     links: Vec<String>,
489///     #[deprecated]
490///     photos_urls: Vec<String>
491/// }
492/// ```
493///
494/// _**Enforce type being used in OpenAPI spec to [`String`] with `value_type` and set format to octet stream
495/// with [`SchemaFormat::KnownFormat(KnownFormat::Binary)`][binary].**_
496/// ```rust
497/// # use utoipa::ToSchema;
498/// #[derive(ToSchema)]
499/// struct Post {
500///     id: i32,
501///     #[schema(value_type = String, format = Binary)]
502///     value: Vec<u8>,
503/// }
504/// ```
505///
506/// _**Enforce type being used in OpenAPI spec to [`String`] with `value_type` option.**_
507/// ```rust
508/// # use utoipa::ToSchema;
509/// #[derive(ToSchema)]
510/// #[schema(value_type = String)]
511/// struct Value(i64);
512/// ```
513///
514/// _**Override the `Bar` reference with a `custom::NewBar` reference.**_
515/// ```rust
516/// # use utoipa::ToSchema;
517/// #  mod custom {
518/// #      struct NewBar;
519/// #  }
520/// #
521/// # struct Bar;
522/// #[derive(ToSchema)]
523/// struct Value {
524///     #[schema(value_type = custom::NewBar)]
525///     field: Bar,
526/// };
527/// ```
528///
529/// _**Use a virtual `Object` type to render generic `object` _(`type: object`)_ in OpenAPI spec.**_
530/// ```rust
531/// # use utoipa::ToSchema;
532/// # mod custom {
533/// #    struct NewBar;
534/// # }
535/// #
536/// # struct Bar;
537/// #[derive(ToSchema)]
538/// struct Value {
539///     #[schema(value_type = Object)]
540///     field: Bar,
541/// };
542/// ```
543///
544/// _**Serde `rename` / `rename_all` will take precedence over schema `rename` / `rename_all`.**_
545/// ```rust
546/// #[derive(utoipa::ToSchema, serde::Deserialize)]
547/// #[serde(rename_all = "lowercase")]
548/// #[schema(rename_all = "UPPERCASE")]
549/// enum Random {
550///     #[serde(rename = "string_value")]
551///     #[schema(rename = "custom_value")]
552///     String(String),
553///
554///     Number {
555///         id: i32,
556///     }
557/// }
558/// ```
559///
560/// _**Add `title` to the enum.**_
561/// ```rust
562/// #[derive(utoipa::ToSchema)]
563/// #[schema(title = "UserType")]
564/// enum UserType {
565///     Admin,
566///     Moderator,
567///     User,
568/// }
569/// ```
570///
571/// _**Example with validation attributes.**_
572/// ```rust
573/// #[derive(utoipa::ToSchema)]
574/// struct Item {
575///     #[schema(maximum = 10, minimum = 5, multiple_of = 2.5)]
576///     id: i32,
577///     #[schema(max_length = 10, min_length = 5, pattern = "[a-z]*")]
578///     value: String,
579///     #[schema(max_items = 5, min_items = 1)]
580///     items: Vec<String>,
581/// }
582/// ````
583///
584/// _**Use `schema_with` to manually implement schema for a field.**_
585/// ```rust
586/// # use utoipa::openapi::schema::{Object, ObjectBuilder};
587/// fn custom_type() -> Object {
588///     ObjectBuilder::new()
589///         .schema_type(utoipa::openapi::SchemaType::String)
590///         .format(Some(utoipa::openapi::SchemaFormat::Custom(
591///             "email".to_string(),
592///         )))
593///         .description(Some("this is the description"))
594///         .build()
595/// }
596///
597/// #[derive(utoipa::ToSchema)]
598/// struct Value {
599///     #[schema(schema_with = custom_type)]
600///     id: String,
601/// }
602/// ```
603///
604/// _**Use `as` attribute to change the name and the path of the schema in the generated OpenAPI
605/// spec.**_
606/// ```rust
607///  #[derive(utoipa::ToSchema)]
608///  #[schema(as = api::models::person::Person)]
609///  struct Person {
610///      name: String,
611///  }
612/// ```
613///
614/// More examples for _`value_type`_ in [`IntoParams` derive docs][into_params].
615///
616/// [to_schema]: trait.ToSchema.html
617/// [known_format]: openapi/schema/enum.KnownFormat.html
618/// [binary]: openapi/schema/enum.KnownFormat.html#variant.Binary
619/// [xml]: openapi/xml/struct.Xml.html
620/// [into_params]: derive.IntoParams.html
621/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
622/// [serde attributes]: https://serde.rs/attributes.html
623/// [discriminator]: openapi/schema/struct.Discriminator.html
624/// [enum_schema]: derive.ToSchema.html#enum-optional-configuration-options-for-schema
625/// [openapi_derive]: derive.OpenApi.html
626/// [to_schema_xml]: macro@ToSchema#xml-attribute-configuration-options
627pub fn derive_to_schema(input: TokenStream) -> TokenStream {
628    let DeriveInput {
629        attrs,
630        ident,
631        data,
632        generics,
633        vis,
634    } = syn::parse_macro_input!(input);
635
636    let schema = Schema::new(&data, &attrs, &ident, &generics, &vis);
637
638    schema.to_token_stream().into()
639}
640
641#[proc_macro_error]
642#[proc_macro_attribute]
643/// Path attribute macro implements OpenAPI path for the decorated function.
644///
645/// This is a `#[derive]` implementation for [`Path`][path] trait. Macro accepts set of attributes that can
646/// be used to configure and override default values what are resolved automatically.
647///
648/// You can use the Rust's own `#[deprecated]` attribute on functions to mark it as deprecated and it will
649/// reflect to the generated OpenAPI spec. Only **parameters** has a special **deprecated** attribute to define them as deprecated.
650///
651/// `#[deprecated]` attribute supports adding additional details such as a reason and or since version but this is is not supported in
652/// OpenAPI. OpenAPI has only a boolean flag to determine deprecation. While it is totally okay to declare deprecated with reason
653/// `#[deprecated  = "There is better way to do this"]` the reason would not render in OpenAPI spec.
654///
655/// Doc comment at decorated function will be used for _`description`_ and _`summary`_ of the path.
656/// First line of the doc comment will be used as the _`summary`_ and the whole doc comment will be
657/// used as _`description`_.
658/// ```rust
659/// /// This is a summary of the operation
660/// ///
661/// /// All lines of the doc comment will be included to operation description.
662/// #[utoipa::path(get, path = "/operation")]
663/// fn operation() {}
664/// ```
665///
666/// # Path Attributes
667///
668/// * `operation` _**Must be first parameter!**_ Accepted values are known http operations such as
669///   _`get, post, put, delete, head, options, connect, patch, trace`_.
670///
671/// * `path = "..."` Must be OpenAPI format compatible str with arguments within curly braces. E.g _`{id}`_
672///
673/// * `operation_id = ...` Unique operation id for the endpoint. By default this is mapped to function name.
674///   The operation_id can be any valid expression (e.g. string literals, macro invocations, variables) so long
675///   as its result can be converted to a `String` using `String::from`.
676///
677/// * `context_path = "..."` Can add optional scope for **path**. The **context_path** will be prepended to beginning of **path**.
678///   This is particularly useful when **path** does not contain the full path to the endpoint. For example if web framework
679///   allows operation to be defined under some context path or scope which does not reflect to the resolved path then this
680///   **context_path** can become handy to alter the path.
681///
682/// * `tag = "..."` Can be used to group operations. Operations with same tag are grouped together. By default
683///   this is derived from the handler that is given to [`OpenApi`][openapi]. If derive results empty str
684///   then default value _`crate`_ is used instead.
685///
686/// * `request_body = ... | request_body(...)` Defining request body indicates that the request is expecting request body within
687///   the performed request.
688///
689/// * `responses(...)` Slice of responses the endpoint is going to possibly return to the caller.
690///
691/// * `params(...)` Slice of params that the endpoint accepts.
692///
693/// * `security(...)` List of [`SecurityRequirement`][security]s local to the path operation.
694///
695/// # Request Body Attributes
696///
697/// **Simple format definition by `request_body = ...`**
698/// * _`request_body = Type`_, _`request_body = inline(Type)`_ or _`request_body = ref("...")`_.
699///   The given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec or Map etc.
700///   With _`inline(...)`_ the schema will be inlined instead of a referenced which is the default for
701///   [`ToSchema`][to_schema] types. _`ref("./external.json")`_ can be used to reference external
702///   json file for body schema. **Note!** Utoipa does **not** guarantee that free form _`ref`_ is accessbile via
703///   OpenAPI doc or Swagger UI, users are eligible to make these guarantees.
704///
705/// **Advanced format definition by `request_body(...)`**
706/// * `content = ...` Can be _`content = Type`_, _`content = inline(Type)`_ or _`content = ref("...")`_. The
707///   given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec
708///   or Map etc. With _`inline(...)`_ the schema will be inlined instead of a referenced
709///   which is the default for [`ToSchema`][to_schema] types. _`ref("./external.json")`_
710///   can be used to reference external json file for body schema. **Note!** Utoipa does **not** guarantee
711///   that free form _`ref`_ is accessible via OpenAPI doc or Swagger UI, users are eligible
712///   to make these guarantees.
713///
714/// * `description = "..."` Define the description for the request body object as str.
715///
716/// * `content_type = "..."` Can be used to override the default behavior of auto resolving the content type
717///   from the `content` attribute. If defined the value should be valid content type such as
718///   _`application/json`_. By default the content type is _`text/plain`_ for
719///   [primitive Rust types][primitive], `application/octet-stream` for _`[u8]`_ and
720///   _`application/json`_ for struct and complex enum types.
721///
722/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
723///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
724///
725/// * `examples(...)` Define multiple examples for single request body. This attribute is mutually
726///   exclusive to the _`example`_ attribute and if both are defined this will override the _`example`_.
727///   This has same syntax as _`examples(...)`_ in [Response Attributes](#response-attributes)
728///   _examples(...)_
729///
730/// _**Example request body definitions.**_
731/// ```text
732///  request_body(content = String, description = "Xml as string request", content_type = "text/xml"),
733///  request_body = Pet,
734///  request_body = Option<[Pet]>,
735/// ```
736///
737/// # Response Attributes
738///
739/// * `status = ...` Is either a valid http status code integer. E.g. _`200`_ or a string value representing
740///   a range such as _`"4XX"`_ or `"default"` or a valid _`http::status::StatusCode`_.
741///   _`StatusCode`_ can either be use path to the status code or _status code_ constant directly.
742///
743/// * `description = "..."` Define description for the response as str.
744///
745/// * `body = ...` Optional response body object type. When left empty response does not expect to send any
746///   response body. Can be _`body = Type`_, _`body = inline(Type)`_, or _`body = ref("...")`_.
747///   The given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec or Map etc.
748///   With _`inline(...)`_ the schema will be inlined instead of a referenced which is the default for
749///   [`ToSchema`][to_schema] types. _`ref("./external.json")`_
750///   can be used to reference external json file for body schema. **Note!** Utoipa does **not** guarantee
751///   that free form _`ref`_ is accessible via OpenAPI doc or Swagger UI, users are eligible
752///   to make these guarantees.
753///
754/// * `content_type = "..." | content_type = [...]` Can be used to override the default behavior of auto resolving the content type
755///   from the `body` attribute. If defined the value should be valid content type such as
756///   _`application/json`_. By default the content type is _`text/plain`_ for
757///   [primitive Rust types][primitive], `application/octet-stream` for _`[u8]`_ and
758///   _`application/json`_ for struct and complex enum types.
759///   Content type can also be slice of **content_type** values if the endpoint support returning multiple
760///  response content types. E.g _`["application/json", "text/xml"]`_ would indicate that endpoint can return both
761///  _`json`_ and _`xml`_ formats. **The order** of the content types define the default example show first in
762///  the Swagger UI. Swagger UI wil use the first _`content_type`_ value as a default example.
763///
764/// * `headers(...)` Slice of response headers that are returned back to a caller.
765///
766/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
767///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
768///
769/// * `response = ...` Type what implements [`ToResponse`][to_response_trait] trait. This can alternatively be used to
770///    define response attributes. _`response`_ attribute cannot co-exist with other than _`status`_ attribute.
771///
772/// * `content((...), (...))` Can be used to define multiple return types for single response status. Supported format for single
773///   _content_ is `(content_type = response_body, example = "...", examples(...))`. _`example`_
774///   and _`examples`_ are optional arguments. Examples attribute behaves exactly same way as in
775///   the response and is mutually exclusive with the example attribute.
776///
777/// * `examples(...)` Define multiple examples for single response. This attribute is mutually
778///   exclusive to the _`example`_ attribute and if both are defined this will override the _`example`_.
779///     * `name = ...` This is first attribute and value must be literal string.
780///     * `summary = ...` Short description of example. Value must be literal string.
781///     * `description = ...` Long description of example. Attribute supports markdown for rich text
782///       representation. Value must be literal string.
783///     * `value = ...` Example value. It must be _`json!(...)`_. _`json!(...)`_ should be something that
784///       _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
785///     * `external_value = ...` Define URI to literal example value. This is mutually exclusive to
786///       the _`value`_ attribute. Value must be literal string.
787///
788///      _**Example of example definition.**_
789///     ```text
790///      ("John" = (summary = "This is John", value = json!({"name": "John"})))
791///     ```
792///
793/// **Minimal response format:**
794/// ```text
795/// responses(
796///     (status = 200, description = "success response"),
797///     (status = 404, description = "resource missing"),
798///     (status = "5XX", description = "server error"),
799///     (status = StatusCode::INTERNAL_SERVER_ERROR, description = "internal server error"),
800///     (status = IM_A_TEAPOT, description = "happy easter")
801/// )
802/// ```
803///
804/// **More complete Response:**
805/// ```text
806/// responses(
807///     (status = 200, description = "Success response", body = Pet, content_type = "application/json",
808///         headers(...),
809///         example = json!({"id": 1, "name": "bob the cat"})
810///     )
811/// )
812/// ```
813///
814/// **Response with multiple response content types:**
815/// ```text
816/// responses(
817///     (status = 200, description = "Success response", body = Pet, content_type = ["application/json", "text/xml"])
818/// )
819/// ```
820///
821/// **Multiple response return types with _`content(...)`_ attribute:**
822///
823/// _**Define multiple response return types for single response status with their own example.**_
824/// ```text
825/// responses(
826///    (status = 200, content(
827///            ("application/vnd.user.v1+json" = User, example = json!(User {id: "id".to_string()})),
828///            ("application/vnd.user.v2+json" = User2, example = json!(User2 {id: 2}))
829///        )
830///    )
831/// )
832/// ```
833///
834/// ### Using `ToResponse` for reusable responses
835///
836/// _**`ReusableResponse` must be a type that implements [`ToResponse`][to_response_trait].**_
837/// ```text
838/// responses(
839///     (status = 200, response = ReusableResponse)
840/// )
841/// ```
842///
843/// _**[`ToResponse`][to_response_trait] can also be inlined to the responses map.**_
844/// ```text
845/// responses(
846///     (status = 200, response = inline(ReusableResponse))
847/// )
848/// ```
849///
850/// ## Responses from `IntoResponses`
851///
852/// _**Responses for a path can be specified with one or more types that implement
853/// [`IntoResponses`][into_responses_trait].**_
854/// ```text
855/// responses(MyResponse)
856/// ```
857///
858/// # Response Header Attributes
859///
860/// * `name` Name of the header. E.g. _`x-csrf-token`_
861///
862/// * `type` Additional type of the header value. Can be `Type` or `inline(Type)`.
863///   The given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec or Map etc.
864///   With _`inline(...)`_ the schema will be inlined instead of a referenced which is the default for
865///   [`ToSchema`][to_schema] types. **Reminder!** It's up to the user to use valid type for the
866///   response header.
867///
868/// * `description = "..."` Can be used to define optional description for the response header as str.
869///
870/// **Header supported formats:**
871///
872/// ```text
873/// ("x-csrf-token"),
874/// ("x-csrf-token" = String, description = "New csrf token"),
875/// ```
876///
877/// # Params Attributes
878///
879/// The list of attributes inside the `params(...)` attribute can take two forms: [Tuples](#tuples) or [IntoParams
880/// Type](#intoparams-type).
881///
882/// ## Tuples
883///
884/// In the tuples format, parameters are specified using the following attributes inside a list of
885/// tuples separated by commas:
886///
887/// * `name` _**Must be the first argument**_. Define the name for parameter.
888///
889/// * `parameter_type` Define possible type for the parameter. Can be `Type` or `inline(Type)`.
890///   The given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec or Map etc.
891///   With _`inline(...)`_ the schema will be inlined instead of a referenced which is the default for
892///   [`ToSchema`][to_schema] types. Parameter type is placed after `name` with
893///   equals sign E.g. _`"id" = String`_
894///
895/// * `in` _**Must be placed after name or parameter_type**_. Define the place of the parameter.
896///   This must be one of the variants of [`openapi::path::ParameterIn`][in_enum].
897///   E.g. _`Path, Query, Header, Cookie`_
898///
899/// * `deprecated` Define whether the parameter is deprecated or not. Can optionally be defined
900///    with explicit `bool` value as _`deprecated = bool`_.
901///
902/// * `description = "..."` Define possible description for the parameter as str.
903///
904/// * `style = ...` Defines how parameters are serialized by [`ParameterStyle`][style]. Default values are based on _`in`_ attribute.
905///
906/// * `explode` Defines whether new _`parameter=value`_ is created for each parameter within _`object`_ or _`array`_.
907///
908/// * `allow_reserved` Defines whether reserved characters _`:/?#[]@!$&'()*+,;=`_ is allowed within value.
909///
910/// * `example = ...` Can method reference or _`json!(...)`_. Given example
911///   will override any example in underlying parameter type.
912///
913/// ##### Parameter type attributes
914///
915/// These attributes supported when _`parameter_type`_ is present. Either by manually providing one
916/// or otherwise resolved e.g from path macro argument when _`actix_extras`_ crate feature is
917/// enabled.
918///
919/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
920///   an open value as a string. By default the format is derived from the type of the property
921///   according OpenApi spec.
922///
923/// * `write_only` Defines property is only used in **write** operations *POST,PUT,PATCH* but not in *GET*
924///
925/// * `read_only` Defines property is only used in **read** operations *GET* but not in *POST,PUT,PATCH*
926///
927/// * `xml(...)` Can be used to define [`Xml`][xml] object properties for the parameter type.
928///    See configuration options at xml attributes of [`ToSchema`][to_schema_xml]
929///
930/// * `nullable` Defines property is nullable (note this is different to non-required).
931///
932/// * `multiple_of = ...` Can be used to define multiplier for a value. Value is considered valid
933///   division will result an `integer`. Value must be strictly above _`0`_.
934///
935/// * `maximum = ...` Can be used to define inclusive upper bound to a `number` value.
936///
937/// * `minimum = ...` Can be used to define inclusive lower bound to a `number` value.
938///
939/// * `exclusive_maximum = ...` Can be used to define exclusive upper bound to a `number` value.
940///
941/// * `exclusive_minimum = ...` Can be used to define exclusive lower bound to a `number` value.
942///
943/// * `max_length = ...` Can be used to define maximum length for `string` types.
944///
945/// * `min_length = ...` Can be used to define minimum length for `string` types.
946///
947/// * `pattern = ...` Can be used to define valid regular expression in _ECMA-262_ dialect the field value must match.
948///
949/// * `max_items = ...` Can be used to define maximum items allowed for `array` fields. Value must
950///   be non-negative integer.
951///
952/// * `min_items = ...` Can be used to define minimum items allowed for `array` fields. Value must
953///   be non-negative integer.
954///
955/// **For example:**
956///
957/// ```text
958/// params(
959///     ("id" = String, Path, deprecated, description = "Pet database id"),
960///     ("name", Path, deprecated, description = "Pet name"),
961///     (
962///         "value" = inline(Option<[String]>),
963///         Query,
964///         description = "Value description",
965///         style = Form,
966///         allow_reserved,
967///         deprecated,
968///         explode,
969///         example = json!(["Value"])),
970///         max_length = 10,
971///         min_items = 1
972///     )
973/// )
974/// ```
975///
976/// ## IntoParams Type
977///
978/// In the IntoParams parameters format, the parameters are specified using an identifier for a type
979/// that implements [`IntoParams`][into_params]. See [`IntoParams`][into_params] for an
980/// example.
981///
982/// ```text
983/// params(MyParameters)
984/// ```
985///
986/// **Note!** that `MyParameters` can also be used in combination with the [tuples
987/// representation](#tuples) or other structs.
988/// ```text
989/// params(
990///     MyParameters1,
991///     MyParameters2,
992///     ("id" = String, Path, deprecated, description = "Pet database id"),
993/// )
994/// ```
995///
996/// # Security Requirement Attributes
997///
998/// * `name` Define the name for security requirement. This must match to name of existing
999///   [`SecuritySchema`][security_schema].
1000/// * `scopes = [...]` Define the list of scopes needed. These must be scopes defined already in
1001///   existing [`SecuritySchema`][security_schema].
1002///
1003/// **Security Requirement supported formats:**
1004///
1005/// ```text
1006/// (),
1007/// ("name" = []),
1008/// ("name" = ["scope1", "scope2"]),
1009/// ```
1010///
1011/// Leaving empty _`()`_ creates an empty [`SecurityRequirement`][security] this is useful when
1012/// security requirement is optional for operation.
1013///
1014/// # actix_extras feature support for actix-web
1015///
1016/// **actix_extras** feature gives **utoipa** ability to parse path operation information from **actix-web** types and macros.
1017///
1018/// 1. Ability to parse `path` from **actix-web** path attribute macros e.g. _`#[get(...)]`_.
1019/// 2. Ability to parse [`std::primitive`]  or [`String`] or [`tuple`] typed `path` parameters from **actix-web** _`web::Path<...>`_.
1020/// 3. Ability to parse `path` and `query` parameters form **actix-web** _`web::Path<...>`_, _`web::Query<...>`_ types
1021///    with [`IntoParams`][into_params] trait.
1022///
1023/// See the **actix_extras** in action in examples [todo-actix](https://github.com/juhaku/utoipa/tree/master/examples/todo-actix).
1024///
1025/// With **actix_extras** feature enabled the you can leave out definitions for **path**, **operation**
1026/// and **parameter types**.
1027/// ```rust
1028/// use actix_web::{get, web, HttpResponse, Responder};
1029/// use serde_json::json;
1030///
1031/// /// Get Pet by id
1032/// #[utoipa::path(
1033///     responses(
1034///         (status = 200, description = "Pet found from database")
1035///     ),
1036///     params(
1037///         ("id", description = "Pet id"),
1038///     )
1039/// )]
1040/// #[get("/pet/{id}")]
1041/// async fn get_pet_by_id(id: web::Path<i32>) -> impl Responder {
1042///     HttpResponse::Ok().json(json!({ "pet": format!("{:?}", &id.into_inner()) }))
1043/// }
1044/// ```
1045///
1046/// With **actix_extras** you may also not to list any _**params**_ if you do not want to specify any description for them. Params are
1047/// resolved from path and the argument types of handler
1048/// ```rust
1049/// use actix_web::{get, web, HttpResponse, Responder};
1050/// use serde_json::json;
1051///
1052/// /// Get Pet by id
1053/// #[utoipa::path(
1054///     responses(
1055///         (status = 200, description = "Pet found from database")
1056///     )
1057/// )]
1058/// #[get("/pet/{id}")]
1059/// async fn get_pet_by_id(id: web::Path<i32>) -> impl Responder {
1060///     HttpResponse::Ok().json(json!({ "pet": format!("{:?}", &id.into_inner()) }))
1061/// }
1062/// ```
1063///
1064/// # rocket_extras feature support for rocket
1065///
1066/// **rocket_extras** feature enhances path operation parameter support. It gives **utoipa** ability to parse `path`, `path parameters`
1067/// and `query parameters` based on arguments given to **rocket**  proc macros such as _**`#[get(...)]`**_.
1068///
1069/// 1. It is able to parse parameter types for [primitive types][primitive], [`String`], [`Vec`], [`Option`] or [`std::path::PathBuf`]
1070///    type.
1071/// 2. It is able to determine `parameter_in` for [`IntoParams`][into_params] trait used for `FromForm` type of query parameters.
1072///
1073/// See the **rocket_extras** in action in examples [rocket-todo](https://github.com/juhaku/utoipa/tree/master/examples/rocket-todo).
1074///
1075///
1076/// # axum_extras feature support for axum
1077///
1078/// **axum_extras** feature enhances parameter support for path operation in following ways.
1079///
1080/// 1. It allows users to use tuple style path parameters e.g. _`Path((id, name)): Path<(i32, String)>`_ and resolves
1081///    parameter names and types from it.
1082/// 2. It enhances [`IntoParams` derive][into_params_derive] functionality by automatically resolving _`parameter_in`_ from
1083///   _`Path<...>`_ or _`Query<...>`_ handler function arguments.
1084///
1085/// _**Resole path argument types from tuple style handler arguments.**_
1086/// ```rust
1087/// # use axum::extract::Path;
1088/// /// Get todo by id and name.
1089/// #[utoipa::path(
1090///     get,
1091///     path = "/todo/{id}",
1092///     params(
1093///         ("id", description = "Todo id"),
1094///         ("name", description = "Todo name")
1095///     ),
1096///     responses(
1097///         (status = 200, description = "Get todo success", body = String)
1098///     )
1099/// )]
1100/// async fn get_todo(
1101///     Path((id, name)): Path<(i32, String)>
1102/// ) -> String {
1103///     String::new()
1104/// }
1105/// ```
1106///
1107/// _**Use `IntoParams` to resolve query parameters.**_
1108/// ```rust
1109/// # use serde::Deserialize;
1110/// # use utoipa::IntoParams;
1111/// # use axum::{extract::Query, Json};
1112/// #[derive(Deserialize, IntoParams)]
1113/// struct TodoSearchQuery {
1114///     /// Search by value. Search is incase sensitive.
1115///     value: String,
1116///     /// Search by `done` status.
1117///     done: bool,
1118/// }
1119///
1120/// /// Search Todos by query params.
1121/// #[utoipa::path(
1122///     get,
1123///     path = "/todo/search",
1124///     params(
1125///         TodoSearchQuery
1126///     ),
1127///     responses(
1128///         (status = 200, description = "List matching todos by query", body = [String])
1129///     )
1130/// )]
1131/// async fn search_todos(
1132///     query: Query<TodoSearchQuery>,
1133/// ) -> Json<Vec<String>> {
1134///     Json(vec![])
1135/// }
1136/// ```
1137///
1138/// # Examples
1139///
1140/// _**More complete example.**_
1141/// ```rust
1142/// # struct Pet {
1143/// #    id: u64,
1144/// #    name: String,
1145/// # }
1146/// #
1147/// #[utoipa::path(
1148///    post,
1149///    operation_id = "custom_post_pet",
1150///    path = "/pet",
1151///    tag = "pet_handlers",
1152///    request_body(content = Pet, description = "Pet to store the database", content_type = "application/json"),
1153///    responses(
1154///         (status = 200, description = "Pet stored successfully", body = Pet, content_type = "application/json",
1155///             headers(
1156///                 ("x-cache-len" = String, description = "Cache length")
1157///             ),
1158///             example = json!({"id": 1, "name": "bob the cat"})
1159///         ),
1160///    ),
1161///    params(
1162///      ("x-csrf-token" = String, Header, deprecated, description = "Current csrf token of user"),
1163///    ),
1164///    security(
1165///        (),
1166///        ("my_auth" = ["read:items", "edit:items"]),
1167///        ("token_jwt" = [])
1168///    )
1169/// )]
1170/// fn post_pet(pet: Pet) -> Pet {
1171///     Pet {
1172///         id: 4,
1173///         name: "bob the cat".to_string(),
1174///     }
1175/// }
1176/// ```
1177///
1178/// _**More minimal example with the defaults.**_
1179/// ```rust
1180/// # struct Pet {
1181/// #    id: u64,
1182/// #    name: String,
1183/// # }
1184/// #
1185/// #[utoipa::path(
1186///    post,
1187///    path = "/pet",
1188///    request_body = Pet,
1189///    responses(
1190///         (status = 200, description = "Pet stored successfully", body = Pet,
1191///             headers(
1192///                 ("x-cache-len", description = "Cache length")
1193///             )
1194///         ),
1195///    ),
1196///    params(
1197///      ("x-csrf-token", Header, description = "Current csrf token of user"),
1198///    )
1199/// )]
1200/// fn post_pet(pet: Pet) -> Pet {
1201///     Pet {
1202///         id: 4,
1203///         name: "bob the cat".to_string(),
1204///     }
1205/// }
1206/// ```
1207///
1208/// _**Use of Rust's own `#[deprecated]` attribute will reflect to the generated OpenAPI spec and mark this operation as deprecated.**_
1209/// ```rust
1210/// # use actix_web::{get, web, HttpResponse, Responder};
1211/// # use serde_json::json;
1212/// #[utoipa::path(
1213///     responses(
1214///         (status = 200, description = "Pet found from database")
1215///     ),
1216///     params(
1217///         ("id", description = "Pet id"),
1218///     )
1219/// )]
1220/// #[get("/pet/{id}")]
1221/// #[deprecated]
1222/// async fn get_pet_by_id(id: web::Path<i32>) -> impl Responder {
1223///     HttpResponse::Ok().json(json!({ "pet": format!("{:?}", &id.into_inner()) }))
1224/// }
1225/// ```
1226///
1227/// _**Define context path for endpoint. The resolved **path** shown in OpenAPI doc will be `/api/pet/{id}`.**_
1228/// ```rust
1229/// # use actix_web::{get, web, HttpResponse, Responder};
1230/// # use serde_json::json;
1231/// #[utoipa::path(
1232///     context_path = "/api",
1233///     responses(
1234///         (status = 200, description = "Pet found from database")
1235///     )
1236/// )]
1237/// #[get("/pet/{id}")]
1238/// async fn get_pet_by_id(id: web::Path<i32>) -> impl Responder {
1239///     HttpResponse::Ok().json(json!({ "pet": format!("{:?}", &id.into_inner()) }))
1240/// }
1241/// ```
1242///
1243/// _**Example with multiple return types**_
1244/// ```rust
1245/// # trait User {}
1246/// # struct User1 {
1247/// #   id: String
1248/// # }
1249/// # impl User for User1 {}
1250/// #[utoipa::path(
1251///     get,
1252///     path = "/user",
1253///     responses(
1254///         (status = 200, content(
1255///                 ("application/vnd.user.v1+json" = User1, example = json!({"id": "id".to_string()})),
1256///                 ("application/vnd.user.v2+json" = User2, example = json!({"id": 2}))
1257///             )
1258///         )
1259///     )
1260/// )]
1261/// fn get_user() -> Box<dyn User> {
1262///   Box::new(User1 {id: "id".to_string()})
1263/// }
1264/// ````
1265///
1266/// _**Example with multiple examples on single response.**_
1267///```rust
1268/// # #[derive(serde::Serialize, serde::Deserialize)]
1269/// # struct User {
1270/// #   name: String
1271/// # }
1272/// #[utoipa::path(
1273///     get,
1274///     path = "/user",
1275///     responses(
1276///         (status = 200, body = User,
1277///             examples(
1278///                 ("Demo" = (summary = "This is summary", description = "Long description",
1279///                             value = json!(User{name: "Demo".to_string()}))),
1280///                 ("John" = (summary = "Another user", value = json!({"name": "John"})))
1281///              )
1282///         )
1283///     )
1284/// )]
1285/// fn get_user() -> User {
1286///   User {name: "John".to_string()}
1287/// }
1288///```
1289///
1290/// [in_enum]: openapi/path/enum.ParameterIn.html
1291/// [path]: trait.Path.html
1292/// [to_schema]: trait.ToSchema.html
1293/// [openapi]: derive.OpenApi.html
1294/// [security]: openapi/security/struct.SecurityRequirement.html
1295/// [security_schema]: openapi/security/enum.SecurityScheme.html
1296/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
1297/// [into_params]: trait.IntoParams.html
1298/// [style]: openapi/path/enum.ParameterStyle.html
1299/// [into_responses_trait]: trait.IntoResponses.html
1300/// [into_params_derive]: derive.IntoParams.html
1301/// [to_response_trait]: trait.ToResponse.html
1302/// [known_format]: openapi/schema/enum.KnownFormat.html
1303/// [xml]: openapi/xml/struct.Xml.html
1304/// [to_schema_xml]: macro@ToSchema#xml-attribute-configuration-options
1305pub fn path(attr: TokenStream, item: TokenStream) -> TokenStream {
1306    let path_attribute = syn::parse_macro_input!(attr as PathAttr);
1307
1308    #[cfg(any(
1309        feature = "actix_extras",
1310        feature = "rocket_extras",
1311        feature = "axum_extras",
1312        feature = "auto_into_responses"
1313    ))]
1314    let mut path_attribute = path_attribute;
1315
1316    let ast_fn = syn::parse::<ItemFn>(item).unwrap_or_abort();
1317    let fn_name = &*ast_fn.sig.ident.to_string();
1318
1319    #[cfg(feature = "auto_into_responses")]
1320    {
1321        if let Some(responses) = ext::auto_types::parse_fn_operation_responses(&ast_fn) {
1322            path_attribute.responses_from_into_responses(responses);
1323        };
1324    }
1325
1326    let mut resolved_operation = PathOperations::resolve_operation(&ast_fn);
1327    let resolved_path = PathOperations::resolve_path(
1328        &resolved_operation
1329            .as_mut()
1330            .map(|operation| mem::take(&mut operation.path))
1331            .or_else(|| path_attribute.path.as_ref().map(String::to_string)), // cannot use mem take because we need this later
1332    );
1333
1334    #[cfg(any(
1335        feature = "actix_extras",
1336        feature = "rocket_extras",
1337        feature = "axum_extras"
1338    ))]
1339    let mut resolved_path = resolved_path;
1340
1341    #[cfg(any(
1342        feature = "actix_extras",
1343        feature = "rocket_extras",
1344        feature = "axum_extras"
1345    ))]
1346    {
1347        use ext::ArgumentResolver;
1348        use path::parameter::Parameter;
1349        let args = resolved_path.as_mut().map(|path| mem::take(&mut path.args));
1350        let body = resolved_operation
1351            .as_mut()
1352            .map(|path| mem::take(&mut path.body))
1353            .unwrap_or_default();
1354
1355        let (arguments, into_params_types, body) =
1356            PathOperations::resolve_arguments(&ast_fn.sig.inputs, args, body);
1357
1358        let parameters = arguments
1359            .into_iter()
1360            .flatten()
1361            .map(Parameter::from)
1362            .chain(into_params_types.into_iter().flatten().map(Parameter::from));
1363        path_attribute.update_parameters_ext(parameters);
1364
1365        path_attribute.update_request_body(body);
1366    }
1367
1368    let path = Path::new(path_attribute, fn_name)
1369        .path_operation(resolved_operation.map(|operation| operation.path_operation))
1370        .path(|| resolved_path.map(|path| path.path))
1371        .doc_comments(CommentAttributes::from_attributes(&ast_fn.attrs).0)
1372        .deprecated(ast_fn.attrs.iter().find_map(|attr| {
1373
1374            if !matches!(attr.path().get_ident(), Some(ident) if &*ident.to_string() == "deprecated")
1375            {
1376                None
1377            } else {
1378                Some(true)
1379            }
1380        }));
1381
1382    quote! {
1383        #path
1384        #ast_fn
1385    }
1386    .into()
1387}
1388
1389#[proc_macro_error]
1390#[proc_macro_derive(OpenApi, attributes(openapi))]
1391/// Generate OpenApi base object with defaults from
1392/// project settings.
1393///
1394/// This is `#[derive]` implementation for [`OpenApi`][openapi] trait. The macro accepts one `openapi` argument.
1395///
1396/// # OpenApi `#[openapi(...)]` attributes
1397///
1398/// * `paths(...)`  List of method references having attribute [`#[utoipa::path]`][path] macro.
1399/// * `components(schemas(...), responses(...))` Takes available _`component`_ configurations. Currently only
1400///    _`schema`_ and _`response`_ components are supported.
1401///    * `schemas(...)` List of [`ToSchema`][to_schema]s in OpenAPI schema.
1402///    * `responses(...)` List of types that implement
1403/// [`ToResponse`][to_response_trait].
1404/// * `modifiers(...)` List of items implementing [`Modify`][modify] trait for runtime OpenApi modification.
1405///   See the [trait documentation][modify] for more details.
1406/// * `security(...)` List of [`SecurityRequirement`][security]s global to all operations.
1407///   See more details in [`#[utoipa::path(...)]`][path] [attribute macro security options][path_security].
1408/// * `tags(...)` List of [`Tag`][tags] which must match the tag _**path operation**_. By default
1409///   the tag is derived from path given to **handlers** list or if undefined then `crate` is used by default.
1410///   Alternatively the tag name can be given to path operation via [`#[utoipa::path(...)]`][path] macro.
1411///   Tag can be used to define extra information for the api to produce richer documentation.
1412/// * `external_docs(...)` Can be used to reference external resource to the OpenAPI doc for extended documentation.
1413///   External docs can be in [`OpenApi`][openapi_struct] or in [`Tag`][tags] level.
1414/// * `servers(...)` Define [`servers`][servers] as derive argument to the _`OpenApi`_. Servers
1415///   are completely optional and thus can be omitted from the declaration.
1416/// * `info(...)` Declare [`Info`][info] attribute values used to override the default values
1417///   generated from Cargo environment variables. **Note!** Defined attributes will override the
1418///   whole attribute from generated values of Cargo environment variables. E.g. defining
1419///   `contact(name = ...)` will ultimately override whole contact of info and not just partially
1420///   the name.
1421///
1422/// OpenApi derive macro will also derive [`Info`][info] for OpenApi specification using Cargo
1423/// environment variables.
1424///
1425/// * env `CARGO_PKG_NAME` map to info `title`
1426/// * env `CARGO_PKG_VERSION` map to info `version`
1427/// * env `CARGO_PKG_DESCRIPTION` map info `description`
1428/// * env `CARGO_PKG_AUTHORS` map to contact `name` and `email` **only first author will be used**
1429/// * env `CARGO_PKG_LICENSE` map to info `license`
1430///
1431/// # `info(...)` attribute syntax
1432///
1433/// * `title = ...` Define title of the API. It can be literal string.
1434/// * `description = ...` Define description of the API. Markdown can be used for rich text
1435///   representation. It can be literal string or [`include_str!`] statement.
1436/// * `version = ...` Override default version from _`Cargo.toml`_. Value must be literal string.
1437/// * `contact(...)` Used to override the whole contact generated from environment variables.
1438///     * `name = ...` Define identifying name of contact person / organization. It Can be a literal string.
1439///     * `email = ...` Define email address of the contact person / organization. It can be a literal string.
1440///     * `url = ...` Define URL pointing to the contact information. It must be in URL formatted string.
1441/// * `license(...)` Used to override the whole license generated from environment variables.
1442///     * `name = ...` License name of the API. It can be a literal string.
1443///     * `url = ...` Define optional URL of the license. It must be URL formatted string.
1444///
1445/// # `servers(...)` attribute syntax
1446///
1447/// * `url = ...` Define the url for server. It can be literal string.
1448/// * `description = ...` Define description for the server. It can be literal string.
1449/// * `variables(...)` Can be used to define variables for the url.
1450///     * `name = ...` Is the first argument within parentheses. It must be literal string.
1451///     * `default = ...` Defines a default value for the variable if nothing else will be
1452///       provided. If _`enum_values`_ is defined the _`default`_ must be found within the enum
1453///       options. It can be a literal string.
1454///     * `description = ...` Define the description for the variable. It can be a literal string.
1455///     * `enum_values(...)` Define list of possible values for the variable. Values must be
1456///       literal strings.
1457///
1458///  _**Example server variable definition.**_
1459///  ```text
1460/// ("username" = (default = "demo", description = "Default username for API")),
1461/// ("port" = (enum_values("8080", "5000", "4545")))
1462/// ```
1463///
1464/// # Examples
1465///
1466/// _**Define OpenApi schema with some paths and components.**_
1467/// ```rust
1468/// # use utoipa::{OpenApi, ToSchema};
1469/// #
1470/// #[derive(ToSchema)]
1471/// struct Pet {
1472///     name: String,
1473///     age: i32,
1474/// }
1475///
1476/// #[derive(ToSchema)]
1477/// enum Status {
1478///     Active, InActive, Locked,
1479/// }
1480///
1481/// #[utoipa::path(get, path = "/pet")]
1482/// fn get_pet() -> Pet {
1483///     Pet {
1484///         name: "bob".to_string(),
1485///         age: 8,
1486///     }
1487/// }
1488///
1489/// #[utoipa::path(get, path = "/status")]
1490/// fn get_status() -> Status {
1491///     Status::Active
1492/// }
1493///
1494/// #[derive(OpenApi)]
1495/// #[openapi(
1496///     paths(get_pet, get_status),
1497///     components(schemas(Pet, Status)),
1498///     security(
1499///         (),
1500///         ("my_auth" = ["read:items", "edit:items"]),
1501///         ("token_jwt" = [])
1502///     ),
1503///     tags(
1504///         (name = "pets::api", description = "All about pets",
1505///             external_docs(url = "http://more.about.pets.api", description = "Find out more"))
1506///     ),
1507///     external_docs(url = "http://more.about.our.apis", description = "More about our APIs")
1508/// )]
1509/// struct ApiDoc;
1510/// ```
1511///
1512/// _**Define servers to OpenApi.**_
1513///```rust
1514/// # use utoipa::OpenApi;
1515/// #[derive(OpenApi)]
1516/// #[openapi(
1517///     servers(
1518///         (url = "http://localhost:8989", description = "Local server"),
1519///         (url = "http://api.{username}:{port}", description = "Remote API",
1520///             variables(
1521///                 ("username" = (default = "demo", description = "Default username for API")),
1522///                 ("port" = (default = "8080", enum_values("8080", "5000", "3030"), description = "Supported ports for API"))
1523///             )
1524///         )
1525///     )
1526/// )]
1527/// struct ApiDoc;
1528///```
1529///
1530/// _**Define info attribute values used to override auto generated ones from Cargo environment
1531/// variables.**_
1532/// ```compile_fail
1533/// # use utoipa::OpenApi;
1534/// #[derive(OpenApi)]
1535/// #[openapi(info(
1536///     title = "title override",
1537///     description = include_str!("./path/to/content"), // fail compile cause no such file
1538///     contact(name = "Test")
1539/// ))]
1540/// struct ApiDoc;
1541/// ```
1542///
1543/// _**Create OpenAPI with reusable response.**_
1544/// ```rust
1545/// #[derive(utoipa::ToSchema)]
1546/// struct Person {
1547///     name: String,
1548/// }
1549///
1550/// /// Person list response
1551/// #[derive(utoipa::ToResponse)]
1552/// struct PersonList(Vec<Person>);
1553///
1554/// #[utoipa::path(
1555///     get,
1556///     path = "/person-list",
1557///     responses(
1558///         (status = 200, response = PersonList)
1559///     )
1560/// )]
1561/// fn get_persons() -> Vec<Person> {
1562///     vec![]
1563/// }
1564///
1565/// #[derive(utoipa::OpenApi)]
1566/// #[openapi(
1567///     components(
1568///         schemas(Person),
1569///         responses(PersonList)
1570///     )
1571/// )]
1572/// struct ApiDoc;
1573/// ```
1574///
1575/// [openapi]: trait.OpenApi.html
1576/// [openapi_struct]: openapi/struct.OpenApi.html
1577/// [to_schema]: derive.ToSchema.html
1578/// [path]: attr.path.html
1579/// [modify]: trait.Modify.html
1580/// [info]: openapi/info/struct.Info.html
1581/// [security]: openapi/security/struct.SecurityRequirement.html
1582/// [path_security]: attr.path.html#security-requirement-attributes
1583/// [tags]: openapi/tag/struct.Tag.html
1584/// [to_response_trait]: trait.ToResponse.html
1585/// [servers]: openapi/server/index.html
1586pub fn openapi(input: TokenStream) -> TokenStream {
1587    let DeriveInput { attrs, ident, .. } = syn::parse_macro_input!(input);
1588
1589    let openapi_attributes = openapi::parse_openapi_attrs(&attrs).expect_or_abort(
1590        "expected #[openapi(...)] attribute to be present when used with OpenApi derive trait",
1591    );
1592
1593    let openapi = OpenApi(openapi_attributes, ident);
1594
1595    openapi.to_token_stream().into()
1596}
1597
1598#[proc_macro_error]
1599#[proc_macro_derive(IntoParams, attributes(param, into_params))]
1600/// Generate [path parameters][path_params] from struct's
1601/// fields.
1602///
1603/// This is `#[derive]` implementation for [`IntoParams`][into_params] trait.
1604///
1605/// Typically path parameters need to be defined within [`#[utoipa::path(...params(...))]`][path_params] section
1606/// for the endpoint. But this trait eliminates the need for that when [`struct`][struct]s are used to define parameters.
1607/// Still [`std::primitive`] and [`String`](std::string::String) path parameters or [`tuple`] style path parameters need to be defined
1608/// within `params(...)` section if description or other than default configuration need to be given.
1609///
1610/// You can use the Rust's own `#[deprecated]` attribute on field to mark it as
1611/// deprecated and it will reflect to the generated OpenAPI spec.
1612///
1613/// `#[deprecated]` attribute supports adding additional details such as a reason and or since version
1614/// but this is is not supported in OpenAPI. OpenAPI has only a boolean flag to determine deprecation.
1615/// While it is totally okay to declare deprecated with reason
1616/// `#[deprecated  = "There is better way to do this"]` the reason would not render in OpenAPI spec.
1617///
1618/// Doc comment on struct fields will be used as description for the generated parameters.
1619/// ```rust
1620/// #[derive(utoipa::IntoParams)]
1621/// struct Query {
1622///     /// Query todo items by name.
1623///     name: String
1624/// }
1625/// ```
1626///
1627/// # IntoParams Container Attributes for `#[into_params(...)]`
1628///
1629/// The following attributes are available for use in on the container attribute `#[into_params(...)]` for the struct
1630/// deriving `IntoParams`:
1631///
1632/// * `names(...)` Define comma separated list of names for unnamed fields of struct used as a path parameter.
1633///    __Only__ supported on __unnamed structs__.
1634/// * `style = ...` Defines how all parameters are serialized by [`ParameterStyle`][style]. Default
1635///    values are based on _`parameter_in`_ attribute.
1636/// * `parameter_in = ...` =  Defines where the parameters of this field are used with a value from
1637///    [`openapi::path::ParameterIn`][in_enum]. There is no default value, if this attribute is not
1638///    supplied, then the value is determined by the `parameter_in_provider` in
1639///    [`IntoParams::into_params()`](trait.IntoParams.html#tymethod.into_params).
1640/// * `rename_all = ...` Can be provided to alternatively to the serde's `rename_all` attribute. Effectively provides same functionality.
1641///
1642/// Use `names` to define name for single unnamed argument.
1643/// ```rust
1644/// # use utoipa::IntoParams;
1645/// #
1646/// #[derive(IntoParams)]
1647/// #[into_params(names("id"))]
1648/// struct Id(u64);
1649/// ```
1650///
1651/// Use `names` to define names for multiple unnamed arguments.
1652/// ```rust
1653/// # use utoipa::IntoParams;
1654/// #
1655/// #[derive(IntoParams)]
1656/// #[into_params(names("id", "name"))]
1657/// struct IdAndName(u64, String);
1658/// ```
1659///
1660/// # IntoParams Field Attributes for `#[param(...)]`
1661///
1662/// The following attributes are available for use in the `#[param(...)]` on struct fields:
1663///
1664/// * `style = ...` Defines how the parameter is serialized by [`ParameterStyle`][style]. Default values are based on _`parameter_in`_ attribute.
1665///
1666/// * `explode` Defines whether new _`parameter=value`_ pair is created for each parameter within _`object`_ or _`array`_.
1667///
1668/// * `allow_reserved` Defines whether reserved characters _`:/?#[]@!$&'()*+,;=`_ is allowed within value.
1669///
1670/// * `example = ...` Can be method reference or _`json!(...)`_. Given example
1671///   will override any example in underlying parameter type.
1672///
1673/// * `value_type = ...` Can be used to override default type derived from type of the field used in OpenAPI spec.
1674///   This is useful in cases where the default type does not correspond to the actual type e.g. when
1675///   any third-party types are used which are not [`ToSchema`][to_schema]s nor [`primitive` types][primitive].
1676///   The value can be any Rust type what normally could be used to serialize to JSON, or either virtual type _`Object`_
1677///   or _`Value`_, or an alias defined using `#[aliases(..)]`.
1678///   _`Object`_ will be rendered as generic OpenAPI object _(`type: object`)_.
1679///   _`Value`_ will be rendered as any OpenAPI value (i.e. no `type` restriction).
1680///
1681/// * `inline` If set, the schema for this field's type needs to be a [`ToSchema`][to_schema], and
1682///   the schema definition will be inlined.
1683///
1684/// * `default = ...` Can be method reference or _`json!(...)`_.
1685///
1686/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
1687///   an open value as a string. By default the format is derived from the type of the property
1688///   according OpenApi spec.
1689///
1690/// * `write_only` Defines property is only used in **write** operations *POST,PUT,PATCH* but not in *GET*
1691///
1692/// * `read_only` Defines property is only used in **read** operations *GET* but not in *POST,PUT,PATCH*
1693///
1694/// * `xml(...)` Can be used to define [`Xml`][xml] object properties applicable to named fields.
1695///    See configuration options at xml attributes of [`ToSchema`][to_schema_xml]
1696///
1697/// * `nullable` Defines property is nullable (note this is different to non-required).
1698///
1699/// * `required = ...` Can be used to enforce required status for the parameter. [See
1700///    rules][derive@IntoParams#field-nullability-and-required-rules]
1701///
1702/// * `rename = ...` Can be provided to alternatively to the serde's `rename` attribute. Effectively provides same functionality.
1703///
1704/// * `multiple_of = ...` Can be used to define multiplier for a value. Value is considered valid
1705///   division will result an `integer`. Value must be strictly above _`0`_.
1706///
1707/// * `maximum = ...` Can be used to define inclusive upper bound to a `number` value.
1708///
1709/// * `minimum = ...` Can be used to define inclusive lower bound to a `number` value.
1710///
1711/// * `exclusive_maximum = ...` Can be used to define exclusive upper bound to a `number` value.
1712///
1713/// * `exclusive_minimum = ...` Can be used to define exclusive lower bound to a `number` value.
1714///
1715/// * `max_length = ...` Can be used to define maximum length for `string` types.
1716///
1717/// * `min_length = ...` Can be used to define minimum length for `string` types.
1718///
1719/// * `pattern = ...` Can be used to define valid regular expression in _ECMA-262_ dialect the field value must match.
1720///
1721/// * `max_items = ...` Can be used to define maximum items allowed for `array` fields. Value must
1722///   be non-negative integer.
1723///
1724/// * `min_items = ...` Can be used to define minimum items allowed for `array` fields. Value must
1725///   be non-negative integer.
1726///
1727/// * `schema_with = ...` Use _`schema`_ created by provided function reference instead of the
1728///   default derived _`schema`_. The function must match to `fn() -> Into<RefOr<Schema>>`. It does
1729///   not accept arguments and must return anything that can be converted into `RefOr<Schema>`.
1730///
1731/// * `additional_properties = ...` Can be used to define free form types for maps such as
1732///   [`HashMap`](std::collections::HashMap) and [`BTreeMap`](std::collections::BTreeMap).
1733///   Free form type enables use of arbitrary types within map values.
1734///   Supports formats _`additional_properties`_ and _`additional_properties = true`_.
1735///
1736/// #### Field nullability and required rules
1737///
1738/// Same rules for nullability and required status apply for _`IntoParams`_ field attributes as for
1739/// _`ToSchema`_ field attributes. [See the rules][`derive@ToSchema#field-nullability-and-required-rules`].
1740///
1741/// # Partial `#[serde(...)]` attributes support
1742///
1743/// IntoParams derive has partial support for [serde attributes]. These supported attributes will reflect to the
1744/// generated OpenAPI doc. The following attributes are currently supported:
1745///
1746/// * `rename_all = "..."` Supported at the container level.
1747/// * `rename = "..."` Supported **only** at the field level.
1748/// * `default` Supported at the container level and field level according to [serde attributes].
1749/// * `skip_serializing_if = "..."` Supported  **only** at the field level.
1750/// * `with = ...` Supported **only** at field level.
1751/// * `skip_serializing = "..."` Supported  **only** at the field or variant level.
1752/// * `skip_deserializing = "..."` Supported  **only** at the field or variant level.
1753/// * `skip = "..."` Supported  **only** at the field level.
1754///
1755/// Other _`serde`_ attributes will impact the serialization but will not be reflected on the generated OpenAPI doc.
1756///
1757/// # Examples
1758///
1759/// _**Demonstrate [`IntoParams`][into_params] usage with resolving `Path` and `Query` parameters
1760/// with _`actix-web`_**_.
1761/// ```rust
1762/// use actix_web::{get, HttpResponse, Responder};
1763/// use actix_web::web::{Path, Query};
1764/// use serde::Deserialize;
1765/// use serde_json::json;
1766/// use utoipa::IntoParams;
1767///
1768/// #[derive(Deserialize, IntoParams)]
1769/// struct PetPathArgs {
1770///     /// Id of pet
1771///     id: i64,
1772///     /// Name of pet
1773///     name: String,
1774/// }
1775///
1776/// #[derive(Deserialize, IntoParams)]
1777/// struct Filter {
1778///     /// Age filter for pets
1779///     #[deprecated]
1780///     #[param(style = Form, explode, allow_reserved, example = json!([10]))]
1781///     age: Option<Vec<i32>>,
1782/// }
1783///
1784/// #[utoipa::path(
1785///     params(PetPathArgs, Filter),
1786///     responses(
1787///         (status = 200, description = "success response")
1788///     )
1789/// )]
1790/// #[get("/pet/{id}/{name}")]
1791/// async fn get_pet(pet: Path<PetPathArgs>, query: Query<Filter>) -> impl Responder {
1792///     HttpResponse::Ok().json(json!({ "id": pet.id }))
1793/// }
1794/// ```
1795///
1796/// _**Demonstrate [`IntoParams`][into_params] usage with the `#[into_params(...)]` container attribute to
1797/// be used as a path query, and inlining a schema query field:**_
1798/// ```rust
1799/// use serde::Deserialize;
1800/// use utoipa::{IntoParams, ToSchema};
1801///
1802/// #[derive(Deserialize, ToSchema)]
1803/// #[serde(rename_all = "snake_case")]
1804/// enum PetKind {
1805///     Dog,
1806///     Cat,
1807/// }
1808///
1809/// #[derive(Deserialize, IntoParams)]
1810/// #[into_params(style = Form, parameter_in = Query)]
1811/// struct PetQuery {
1812///     /// Name of pet
1813///     name: Option<String>,
1814///     /// Age of pet
1815///     age: Option<i32>,
1816///     /// Kind of pet
1817///     #[param(inline)]
1818///     kind: PetKind
1819/// }
1820///
1821/// #[utoipa::path(
1822///     get,
1823///     path = "/get_pet",
1824///     params(PetQuery),
1825///     responses(
1826///         (status = 200, description = "success response")
1827///     )
1828/// )]
1829/// async fn get_pet(query: PetQuery) {
1830///     // ...
1831/// }
1832/// ```
1833///
1834/// _**Override `String` with `i64` using `value_type` attribute.**_
1835/// ```rust
1836/// # use utoipa::IntoParams;
1837/// #
1838/// #[derive(IntoParams)]
1839/// #[into_params(parameter_in = Query)]
1840/// struct Filter {
1841///     #[param(value_type = i64)]
1842///     id: String,
1843/// }
1844/// ```
1845///
1846/// _**Override `String` with `Object` using `value_type` attribute. _`Object`_ will render as `type: object` in OpenAPI spec.**_
1847/// ```rust
1848/// # use utoipa::IntoParams;
1849/// #
1850/// #[derive(IntoParams)]
1851/// #[into_params(parameter_in = Query)]
1852/// struct Filter {
1853///     #[param(value_type = Object)]
1854///     id: String,
1855/// }
1856/// ```
1857///
1858/// _**You can use a generic type to override the default type of the field.**_
1859/// ```rust
1860/// # use utoipa::IntoParams;
1861/// #
1862/// #[derive(IntoParams)]
1863/// #[into_params(parameter_in = Query)]
1864/// struct Filter {
1865///     #[param(value_type = Option<String>)]
1866///     id: String
1867/// }
1868/// ```
1869///
1870/// _**You can even override a [`Vec`] with another one.**_
1871/// ```rust
1872/// # use utoipa::IntoParams;
1873/// #
1874/// #[derive(IntoParams)]
1875/// #[into_params(parameter_in = Query)]
1876/// struct Filter {
1877///     #[param(value_type = Vec<i32>)]
1878///     id: Vec<String>
1879/// }
1880/// ```
1881///
1882/// _**We can override value with another [`ToSchema`][to_schema].**_
1883/// ```rust
1884/// # use utoipa::{IntoParams, ToSchema};
1885/// #
1886/// #[derive(ToSchema)]
1887/// struct Id {
1888///     value: i64,
1889/// }
1890///
1891/// #[derive(IntoParams)]
1892/// #[into_params(parameter_in = Query)]
1893/// struct Filter {
1894///     #[param(value_type = Id)]
1895///     id: String
1896/// }
1897/// ```
1898///
1899/// _**Example with validation attributes.**_
1900/// ```rust
1901/// #[derive(utoipa::IntoParams)]
1902/// struct Item {
1903///     #[param(maximum = 10, minimum = 5, multiple_of = 2.5)]
1904///     id: i32,
1905///     #[param(max_length = 10, min_length = 5, pattern = "[a-z]*")]
1906///     value: String,
1907///     #[param(max_items = 5, min_items = 1)]
1908///     items: Vec<String>,
1909/// }
1910/// ````
1911///
1912/// _**Use `schema_with` to manually implement schema for a field.**_
1913/// ```rust
1914/// # use utoipa::openapi::schema::{Object, ObjectBuilder};
1915/// fn custom_type() -> Object {
1916///     ObjectBuilder::new()
1917///         .schema_type(utoipa::openapi::SchemaType::String)
1918///         .format(Some(utoipa::openapi::SchemaFormat::Custom(
1919///             "email".to_string(),
1920///         )))
1921///         .description(Some("this is the description"))
1922///         .build()
1923/// }
1924///
1925/// #[derive(utoipa::IntoParams)]
1926/// #[into_params(parameter_in = Query)]
1927/// struct Query {
1928///     #[param(schema_with = custom_type)]
1929///     email: String,
1930/// }
1931/// ```
1932///
1933/// [to_schema]: trait.ToSchema.html
1934/// [known_format]: openapi/schema/enum.KnownFormat.html
1935/// [xml]: openapi/xml/struct.Xml.html
1936/// [into_params]: trait.IntoParams.html
1937/// [path_params]: attr.path.html#params-attributes
1938/// [struct]: https://doc.rust-lang.org/std/keyword.struct.html
1939/// [style]: openapi/path/enum.ParameterStyle.html
1940/// [in_enum]: openapi/path/enum.ParameterIn.html
1941/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
1942/// [serde attributes]: https://serde.rs/attributes.html
1943/// [to_schema_xml]: macro@ToSchema#xml-attribute-configuration-options
1944pub fn into_params(input: TokenStream) -> TokenStream {
1945    let DeriveInput {
1946        attrs,
1947        ident,
1948        generics,
1949        data,
1950        ..
1951    } = syn::parse_macro_input!(input);
1952
1953    let into_params = IntoParams {
1954        attrs,
1955        generics,
1956        data,
1957        ident,
1958    };
1959
1960    into_params.to_token_stream().into()
1961}
1962
1963#[proc_macro_error]
1964#[proc_macro_derive(ToResponse, attributes(response, content, to_schema))]
1965/// Generate reusable OpenAPI response what can be used
1966/// in [`utoipa::path`][path] or in [`OpenApi`][openapi].
1967///
1968/// This is `#[derive]` implementation for [`ToResponse`][to_response] trait.
1969///
1970///
1971/// _`#[response]`_ attribute can be used to alter and add [response attributes](#toresponse-response-attributes).
1972///
1973/// _`#[content]`_ attributes is used to make enum variant a content of a specific type for the
1974/// response.
1975///
1976/// _`#[to_schema]`_ attribute is used to inline a schema for a response in unnamed structs or
1977/// enum variants with `#[content]` attribute. **Note!** [`ToSchema`] need to be implemented for
1978/// the field or variant type.
1979///
1980/// Type derived with _`ToResponse`_ uses provided doc comment as a description for the response. It
1981/// can alternatively be overridden with _`description = ...`_ attribute.
1982///
1983/// _`ToResponse`_ can be used in four different ways to generate OpenAPI response component.
1984///
1985/// 1. By decorating `struct` or `enum` with [`derive@ToResponse`] derive macro. This will create a
1986///    response with inlined schema resolved from the fields of the `struct` or `variants` of the
1987///    enum.
1988///
1989///    ```rust
1990///     # use utoipa::ToResponse;
1991///     #[derive(ToResponse)]
1992///     #[response(description = "Person response returns single Person entity")]
1993///     struct Person {
1994///         name: String,
1995///     }
1996///    ```
1997///
1998/// 2. By decorating unnamed field `struct` with [`derive@ToResponse`] derive macro. Unnamed field struct
1999///    allows users to use new type pattern to define one inner field which is used as a schema for
2000///    the generated response. This allows users to define `Vec` and `Option` response types.
2001///    Additionally these types can also be used with `#[to_schema]` attribute to inline the
2002///    field's type schema if it implements [`ToSchema`] derive macro.
2003///
2004///    ```rust
2005///     # #[derive(utoipa::ToSchema)]
2006///     # struct Person {
2007///     #     name: String,
2008///     # }
2009///     /// Person list response
2010///     #[derive(utoipa::ToResponse)]
2011///     struct PersonList(Vec<Person>);
2012///    ```
2013///
2014/// 3. By decorating unit struct with [`derive@ToResponse`] derive macro. Unit structs will produce a
2015///    response without body.
2016///
2017///    ```rust
2018///     /// Success response which does not have body.
2019///     #[derive(utoipa::ToResponse)]
2020///     struct SuccessResponse;
2021///    ```
2022///
2023/// 4. By decorating `enum` with variants having `#[content(...)]` attribute. This allows users to
2024///    define multiple response content schemas to single response according to OpenAPI spec.
2025///    **Note!** Enum with _`content`_ attribute in variants cannot have enum level _`example`_ or
2026///    _`examples`_ defined. Instead examples need to be defined per variant basis. Additionally
2027///    these variants can also be used with `#[to_schema]` attribute to inline the variant's type schema
2028///    if it implements [`ToSchema`] derive macro.
2029///
2030///    ```rust
2031///     #[derive(utoipa::ToSchema)]
2032///     struct Admin {
2033///         name: String,
2034///     }
2035///     #[derive(utoipa::ToSchema)]
2036///     struct Admin2 {
2037///         name: String,
2038///         id: i32,
2039///     }
2040///
2041///     #[derive(utoipa::ToResponse)]
2042///     enum Person {
2043///         #[response(examples(
2044///             ("Person1" = (value = json!({"name": "name1"}))),
2045///             ("Person2" = (value = json!({"name": "name2"})))
2046///         ))]
2047///         Admin(#[content("application/vnd-custom-v1+json")] Admin),
2048///
2049///         #[response(example = json!({"name": "name3", "id": 1}))]
2050///         Admin2(#[content("application/vnd-custom-v2+json")] #[to_schema] Admin2),
2051///     }
2052///    ```
2053///
2054/// # ToResponse `#[response(...)]` attributes
2055///
2056/// * `description = "..."` Define description for the response as str. This can be used to
2057///   override the default description resolved from doc comments if present.
2058///
2059/// * `content_type = "..." | content_type = [...]` Can be used to override the default behavior of auto resolving the content type
2060///   from the `body` attribute. If defined the value should be valid content type such as
2061///   _`application/json`_. By default the content type is _`text/plain`_ for
2062///   [primitive Rust types][primitive], `application/octet-stream` for _`[u8]`_ and
2063///   _`application/json`_ for struct and complex enum types.
2064///   Content type can also be slice of **content_type** values if the endpoint support returning multiple
2065///  response content types. E.g _`["application/json", "text/xml"]`_ would indicate that endpoint can return both
2066///  _`json`_ and _`xml`_ formats. **The order** of the content types define the default example show first in
2067///  the Swagger UI. Swagger UI wil use the first _`content_type`_ value as a default example.
2068///
2069/// * `headers(...)` Slice of response headers that are returned back to a caller.
2070///
2071/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
2072///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
2073///
2074/// * `examples(...)` Define multiple examples for single response. This attribute is mutually
2075///   exclusive to the _`example`_ attribute and if both are defined this will override the _`example`_.
2076///     * `name = ...` This is first attribute and value must be literal string.
2077///     * `summary = ...` Short description of example. Value must be literal string.
2078///     * `description = ...` Long description of example. Attribute supports markdown for rich text
2079///       representation. Value must be literal string.
2080///     * `value = ...` Example value. It must be _`json!(...)`_. _`json!(...)`_ should be something that
2081///       _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
2082///     * `external_value = ...` Define URI to literal example value. This is mutually exclusive to
2083///       the _`value`_ attribute. Value must be literal string.
2084///
2085///      _**Example of example definition.**_
2086///     ```text
2087///      ("John" = (summary = "This is John", value = json!({"name": "John"})))
2088///     ```
2089///
2090/// # Examples
2091///
2092/// _**Use reusable response in operation handler.**_
2093/// ```rust
2094/// #[derive(utoipa::ToResponse)]
2095/// struct PersonResponse {
2096///    value: String
2097/// }
2098///
2099/// #[derive(utoipa::OpenApi)]
2100/// #[openapi(components(responses(PersonResponse)))]
2101/// struct Doc;
2102///
2103/// #[utoipa::path(
2104///     get,
2105///     path = "/api/person",
2106///     responses(
2107///         (status = 200, response = PersonResponse)
2108///     )
2109/// )]
2110/// fn get_person() -> PersonResponse {
2111///     PersonResponse { value: "person".to_string() }
2112/// }
2113/// ```
2114///
2115/// _**Create a response from named struct.**_
2116/// ```rust
2117///  /// This is description
2118///  ///
2119///  /// It will also be used in `ToSchema` if present
2120///  #[derive(utoipa::ToSchema, utoipa::ToResponse)]
2121///  #[response(
2122///      description = "Override description for response",
2123///      content_type = "text/xml"
2124///  )]
2125///  #[response(
2126///      example = json!({"name": "the name"}),
2127///      headers(
2128///          ("csrf-token", description = "response csrf token"),
2129///          ("random-id" = i32)
2130///      )
2131///  )]
2132///  struct Person {
2133///      name: String,
2134///  }
2135/// ```
2136///
2137/// _**Create inlined person list response.**_
2138/// ```rust
2139///  # #[derive(utoipa::ToSchema)]
2140///  # struct Person {
2141///  #     name: String,
2142///  # }
2143///  /// Person list response
2144///  #[derive(utoipa::ToResponse)]
2145///  struct PersonList(#[to_schema] Vec<Person>);
2146/// ```
2147///
2148/// _**Create enum response from variants.**_
2149/// ```rust
2150///  #[derive(utoipa::ToResponse)]
2151///  enum PersonType {
2152///      Value(String),
2153///      Foobar,
2154///  }
2155/// ```
2156///
2157/// [to_response]: trait.ToResponse.html
2158/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
2159/// [path]: attr.path.html
2160/// [openapi]: derive.OpenApi.html
2161pub fn to_response(input: TokenStream) -> TokenStream {
2162    let DeriveInput {
2163        attrs,
2164        ident,
2165        generics,
2166        data,
2167        ..
2168    } = syn::parse_macro_input!(input);
2169
2170    let response = ToResponse::new(attrs, &data, generics, ident);
2171
2172    response.to_token_stream().into()
2173}
2174
2175#[proc_macro_error]
2176#[proc_macro_derive(
2177    IntoResponses,
2178    attributes(response, to_schema, ref_response, to_response)
2179)]
2180/// Generate responses with status codes what
2181/// can be attached to the [`utoipa::path`][path_into_responses].
2182///
2183/// This is `#[derive]` implementation of [`IntoResponses`][into_responses] trait. [`derive@IntoResponses`]
2184/// can be used to decorate _`structs`_ and _`enums`_ to generate response maps that can be used in
2185/// [`utoipa::path`][path_into_responses]. If _`struct`_ is decorated with [`derive@IntoResponses`] it will be
2186/// used to create a map of responses containing single response. Decorating _`enum`_ with
2187/// [`derive@IntoResponses`] will create a map of responses with a response for each variant of the _`enum`_.
2188///
2189/// Named field _`struct`_ decorated with [`derive@IntoResponses`] will create a response with inlined schema
2190/// generated from the body of the struct. This is a conveniency which allows users to directly
2191/// create responses with schemas without first creating a separate [response][to_response] type.
2192///
2193/// Unit _`struct`_ behaves similarly to then named field struct. Only difference is that it will create
2194/// a response without content since there is no inner fields.
2195///
2196/// Unnamed field _`struct`_ decorated with [`derive@IntoResponses`] will by default create a response with
2197/// referenced [schema][to_schema] if field is object or schema if type is [primitive
2198/// type][primitive]. _`#[to_schema]`_ attribute at field of unnamed _`struct`_ can be used to inline
2199/// the schema if type of the field implements [`ToSchema`][to_schema] trait. Alternatively
2200/// _`#[to_response]`_ and _`#[ref_response]`_ can be used at field to either reference a reusable
2201/// [response][to_response] or inline a reusable [response][to_response]. In both cases the field
2202/// type is expected to implement [`ToResponse`][to_response] trait.
2203///
2204///
2205/// Enum decorated with [`derive@IntoResponses`] will create a response for each variant of the _`enum`_.
2206/// Each variant must have it's own _`#[response(...)]`_ definition. Unit variant will behave same
2207/// as unit _`struct`_ by creating a response without content. Similarly named field variant and
2208/// unnamed field variant behaves the same as it was named field _`struct`_ and unnamed field
2209/// _`struct`_.
2210///
2211/// _`#[response]`_ attribute can be used at named structs, unnamed structs, unit structs and enum
2212/// variants to alter [response attributes](#intoresponses-response-attributes) of responses.
2213///
2214/// Doc comment on a _`struct`_ or _`enum`_ variant will be used as a description for the response.
2215/// It can also be overridden with _`description = "..."`_ attribute.
2216///
2217/// # IntoResponses `#[response(...)]` attributes
2218///
2219/// * `status = ...` Must be provided. Is either a valid http status code integer. E.g. _`200`_ or a
2220///   string value representing a range such as _`"4XX"`_ or `"default"` or a valid _`http::status::StatusCode`_.
2221///   _`StatusCode`_ can either be use path to the status code or _status code_ constant directly.
2222///
2223/// * `description = "..."` Define description for the response as str. This can be used to
2224///   override the default description resolved from doc comments if present.
2225///
2226/// * `content_type = "..." | content_type = [...]` Can be used to override the default behavior of auto resolving the content type
2227///   from the `body` attribute. If defined the value should be valid content type such as
2228///   _`application/json`_. By default the content type is _`text/plain`_ for
2229///   [primitive Rust types][primitive], `application/octet-stream` for _`[u8]`_ and
2230///   _`application/json`_ for struct and complex enum types.
2231///   Content type can also be slice of **content_type** values if the endpoint support returning multiple
2232///  response content types. E.g _`["application/json", "text/xml"]`_ would indicate that endpoint can return both
2233///  _`json`_ and _`xml`_ formats. **The order** of the content types define the default example show first in
2234///  the Swagger UI. Swagger UI wil use the first _`content_type`_ value as a default example.
2235///
2236/// * `headers(...)` Slice of response headers that are returned back to a caller.
2237///
2238/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
2239///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
2240///
2241/// * `examples(...)` Define multiple examples for single response. This attribute is mutually
2242///   exclusive to the _`example`_ attribute and if both are defined this will override the _`example`_.
2243///     * `name = ...` This is first attribute and value must be literal string.
2244///     * `summary = ...` Short description of example. Value must be literal string.
2245///     * `description = ...` Long description of example. Attribute supports markdown for rich text
2246///       representation. Value must be literal string.
2247///     * `value = ...` Example value. It must be _`json!(...)`_. _`json!(...)`_ should be something that
2248///       _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
2249///     * `external_value = ...` Define URI to literal example value. This is mutually exclusive to
2250///       the _`value`_ attribute. Value must be literal string.
2251///
2252///      _**Example of example definition.**_
2253///     ```text
2254///      ("John" = (summary = "This is John", value = json!({"name": "John"})))
2255///     ```
2256///
2257/// # Examples
2258///
2259/// _**Use `IntoResponses` to define [`utoipa::path`][path] responses.**_
2260/// ```rust
2261/// #[derive(utoipa::ToSchema)]
2262/// struct BadRequest {
2263///     message: String,
2264/// }
2265///
2266/// #[derive(utoipa::IntoResponses)]
2267/// enum UserResponses {
2268///     /// Success response
2269///     #[response(status = 200)]
2270///     Success { value: String },
2271///
2272///     #[response(status = 404)]
2273///     NotFound,
2274///
2275///     #[response(status = 400)]
2276///     BadRequest(BadRequest),
2277/// }
2278///
2279/// #[utoipa::path(
2280///     get,
2281///     path = "/api/user",
2282///     responses(
2283///         UserResponses
2284///     )
2285/// )]
2286/// fn get_user() -> UserResponses {
2287///    UserResponses::NotFound
2288/// }
2289/// ```
2290/// _**Named struct response with inlined schema.**_
2291/// ```rust
2292/// /// This is success response
2293/// #[derive(utoipa::IntoResponses)]
2294/// #[response(status = 200)]
2295/// struct SuccessResponse {
2296///     value: String,
2297/// }
2298/// ```
2299///
2300/// _**Unit struct response without content.**_
2301/// ```rust
2302/// #[derive(utoipa::IntoResponses)]
2303/// #[response(status = NOT_FOUND)]
2304/// struct NotFound;
2305/// ```
2306///
2307/// _**Unnamed struct response with inlined response schema.**_
2308/// ```rust
2309/// # #[derive(utoipa::ToSchema)]
2310/// # struct Foo;
2311/// #[derive(utoipa::IntoResponses)]
2312/// #[response(status = 201)]
2313/// struct CreatedResponse(#[to_schema] Foo);
2314/// ```
2315///
2316/// _**Enum with multiple responses.**_
2317/// ```rust
2318/// # #[derive(utoipa::ToResponse)]
2319/// # struct Response {
2320/// #     message: String,
2321/// # }
2322/// # #[derive(utoipa::ToSchema)]
2323/// # struct BadRequest {}
2324/// #[derive(utoipa::IntoResponses)]
2325/// enum UserResponses {
2326///     /// Success response description.
2327///     #[response(status = 200)]
2328///     Success { value: String },
2329///
2330///     #[response(status = 404)]
2331///     NotFound,
2332///
2333///     #[response(status = 400)]
2334///     BadRequest(BadRequest),
2335///
2336///     #[response(status = 500)]
2337///     ServerError(#[ref_response] Response),
2338///
2339///     #[response(status = 418)]
2340///     TeaPot(#[to_response] Response),
2341/// }
2342/// ```
2343///
2344/// [into_responses]: trait.IntoResponses.html
2345/// [to_schema]: trait.ToSchema.html
2346/// [to_response]: trait.ToResponse.html
2347/// [path_into_responses]: attr.path.html#responses-from-intoresponses
2348/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
2349/// [path]: macro@crate::path
2350pub fn into_responses(input: TokenStream) -> TokenStream {
2351    let DeriveInput {
2352        attrs,
2353        ident,
2354        generics,
2355        data,
2356        ..
2357    } = syn::parse_macro_input!(input);
2358
2359    let into_responses = IntoResponses {
2360        attributes: attrs,
2361        ident,
2362        generics,
2363        data,
2364    };
2365
2366    into_responses.to_token_stream().into()
2367}
2368
2369/// Create OpenAPI Schema from arbitrary type.
2370///
2371/// This macro provides a quick way to render arbitrary types as OpenAPI Schema Objects. It
2372/// supports two call formats.
2373/// 1. With type only
2374/// 2. With _`#[inline]`_ attribute to inline the referenced schemas.
2375///
2376/// By default the macro will create references `($ref)` for non primitive types like _`Pet`_.
2377/// However when used with _`#[inline]`_ the non [`primitive`][primitive] type schemas will
2378/// be inlined to the schema output.
2379///
2380/// ```rust
2381/// # #[derive(utoipa::ToSchema)]
2382/// # struct Pet {id: i32};
2383/// let schema = utoipa::schema!(Vec<Pet>);
2384///
2385/// // with inline
2386/// let schema = utoipa::schema!(#[inline] Vec<Pet>);
2387/// ```
2388///
2389/// # Examples
2390///
2391/// _**Create vec of pets schema.**_
2392/// ```rust
2393/// # use utoipa::openapi::schema::{Schema, Array, Object, ObjectBuilder, SchemaFormat,
2394/// # KnownFormat, SchemaType};
2395/// # use utoipa::openapi::RefOr;
2396/// #[derive(utoipa::ToSchema)]
2397/// struct Pet {
2398///     id: i32,
2399///     name: String,
2400/// }
2401///
2402/// let schema: RefOr<Schema> = utoipa::schema!(#[inline] Vec<Pet>).into();
2403/// // will output
2404/// let generated = RefOr::T(Schema::Array(
2405///     Array::new(
2406///         ObjectBuilder::new()
2407///             .property("id", ObjectBuilder::new()
2408///                 .schema_type(SchemaType::Integer)
2409///                 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2410///                 .build())
2411///             .required("id")
2412///             .property("name", Object::with_type(SchemaType::String))
2413///             .required("name")
2414///     )
2415/// ));
2416/// # assert_json_diff::assert_json_eq!(serde_json::to_value(&schema).unwrap(), serde_json::to_value(&generated).unwrap());
2417/// ```
2418///
2419/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
2420#[proc_macro]
2421pub fn schema(input: TokenStream) -> TokenStream {
2422    struct Schema {
2423        inline: bool,
2424        ty: syn::Type,
2425    }
2426    impl Parse for Schema {
2427        fn parse(input: ParseStream) -> syn::Result<Self> {
2428            let inline = if input.peek(Token![#]) && input.peek2(Bracket) {
2429                input.parse::<Token![#]>()?;
2430
2431                let inline;
2432                bracketed!(inline in input);
2433                let i = inline.parse::<Ident>()?;
2434                i == "inline"
2435            } else {
2436                false
2437            };
2438
2439            let ty = input.parse()?;
2440
2441            Ok(Self { inline, ty })
2442        }
2443    }
2444
2445    let schema = syn::parse_macro_input!(input as Schema);
2446    let type_tree = TypeTree::from_type(&schema.ty);
2447
2448    let schema = ComponentSchema::new(ComponentSchemaProps {
2449        features: Some(vec![Feature::Inline(schema.inline.into())]),
2450        type_tree: &type_tree,
2451        deprecated: None,
2452        description: None,
2453        object_name: "",
2454    });
2455
2456    schema.to_token_stream().into()
2457}
2458
2459/// Tokenizes slice or Vec of tokenizable items as array either with reference (`&[...]`)
2460/// or without correctly to OpenAPI JSON.
2461#[cfg_attr(feature = "debug", derive(Debug))]
2462enum Array<'a, T>
2463where
2464    T: Sized + ToTokens,
2465{
2466    Owned(Vec<T>),
2467    #[allow(dead_code)]
2468    Borrowed(&'a [T]),
2469}
2470
2471impl<T> Array<'_, T> where T: ToTokens + Sized {}
2472
2473impl<V> FromIterator<V> for Array<'_, V>
2474where
2475    V: Sized + ToTokens,
2476{
2477    fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
2478        Self::Owned(iter.into_iter().collect())
2479    }
2480}
2481
2482impl<'a, T> Deref for Array<'a, T>
2483where
2484    T: Sized + ToTokens,
2485{
2486    type Target = [T];
2487
2488    fn deref(&self) -> &Self::Target {
2489        match self {
2490            Self::Owned(vec) => vec.as_slice(),
2491            Self::Borrowed(slice) => slice,
2492        }
2493    }
2494}
2495
2496impl<T> ToTokens for Array<'_, T>
2497where
2498    T: Sized + ToTokens,
2499{
2500    fn to_tokens(&self, tokens: &mut TokenStream2) {
2501        let values = match self {
2502            Self::Owned(values) => values.iter(),
2503            Self::Borrowed(values) => values.iter(),
2504        };
2505
2506        tokens.append(Group::new(
2507            proc_macro2::Delimiter::Bracket,
2508            values
2509                .fold(Punctuated::new(), |mut punctuated, item| {
2510                    punctuated.push_value(item);
2511                    punctuated.push_punct(Punct::new(',', proc_macro2::Spacing::Alone));
2512
2513                    punctuated
2514                })
2515                .to_token_stream(),
2516        ));
2517    }
2518}
2519
2520#[cfg_attr(feature = "debug", derive(Debug))]
2521enum Deprecated {
2522    True,
2523    False,
2524}
2525
2526impl From<bool> for Deprecated {
2527    fn from(bool: bool) -> Self {
2528        if bool {
2529            Self::True
2530        } else {
2531            Self::False
2532        }
2533    }
2534}
2535
2536impl ToTokens for Deprecated {
2537    fn to_tokens(&self, tokens: &mut TokenStream2) {
2538        tokens.extend(match self {
2539            Self::False => quote! { utoipa::openapi::Deprecated::False },
2540            Self::True => quote! { utoipa::openapi::Deprecated::True },
2541        })
2542    }
2543}
2544
2545#[derive(PartialEq, Eq)]
2546#[cfg_attr(feature = "debug", derive(Debug))]
2547enum Required {
2548    True,
2549    False,
2550}
2551
2552impl From<bool> for Required {
2553    fn from(bool: bool) -> Self {
2554        if bool {
2555            Self::True
2556        } else {
2557            Self::False
2558        }
2559    }
2560}
2561
2562impl From<features::Required> for Required {
2563    fn from(value: features::Required) -> Self {
2564        let features::Required(required) = value;
2565        crate::Required::from(required)
2566    }
2567}
2568
2569impl ToTokens for Required {
2570    fn to_tokens(&self, tokens: &mut TokenStream2) {
2571        tokens.extend(match self {
2572            Self::False => quote! { utoipa::openapi::Required::False },
2573            Self::True => quote! { utoipa::openapi::Required::True },
2574        })
2575    }
2576}
2577
2578#[derive(Default)]
2579#[cfg_attr(feature = "debug", derive(Debug))]
2580struct ExternalDocs {
2581    url: String,
2582    description: Option<String>,
2583}
2584
2585impl Parse for ExternalDocs {
2586    fn parse(input: ParseStream) -> syn::Result<Self> {
2587        const EXPECTED_ATTRIBUTE: &str = "unexpected attribute, expected any of: url, description";
2588
2589        let mut external_docs = ExternalDocs::default();
2590
2591        while !input.is_empty() {
2592            let ident = input.parse::<Ident>().map_err(|error| {
2593                syn::Error::new(error.span(), format!("{EXPECTED_ATTRIBUTE}, {error}"))
2594            })?;
2595            let attribute_name = &*ident.to_string();
2596
2597            match attribute_name {
2598                "url" => {
2599                    external_docs.url = parse_utils::parse_next_literal_str(input)?;
2600                }
2601                "description" => {
2602                    external_docs.description = Some(parse_utils::parse_next_literal_str(input)?);
2603                }
2604                _ => return Err(syn::Error::new(ident.span(), EXPECTED_ATTRIBUTE)),
2605            }
2606
2607            if !input.is_empty() {
2608                input.parse::<Token![,]>()?;
2609            }
2610        }
2611
2612        Ok(external_docs)
2613    }
2614}
2615
2616impl ToTokens for ExternalDocs {
2617    fn to_tokens(&self, tokens: &mut TokenStream2) {
2618        let url = &self.url;
2619        tokens.extend(quote! {
2620            utoipa::openapi::external_docs::ExternalDocsBuilder::new()
2621                .url(#url)
2622        });
2623
2624        if let Some(ref description) = self.description {
2625            tokens.extend(quote! {
2626                .description(Some(#description))
2627            });
2628        }
2629
2630        tokens.extend(quote! { .build() })
2631    }
2632}
2633
2634/// Represents OpenAPI Any value used in example and default fields.
2635#[derive(Clone)]
2636#[cfg_attr(feature = "debug", derive(Debug))]
2637pub(self) enum AnyValue {
2638    String(TokenStream2),
2639    Json(TokenStream2),
2640    DefaultTrait {
2641        struct_ident: Ident,
2642        field_ident: Member,
2643    },
2644}
2645
2646impl AnyValue {
2647    /// Parse `json!(...)` as [`AnyValue::Json`]
2648    fn parse_json(input: ParseStream) -> syn::Result<Self> {
2649        parse_utils::parse_json_token_stream(input).map(AnyValue::Json)
2650    }
2651
2652    fn parse_any(input: ParseStream) -> syn::Result<Self> {
2653        if input.peek(Lit) {
2654            if input.peek(LitStr) {
2655                let lit_str = input.parse::<LitStr>().unwrap().to_token_stream();
2656
2657                Ok(AnyValue::Json(lit_str))
2658            } else {
2659                let lit = input.parse::<Lit>().unwrap().to_token_stream();
2660
2661                Ok(AnyValue::Json(lit))
2662            }
2663        } else {
2664            let fork = input.fork();
2665            let is_json = if fork.peek(syn::Ident) && fork.peek2(Token![!]) {
2666                let ident = fork.parse::<Ident>().unwrap();
2667                ident == "json"
2668            } else {
2669                false
2670            };
2671
2672            if is_json {
2673                let json = parse_utils::parse_json_token_stream(input)?;
2674
2675                Ok(AnyValue::Json(json))
2676            } else {
2677                let method = input.parse::<ExprPath>().map_err(|error| {
2678                    syn::Error::new(
2679                        error.span(),
2680                        "expected literal value, json!(...) or method reference",
2681                    )
2682                })?;
2683
2684                Ok(AnyValue::Json(quote! { #method() }))
2685            }
2686        }
2687    }
2688
2689    fn parse_lit_str_or_json(input: ParseStream) -> syn::Result<Self> {
2690        if input.peek(LitStr) {
2691            Ok(AnyValue::String(
2692                input.parse::<LitStr>().unwrap().to_token_stream(),
2693            ))
2694        } else {
2695            Ok(AnyValue::Json(parse_utils::parse_json_token_stream(input)?))
2696        }
2697    }
2698
2699    fn new_default_trait(struct_ident: Ident, field_ident: Member) -> Self {
2700        Self::DefaultTrait {
2701            struct_ident,
2702            field_ident,
2703        }
2704    }
2705}
2706
2707impl ToTokens for AnyValue {
2708    fn to_tokens(&self, tokens: &mut TokenStream2) {
2709        match self {
2710            Self::Json(json) => tokens.extend(quote! {
2711                serde_json::json!(#json)
2712            }),
2713            Self::String(string) => string.to_tokens(tokens),
2714            Self::DefaultTrait {
2715                struct_ident,
2716                field_ident,
2717            } => tokens.extend(quote! {
2718                serde_json::to_value(#struct_ident::default().#field_ident).unwrap()
2719            }),
2720        }
2721    }
2722}
2723
2724trait ResultExt<T> {
2725    fn unwrap_or_abort(self) -> T;
2726    fn expect_or_abort(self, message: &str) -> T;
2727}
2728
2729impl<T> ResultExt<T> for Result<T, syn::Error> {
2730    fn unwrap_or_abort(self) -> T {
2731        match self {
2732            Ok(value) => value,
2733            Err(error) => abort!(error.span(), format!("{error}")),
2734        }
2735    }
2736
2737    fn expect_or_abort(self, message: &str) -> T {
2738        match self {
2739            Ok(value) => value,
2740            Err(error) => abort!(error.span(), format!("{error}: {message}")),
2741        }
2742    }
2743}
2744
2745trait OptionExt<T> {
2746    fn expect_or_abort(self, message: &str) -> T;
2747}
2748
2749impl<T> OptionExt<T> for Option<T> {
2750    fn expect_or_abort(self, message: &str) -> T {
2751        self.unwrap_or_else(|| abort!(Span::call_site(), message))
2752    }
2753}
2754
2755/// Parsing utils
2756mod parse_utils {
2757    use proc_macro2::{Group, Ident, TokenStream};
2758    use syn::{
2759        parenthesized,
2760        parse::{Parse, ParseStream},
2761        punctuated::Punctuated,
2762        token::Comma,
2763        Error, LitBool, LitStr, Token,
2764    };
2765
2766    use crate::ResultExt;
2767
2768    pub fn parse_next<T: Sized>(input: ParseStream, next: impl FnOnce() -> T) -> T {
2769        input
2770            .parse::<Token![=]>()
2771            .expect_or_abort("expected equals token before value assignment");
2772        next()
2773    }
2774
2775    pub fn parse_next_literal_str(input: ParseStream) -> syn::Result<String> {
2776        Ok(parse_next(input, || input.parse::<LitStr>())?.value())
2777    }
2778
2779    pub fn parse_groups<T, R>(input: ParseStream) -> syn::Result<R>
2780    where
2781        T: Sized,
2782        T: Parse,
2783        R: FromIterator<T>,
2784    {
2785        Punctuated::<Group, Comma>::parse_terminated(input).and_then(|groups| {
2786            groups
2787                .into_iter()
2788                .map(|group| syn::parse2::<T>(group.stream()))
2789                .collect::<syn::Result<R>>()
2790        })
2791    }
2792
2793    pub fn parse_punctuated_within_parenthesis<T>(
2794        input: ParseStream,
2795    ) -> syn::Result<Punctuated<T, Comma>>
2796    where
2797        T: Parse,
2798    {
2799        let content;
2800        parenthesized!(content in input);
2801        Punctuated::<T, Comma>::parse_terminated(&content)
2802    }
2803
2804    pub fn parse_bool_or_true(input: ParseStream) -> syn::Result<bool> {
2805        if input.peek(Token![=]) && input.peek2(LitBool) {
2806            input.parse::<Token![=]>()?;
2807
2808            Ok(input.parse::<LitBool>()?.value())
2809        } else {
2810            Ok(true)
2811        }
2812    }
2813
2814    /// Parse `json!(...)` as a [`TokenStream`].
2815    pub fn parse_json_token_stream(input: ParseStream) -> syn::Result<TokenStream> {
2816        if input.peek(syn::Ident) && input.peek2(Token![!]) {
2817            input.parse::<Ident>().and_then(|ident| {
2818                if ident != "json" {
2819                    return Err(Error::new(
2820                        ident.span(),
2821                        format!("unexpected token {ident}, expected: json!(...)"),
2822                    ));
2823                }
2824
2825                Ok(ident)
2826            })?;
2827            input.parse::<Token![!]>()?;
2828
2829            Ok(input.parse::<Group>()?.stream())
2830        } else {
2831            Err(Error::new(
2832                input.span(),
2833                "unexpected token, expected json!(...)",
2834            ))
2835        }
2836    }
2837}