Skip to main content

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#![cfg_attr(doc_cfg, feature(doc_cfg))]
8#![warn(missing_docs)]
9#![warn(rustdoc::broken_intra_doc_links)]
10
11#[cfg(all(feature = "decimal", feature = "decimal_float"))]
12compile_error!("`decimal` and `decimal_float` are mutually exclusive feature flags");
13
14#[cfg(all(feature = "bigdecimal", feature = "bigdecimal_float"))]
15compile_error!("`bigdecimal` and `bigdecimal_float` are mutually exclusive feature flags");
16
17#[cfg(all(
18    feature = "actix_extras",
19    feature = "axum_extras",
20    feature = "rocket_extras"
21))]
22compile_error!(
23    "`actix_extras`, `axum_extras` and `rocket_extras` are mutually exclusive feature flags"
24);
25
26use std::{mem, ops::Deref};
27
28use component::schema::Schema;
29use doc_comment::CommentAttributes;
30
31use component::into_params::IntoParams;
32use ext::{PathOperationResolver, PathOperations, PathResolver};
33use openapi::OpenApi;
34use proc_macro::TokenStream;
35use quote::{quote, ToTokens};
36
37use proc_macro2::{Ident, Punct, TokenStream as TokenStream2};
38use syn::{
39    bracketed,
40    parse::{Parse, ParseStream},
41    punctuated::Punctuated,
42    token::Bracket,
43    DeriveInput, ExprPath, GenericParam, ItemFn, Lit, LitStr, Member, Token,
44};
45
46mod component;
47mod doc_comment;
48mod ext;
49mod openapi;
50mod path;
51mod schema_type;
52mod security_requirement;
53mod server;
54pub(crate) mod token_stream;
55
56use crate::path::{Path, PathAttr};
57
58use self::{
59    component::{
60        features::{self, Feature},
61        ComponentSchema, ComponentSchemaProps, TypeTree,
62    },
63    openapi::parse_openapi_attrs,
64    path::response::derive::{IntoResponses, ToResponse},
65    token_stream::{Diagnostics, ToTokensDiagnostics},
66};
67
68#[cfg(feature = "config")]
69static CONFIG: once_cell::sync::Lazy<utoipa_config::Config> =
70    once_cell::sync::Lazy::new(utoipa_config::Config::read_from_file);
71
72#[proc_macro_derive(ToSchema, attributes(schema, serde))]
73/// Generate reusable OpenAPI schema to be used
74/// together with [`OpenApi`][openapi_derive].
75///
76/// This is `#[derive]` implementation for [`ToSchema`][to_schema] trait. The macro accepts one
77/// `schema`
78/// attribute optionally which can be used to enhance generated documentation. The attribute can be placed
79/// at item level or field and variant levels in structs and enum.
80///
81/// You can use the Rust's own `#[deprecated]` attribute on any struct, enum or field to mark it as deprecated and it will
82/// reflect to the generated OpenAPI spec.
83///
84/// `#[deprecated]` attribute supports adding additional details such as a reason and or since version but this is is not supported in
85/// OpenAPI. OpenAPI has only a boolean flag to determine deprecation. While it is totally okay to declare deprecated with reason
86/// `#[deprecated  = "There is better way to do this"]` the reason would not render in OpenAPI spec.
87///
88/// Doc comments on fields will resolve to field descriptions in generated OpenAPI doc. On struct
89/// level doc comments will resolve to object descriptions.
90///
91/// Schemas derived with `ToSchema` will be automatically collected from usage. In case of looping
92/// schema tree _`no_recursion`_ attribute must be used to break from recurring into infinite loop.
93/// See [more details from example][derive@ToSchema#examples]. All arguments of generic schemas
94/// must implement `ToSchema` trait.
95///
96/// ```rust
97/// /// This is a pet
98/// #[derive(utoipa::ToSchema)]
99/// struct Pet {
100///     /// Name for your pet
101///     name: String,
102/// }
103/// ```
104///
105/// # Named Field Struct Optional Configuration Options for `#[schema(...)]`
106///
107/// * `description = ...` Can be literal string or Rust expression e.g. _`const`_ reference or
108///   `include_str!(...)` statement. This can be used to override **default** description what is
109///   resolved from doc comments of the type.
110/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
111///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
112/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
113///   _`example`_ Can be any value e.g. literal, method reference or _`json!(...)`_.
114/// * `xml(...)` Can be used to define [`Xml`][xml] object properties applicable to Structs.
115/// * `title = ...` Literal string value. Can be used to define title for struct in OpenAPI
116///   document. Some OpenAPI code generation libraries also use this field as a name for the
117///   struct.
118/// * `rename_all = ...` Supports same syntax as _serde_ _`rename_all`_ attribute. Will rename all fields
119///   of the structs accordingly. If both _serde_ `rename_all` and _schema_ _`rename_all`_ are defined
120///   __serde__ will take precedence.
121/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
122///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
123///   OpenAPI spec as _`path.to.Pet`_. This same name will be used throughout the OpenAPI generated
124///   with `utoipa` when the type is being referenced in [`OpenApi`][openapi_derive] derive macro
125///   or in [`utoipa::path(...)`][path_macro] macro.
126/// * `bound = ...` Can be used to override default trait bounds on generated `impl`s.
127///   See [Generic schemas section](#generic-schemas) below for more details.
128/// * `default` Can be used to populate default values on all fields using the struct's
129///   [`Default`] implementation.
130/// * `deprecated` Can be used to mark all fields as deprecated in the generated OpenAPI spec but
131///   not in the code. If you'd like to mark the fields as deprecated in the code as well use
132///   Rust's own `#[deprecated]` attribute instead.
133/// * `max_properties = ...` Can be used to define maximum number of properties this struct can
134///   contain. Value must be a number.
135/// * `min_properties = ...` Can be used to define minimum number of properties this struct can
136///   contain. Value must be a number.
137///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
138///  `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
139///  recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**. On
140///  struct level the _`no_recursion`_ rule will be applied to all of its fields.
141///
142/// ## Named Fields Optional Configuration Options for `#[schema(...)]`
143///
144/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
145///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
146/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
147///   _`example`_ Can be any value e.g. literal, method reference or _`json!(...)`_.
148/// * `default = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
149/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
150///   an open value as a string. By default the format is derived from the type of the property
151///   according OpenApi spec.
152/// * `write_only` Defines property is only used in **write** operations *POST,PUT,PATCH* but not in *GET*
153/// * `read_only` Defines property is only used in **read** operations *GET* but not in *POST,PUT,PATCH*
154/// * `xml(...)` Can be used to define [`Xml`][xml] object properties applicable to named fields.
155///   See configuration options at xml attributes of [`ToSchema`][to_schema_xml]
156/// * `value_type = ...` Can be used to override default type derived from type of the field used in OpenAPI spec.
157///   This is useful in cases where the default type does not correspond to the actual type e.g. when
158///   any third-party types are used which are not [`ToSchema`][to_schema]s nor [`primitive` types][primitive].
159///   The value can be any Rust type what normally could be used to serialize to JSON, or either virtual type _`Object`_
160///   or _`Value`_.
161///   _`Object`_ will be rendered as generic OpenAPI object _(`type: object`)_.
162///   _`Value`_ will be rendered as any OpenAPI value (i.e. no `type` restriction).
163/// * `inline` If the type of this field implements [`ToSchema`][to_schema], then the schema definition
164///   will be inlined. **warning:** Don't use this for recursive data types!
165///
166///   **Note!**<br>Using `inline` with generic arguments might lead to incorrect spec generation.
167///   This is due to the fact that during compilation we cannot know how to treat the generic
168///   argument and there is difference whether it is a primitive type or another generic type.
169/// * `required = ...` Can be used to enforce required status for the field. [See
170///   rules][derive@ToSchema#field-nullability-and-required-rules]
171/// * `nullable` Defines property is nullable (note this is different to non-required).
172/// * `rename = ...` Supports same syntax as _serde_ _`rename`_ attribute. Will rename field
173///   accordingly. If both _serde_ `rename` and _schema_ _`rename`_ are defined __serde__ will take
174///   precedence.
175/// * `multiple_of = ...` Can be used to define multiplier for a value. Value is considered valid
176///   division will result an `integer`. Value must be strictly above _`0`_.
177/// * `maximum = ...` Can be used to define inclusive upper bound to a `number` value.
178/// * `minimum = ...` Can be used to define inclusive lower bound to a `number` value.
179/// * `exclusive_maximum = ...` Can be used to define exclusive upper bound to a `number` value.
180/// * `exclusive_minimum = ...` Can be used to define exclusive lower bound to a `number` value.
181/// * `max_length = ...` Can be used to define maximum length for `string` types.
182/// * `min_length = ...` Can be used to define minimum length for `string` types.
183/// * `pattern = ...` Can be used to define valid regular expression in _ECMA-262_ dialect the field value must match.
184/// * `max_items = ...` Can be used to define maximum items allowed for `array` fields. Value must
185///   be non-negative integer.
186/// * `min_items = ...` Can be used to define minimum items allowed for `array` fields. Value must
187///   be non-negative integer.
188/// * `schema_with = ...` Use _`schema`_ created by provided function reference instead of the
189///   default derived _`schema`_. The function must match to `fn() -> Into<RefOr<Schema>>`. It does
190///   not accept arguments and must return anything that can be converted into `RefOr<Schema>`.
191/// * `additional_properties = ...` Can be used to define free form types for maps such as
192///   [`HashMap`](std::collections::HashMap) and [`BTreeMap`](std::collections::BTreeMap).
193///   Free form type enables use of arbitrary types within map values.
194///   Supports formats _`additional_properties`_ and _`additional_properties = true`_.
195/// * `deprecated` Can be used to mark the field as deprecated in the generated OpenAPI spec but
196///   not in the code. If you'd like to mark the field as deprecated in the code as well use
197///   Rust's own `#[deprecated]` attribute instead.
198/// * `content_encoding = ...` Can be used to define content encoding used for underlying schema object.
199///   See [`Object::content_encoding`][schema_object_encoding]
200/// * `content_media_type = ...` Can be used to define MIME type of a string for underlying schema object.
201///   See [`Object::content_media_type`][schema_object_media_type]
202/// * `ignore` or `ignore = ...` Can be used to skip the field from being serialized to OpenAPI schema Only literal `bool` value is allowed.
203/// * `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
204///   `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
205///   recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**.
206/// * `extensions(...)` List of extensions to add to the field. See below for the format.
207///
208/// #### Field nullability and required rules
209///
210/// Field is considered _`required`_ if
211/// * it is not `Option` field
212/// * and it does not have _`skip_serializing_if`_ property
213/// * and it does not have _`serde_with`_ _[`double_option`](https://docs.rs/serde_with/latest/serde_with/rust/double_option/index.html)_
214/// * and it does not have default value provided with serde _`default`_
215///   attribute
216///
217/// Field is considered _`nullable`_ when field type is _`Option`_.
218///
219/// ## Xml attribute Configuration Options
220///
221/// * `xml(name = "...")` Will set name for property or type.
222/// * `xml(namespace = "...")` Will set namespace for xml element which needs to be valid uri.
223/// * `xml(prefix = "...")` Will set prefix for name.
224/// * `xml(attribute)` Will translate property to xml attribute instead of xml element.
225/// * `xml(wrapped)` Will make wrapped xml element.
226/// * `xml(wrapped(name = "wrap_name"))` Will override the wrapper elements name.
227///
228/// See [`Xml`][xml] for more details.
229///
230/// # Unnamed Field Struct Optional Configuration Options for `#[schema(...)]`
231///
232/// * `description = ...` Can be literal string or Rust expression e.g. [_`const`_][const] reference or
233///   `include_str!(...)` statement. This can be used to override **default** description what is
234///   resolved from doc comments of the type.
235/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
236///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
237/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
238///   _`example`_ Can be any value e.g. literal, method reference or _`json!(...)`_.
239/// * `default = ...` Can be any value e.g. literal, method reference or _`json!(...)`_. If no value
240///   is specified, and the struct has only one field, the field's default value in the schema will be
241///   set from the struct's [`Default`] implementation.
242/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
243///   an open value as a string. By default the format is derived from the type of the property
244///   according OpenApi spec.
245/// * `value_type = ...` Can be used to override default type derived from type of the field used in OpenAPI spec.
246///   This is useful in cases where the default type does not correspond to the actual type e.g. when
247///   any third-party types are used which are not [`ToSchema`][to_schema]s nor [`primitive` types][primitive].
248///   The value can be any Rust type what normally could be used to serialize to JSON or either virtual type _`Object`_
249///   or _`Value`_.
250///   _`Object`_ will be rendered as generic OpenAPI object _(`type: object`)_.
251///   _`Value`_ will be rendered as any OpenAPI value (i.e. no `type` restriction).
252/// * `title = ...` Literal string value. Can be used to define title for struct in OpenAPI
253///   document. Some OpenAPI code generation libraries also use this field as a name for the
254///   struct.
255/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
256///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
257///   OpenAPI spec as _`path.to.Pet`_. This same name will be used throughout the OpenAPI generated
258///   with `utoipa` when the type is being referenced in [`OpenApi`][openapi_derive] derive macro
259///   or in [`utoipa::path(...)`][path_macro] macro.
260/// * `bound = ...` Can be used to override default trait bounds on generated `impl`s.
261///   See [Generic schemas section](#generic-schemas) below for more details.
262/// * `deprecated` Can be used to mark the field as deprecated in the generated OpenAPI spec but
263///   not in the code. If you'd like to mark the field as deprecated in the code as well use
264///   Rust's own `#[deprecated]` attribute instead.
265/// * `content_encoding = ...` Can be used to define content encoding used for underlying schema object.
266///   See [`Object::content_encoding`][schema_object_encoding]
267/// * `content_media_type = ...` Can be used to define MIME type of a string for underlying schema object.
268///   See [`Object::content_media_type`][schema_object_media_type]
269///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
270///  `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
271///  recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**.
272///
273/// # Enum Optional Configuration Options for `#[schema(...)]`
274///
275/// ## Plain Enum having only `Unit` variants Optional Configuration Options for `#[schema(...)]`
276///
277/// * `description = ...` Can be literal string or Rust expression e.g. [_`const`_][const] reference or
278///   `include_str!(...)` statement. This can be used to override **default** description what is
279///   resolved from doc comments of the type.
280/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
281///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
282/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
283///   _`example`_ Can be any value e.g. literal, method reference or _`json!(...)`_.
284/// * `default = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
285/// * `title = ...` Literal string value. Can be used to define title for enum in OpenAPI
286///   document. Some OpenAPI code generation libraries also use this field as a name for the
287///   enum.
288/// * `rename_all = ...` Supports same syntax as _serde_ _`rename_all`_ attribute. Will rename all
289///   variants of the enum accordingly. If both _serde_ `rename_all` and _schema_ _`rename_all`_
290///   are defined __serde__ will take precedence.
291/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
292///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
293///   OpenAPI spec as _`path.to.Pet`_. This same name will be used throughout the OpenAPI generated
294///   with `utoipa` when the type is being referenced in [`OpenApi`][openapi_derive] derive macro
295///   or in [`utoipa::path(...)`][path_macro] macro.
296/// * `bound = ...` Can be used to override default trait bounds on generated `impl`s.
297///   See [Generic schemas section](#generic-schemas) below for more details.
298/// * `deprecated` Can be used to mark the enum as deprecated in the generated OpenAPI spec but
299///   not in the code. If you'd like to mark the enum as deprecated in the code as well use
300///   Rust's own `#[deprecated]` attribute instead.
301///
302/// ### Plain Enum Variant Optional Configuration Options for `#[schema(...)]`
303///
304/// * `rename = ...` Supports same syntax as _serde_ _`rename`_ attribute. Will rename variant
305///   accordingly. If both _serde_ `rename` and _schema_ _`rename`_ are defined __serde__ will take
306///   precedence. **Note!** [`Repr enum`][macro@ToSchema#repr-attribute-support] variant does not
307///   support _`rename`_.
308///
309/// ## Mixed Enum Optional Configuration Options for `#[schema(...)]`
310///
311/// * `description = ...` Can be literal string or Rust expression e.g. [_`const`_][const] reference or
312///   `include_str!(...)` statement. This can be used to override **default** description what is
313///   resolved from doc comments of the type.
314/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
315///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
316/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
317/// * `default = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
318/// * `title = ...` Literal string value. Can be used to define title for enum in OpenAPI
319///   document. Some OpenAPI code generation libraries also use this field as a name for the
320///   enum.
321/// * `rename_all = ...` Supports same syntax as _serde_ _`rename_all`_ attribute. Will rename all
322///   variants of the enum accordingly. If both _serde_ `rename_all` and _schema_ _`rename_all`_
323///   are defined __serde__ will take precedence.
324/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
325///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
326///   OpenAPI spec as _`path.to.Pet`_. This same name will be used throughout the OpenAPI generated
327///   with `utoipa` when the type is being referenced in [`OpenApi`][openapi_derive] derive macro
328///   or in [`utoipa::path(...)`][path_macro] macro.
329/// * `bound = ...` Can be used to override default trait bounds on generated `impl`s.
330///   See [Generic schemas section](#generic-schemas) below for more details.
331/// * `deprecated` Can be used to mark the enum as deprecated in the generated OpenAPI spec but
332///   not in the code. If you'd like to mark the enum as deprecated in the code as well use
333///   Rust's own `#[deprecated]` attribute instead.
334/// * `discriminator = ...` or `discriminator(...)` Can be used to define OpenAPI discriminator
335///   field for enums with single unnamed _`ToSchema`_ reference field. See the [discriminator
336///   syntax][derive@ToSchema#schemadiscriminator-syntax].
337///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
338///  `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
339///  recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**. On
340///  enum level the _`no_recursion`_ rule will be applied to all of its variants.
341///
342///  ### `#[schema(discriminator)]` syntax
343///
344///  Discriminator can **only** be used with enums having **`#[serde(untagged)]`** attribute and
345///  each variant must have only one unnamed field schema reference to type implementing
346///  _`ToSchema`_.
347///
348///  **Simple form `discriminator = ...`**
349///
350///  Can be literal string or expression e.g. [_`const`_][const] reference. It can be defined as
351///  _`discriminator = "value"`_ where the assigned value is the
352///  discriminator field that must exists in each variant referencing schema.
353///
354/// **Complex form `discriminator(...)`**
355///
356/// * `property_name = ...` Can be literal string or expression e.g. [_`const`_][const] reference.
357/// * mapping `key` Can be literal string or expression e.g. [_`const`_][const] reference.
358/// * mapping `value` Can be literal string or expression e.g. [_`const`_][const] reference.
359///
360/// Additionally discriminator can be defined with custom mappings as show below. The _`mapping`_
361/// values defines _**key = value**_ pairs where _**key**_ is the expected value for _**property_name**_ field
362/// and _**value**_ is schema to map.
363/// ```text
364/// discriminator(property_name = "my_field", mapping(
365///      ("value" = "#/components/schemas/Schema1"),
366///      ("value2" = "#/components/schemas/Schema2")
367/// ))
368/// ```
369///
370/// ### Mixed Enum Named Field Variant Optional Configuration Options for `#[serde(schema)]`
371///
372/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
373///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
374/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
375/// * `default = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
376/// * `title = ...` Literal string value. Can be used to define title for enum variant in OpenAPI
377///   document. Some OpenAPI code generation libraries also use this field as a name for the
378///   enum.
379/// * `xml(...)` Can be used to define [`Xml`][xml] object properties applicable to Structs.
380/// * `rename = ...` Supports same syntax as _serde_ _`rename`_ attribute. Will rename variant
381///   accordingly. If both _serde_ `rename` and _schema_ _`rename`_ are defined __serde__ will take
382///   precedence.
383/// * `rename_all = ...` Supports same syntax as _serde_ _`rename_all`_ attribute. Will rename all
384///   variant fields accordingly. If both _serde_ `rename_all` and _schema_ _`rename_all`_
385///   are defined __serde__ will take precedence.
386/// * `deprecated` Can be used to mark the enum as deprecated in the generated OpenAPI spec but
387///   not in the code. If you'd like to mark the enum as deprecated in the code as well use
388///   Rust's own `#[deprecated]` attribute instead.
389/// * `max_properties = ...` Can be used to define maximum number of properties this struct can
390///   contain. Value must be a number.
391/// * `min_properties = ...` Can be used to define minimum number of properties this struct can
392///   contain. Value must be a number.
393///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
394///  `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
395///  recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**. On
396///  named field variant level the _`no_recursion`_ rule will be applied to all of its fields.
397///
398/// ## Mixed Enum Unnamed Field Variant Optional Configuration Options for `#[serde(schema)]`
399///
400/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
401///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
402/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
403///   _`example`_ Can be any value e.g. literal, method reference or _`json!(...)`_.
404/// * `default = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
405/// * `title = ...` Literal string value. Can be used to define title for enum variant in OpenAPI
406///   document. Some OpenAPI code generation libraries also use this field as a name for the
407///   struct.
408/// * `rename = ...` Supports same syntax as _serde_ _`rename`_ attribute. Will rename variant
409///   accordingly. If both _serde_ `rename` and _schema_ _`rename`_ are defined __serde__ will take
410///   precedence.
411/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
412///   an open value as a string. By default the format is derived from the type of the property
413///   according OpenApi spec.
414/// * `value_type = ...` Can be used to override default type derived from type of the field used in OpenAPI spec.
415///   This is useful in cases where the default type does not correspond to the actual type e.g. when
416///   any third-party types are used which are not [`ToSchema`][to_schema]s nor [`primitive` types][primitive].
417///   The value can be any Rust type what normally could be used to serialize to JSON or either virtual type _`Object`_
418///   or _`Value`_.
419///   _`Object`_ will be rendered as generic OpenAPI object _(`type: object`)_.
420///   _`Value`_ will be rendered as any OpenAPI value (i.e. no `type` restriction).
421/// * `deprecated` Can be used to mark the field as deprecated in the generated OpenAPI spec but
422///   not in the code. If you'd like to mark the field as deprecated in the code as well use
423///   Rust's own `#[deprecated]` attribute instead.
424///* `no_recursion` Is used to break from recursion in case of looping schema tree e.g. `Pet` ->
425///  `Owner` -> `Pet`. _`no_recursion`_ attribute must be used within `Owner` type not to allow
426///  recurring into `Pet`. Failing to do so will cause infinite loop and runtime **panic**.
427///
428/// #### Mixed Enum Unnamed Field Variant's Field Configuration Options
429///
430/// * `inline` If the type of this field implements [`ToSchema`][to_schema], then the schema definition
431///   will be inlined. **warning:** Don't use this for recursive data types!
432///
433///   **Note!**<br>Using `inline` with generic arguments might lead to incorrect spec generation.
434///   This is due to the fact that during compilation we cannot know how to treat the generic
435///   argument and there is difference whether it is a primitive type or another generic type.
436///
437///   _**Inline unnamed field variant schemas.**_
438///   ```rust
439///   # use utoipa::ToSchema;
440///   # #[derive(ToSchema)]
441///   # enum Number {
442///   #     One,
443///   # }
444///   #
445///   # #[derive(ToSchema)]
446///   # enum Color {
447///   #     Spade,
448///   # }
449///    #[derive(ToSchema)]
450///    enum Card {
451///        Number(#[schema(inline)] Number),
452///        Color(#[schema(inline)] Color),
453///    }
454///   ```
455///
456/// ## Mixed Enum Unit Field Variant Optional Configuration Options for `#[serde(schema)]`
457///
458/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
459///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
460/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
461///   _`example`_ Can be any value e.g. literal, method reference or _`json!(...)`_.
462/// * `title = ...` Literal string value. Can be used to define title for enum variant in OpenAPI
463///   document. Some OpenAPI code generation libraries also use this field as a name for the
464///   struct.
465/// * `rename = ...` Supports same syntax as _serde_ _`rename`_ attribute. Will rename variant
466///   accordingly. If both _serde_ `rename` and _schema_ _`rename`_ are defined __serde__ will take
467///   precedence.
468/// * `deprecated` Can be used to mark the field as deprecated in the generated OpenAPI spec but
469///   not in the code. If you'd like to mark the field as deprecated in the code as well use
470///   Rust's own `#[deprecated]` attribute instead.
471///
472/// # Extensions Requirements Attributes
473///
474/// * `x-property` defines the name of the extension.
475/// * `json!(...)` defines the value associated with the named extension as a `serde_json::Value`.
476///
477/// **Extensions Requitement supported formats:**
478///
479/// ```text
480/// ("x-property" = json!({ "type": "mock" }) ),
481/// ("x-an-extension" = json!({ "type": "mock" }) ),
482/// ("x-another-extension" = json!( "body" ) ),
483/// ```
484///
485/// # Partial `#[serde(...)]` attributes support
486///
487/// ToSchema derive has partial support for [serde attributes]. These supported attributes will reflect to the
488/// 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
489/// be serialized anyway. Similarly the _`rename`_ and _`rename_all`_ will reflect to the generated OpenAPI doc.
490///
491/// * `rename_all = "..."` Supported at the container level.
492/// * `rename = "..."` Supported **only** at the field or variant level.
493/// * `skip = "..."` Supported  **only** at the field or variant level.
494/// * `skip_serializing = "..."` Supported  **only** at the field or variant level.
495/// * `skip_deserializing = "..."` Supported  **only** at the field or variant level.
496/// * `skip_serializing_if = "..."` Supported  **only** at the field level.
497/// * `with = ...` Supported **only at field level.**
498/// * `tag = "..."` Supported at the container level.
499/// * `content = "..."` Supported at the container level, allows [adjacently-tagged enums](https://serde.rs/enum-representations.html#adjacently-tagged).
500///   This attribute requires that a `tag` is present, otherwise serde will trigger a compile-time
501///   failure.
502/// * `untagged` Supported at the container level. Allows [untagged
503///   enum representation](https://serde.rs/enum-representations.html#untagged).
504/// * `default` Supported at the container level and field level according to [serde attributes].
505/// * `deny_unknown_fields` Supported at the container level.
506/// * `flatten` Supported at the field level.
507///
508/// Other _`serde`_ attributes works as is but does not have any effect on the generated OpenAPI doc.
509///
510/// **Note!** `tag` attribute has some limitations like it cannot be used with **tuple types**. See more at
511/// [enum representation docs](https://serde.rs/enum-representations.html).
512///
513/// **Note!** `with` attribute is used in tandem with [serde_with](https://github.com/jonasbb/serde_with) to recognize
514/// _[`double_option`](https://docs.rs/serde_with/latest/serde_with/rust/double_option/index.html)_ from **field value**.
515/// _`double_option`_ is **only** supported attribute from _`serde_with`_ crate.
516///
517/// ```rust
518/// # use serde::Serialize;
519/// # use utoipa::ToSchema;
520/// #[derive(Serialize, ToSchema)]
521/// struct Foo(String);
522///
523/// #[derive(Serialize, ToSchema)]
524/// #[serde(rename_all = "camelCase")]
525/// enum Bar {
526///     UnitValue,
527///     #[serde(rename_all = "camelCase")]
528///     NamedFields {
529///         #[serde(rename = "id")]
530///         named_id: &'static str,
531///         name_list: Option<Vec<String>>
532///     },
533///     UnnamedFields(Foo),
534///     #[serde(skip)]
535///     SkipMe,
536/// }
537/// ```
538///
539/// _**Add custom `tag` to change JSON representation to be internally tagged.**_
540/// ```rust
541/// # use serde::Serialize;
542/// # use utoipa::ToSchema;
543/// #[derive(Serialize, ToSchema)]
544/// struct Foo(String);
545///
546/// #[derive(Serialize, ToSchema)]
547/// #[serde(tag = "tag")]
548/// enum Bar {
549///     UnitValue,
550///     NamedFields {
551///         id: &'static str,
552///         names: Option<Vec<String>>
553///     },
554/// }
555/// ```
556///
557/// _**Add serde `default` attribute for MyValue struct. Similarly `default` could be added to
558/// individual fields as well. If `default` is given the field's affected will be treated
559/// as optional.**_
560/// ```rust
561///  #[derive(utoipa::ToSchema, serde::Deserialize, Default)]
562///  #[serde(default)]
563///  struct MyValue {
564///      field: String
565///  }
566/// ```
567///
568/// # `#[repr(...)]` attribute support
569///
570/// [Serde repr](https://github.com/dtolnay/serde-repr) allows field-less enums be represented by
571/// their numeric value.
572///
573/// * `repr(u*)` for unsigned integer.
574/// * `repr(i*)` for signed integer.
575///
576/// **Supported schema attributes**
577///
578/// * `example = ...` Can be any value e.g. literal, method reference or _`json!(...)`_.
579///   **Deprecated since OpenAPI 3.0, using `examples` is preferred instead.**
580/// * `examples(..., ...)` Comma separated list defining multiple _`examples`_ for the schema. Each
581///   _`example`_ Can be any value e.g. literal, method reference or _`json!(...)`_.
582/// * `title = ...` Literal string value. Can be used to define title for enum in OpenAPI
583///   document. Some OpenAPI code generation libraries also use this field as a name for the
584///   struct.
585/// * `as = ...` Can be used to define alternative path and name for the schema what will be used in
586///   the OpenAPI. E.g _`as = path::to::Pet`_. This would make the schema appear in the generated
587///   OpenAPI spec as _`path.to.Pet`_. This same name will be used throughout the OpenAPI generated
588///   with `utoipa` when the type is being referenced in [`OpenApi`][openapi_derive] derive macro
589///   or in [`utoipa::path(...)`][path_macro] macro.
590///
591/// _**Create enum with numeric values.**_
592/// ```rust
593/// # use utoipa::ToSchema;
594/// #[derive(ToSchema)]
595/// #[repr(u8)]
596/// #[schema(default = default_value, example = 2)]
597/// enum Mode {
598///     One = 1,
599///     Two,
600///  }
601///
602/// fn default_value() -> u8 {
603///     1
604/// }
605/// ```
606///
607/// _**You can use `skip` and `tag` attributes from serde.**_
608/// ```rust
609/// # use utoipa::ToSchema;
610/// #[derive(ToSchema, serde::Serialize)]
611/// #[repr(i8)]
612/// #[serde(tag = "code")]
613/// enum ExitCode {
614///     Error = -1,
615///     #[serde(skip)]
616///     Unknown = 0,
617///     Ok = 1,
618///  }
619/// ```
620///
621/// # Generic schemas
622///
623/// Utoipa supports full set of deeply nested generics as shown below. The type will implement
624/// [`ToSchema`][to_schema] if and only if all the generic types implement `ToSchema` by default.
625/// That is in Rust `impl<T> ToSchema for MyType<T> where T: Schema { ... }`.
626/// You can also specify `bound = ...` on the item to override the default auto bounds.
627///
628/// The _`as = ...`_ attribute is used to define the prefixed or alternative name for the component
629/// in question. This same name will be used throughout the OpenAPI generated with `utoipa` when
630/// the type is being referenced in [`OpenApi`][openapi_derive] derive macro or in [`utoipa::path(...)`][path_macro] macro.
631///
632/// ```rust
633/// # use utoipa::ToSchema;
634/// # use std::borrow::Cow;
635///  #[derive(ToSchema)]
636///  #[schema(as = path::MyType<T>)]
637///  struct Type<T> {
638///      t: T,
639///  }
640///
641///  #[derive(ToSchema)]
642///  struct Person<'p, T: Sized, P> {
643///      id: usize,
644///      name: Option<Cow<'p, str>>,
645///      field: T,
646///      t: P,
647///  }
648///
649///  #[derive(ToSchema)]
650///  #[schema(as = path::to::PageList)]
651///  struct Page<T> {
652///      total: usize,
653///      page: usize,
654///      pages: usize,
655///      items: Vec<T>,
656///  }
657///
658///  #[derive(ToSchema)]
659///  #[schema(as = path::to::Element<T>)]
660///  enum E<T> {
661///      One(T),
662///      Many(Vec<T>),
663///  }
664/// ```
665/// When generic types are registered to the `OpenApi` the full type declaration must be provided.
666/// See the full example in test [schema_generics.rs](https://github.com/juhaku/utoipa/blob/master/utoipa-gen/tests/schema_generics.rs)
667///
668/// # Examples
669///
670/// _**Simple example of a Pet with descriptions and object level example.**_
671/// ```rust
672/// # use utoipa::ToSchema;
673/// /// This is a pet.
674/// #[derive(ToSchema)]
675/// #[schema(example = json!({"name": "bob the cat", "id": 0}))]
676/// struct Pet {
677///     /// Unique id of a pet.
678///     id: u64,
679///     /// Name of a pet.
680///     name: String,
681///     /// Age of a pet if known.
682///     age: Option<i32>,
683/// }
684/// ```
685///
686/// _**The `schema` attribute can also be placed at field level as follows.**_
687/// ```rust
688/// # use utoipa::ToSchema;
689/// #[derive(ToSchema)]
690/// struct Pet {
691///     #[schema(example = 1, default = 0)]
692///     id: u64,
693///     name: String,
694///     age: Option<i32>,
695/// }
696/// ```
697///
698/// _**You can also use method reference for attribute values.**_
699/// ```rust
700/// # use utoipa::ToSchema;
701/// #[derive(ToSchema)]
702/// struct Pet {
703///     #[schema(example = u64::default, default = u64::default)]
704///     id: u64,
705///     #[schema(default = default_name)]
706///     name: String,
707///     age: Option<i32>,
708/// }
709///
710/// fn default_name() -> String {
711///     "bob".to_string()
712/// }
713/// ```
714///
715/// _**For enums and unnamed field structs you can define `schema` at type level.**_
716/// ```rust
717/// # use utoipa::ToSchema;
718/// #[derive(ToSchema)]
719/// #[schema(example = "Bus")]
720/// enum VehicleType {
721///     Rocket, Car, Bus, Submarine
722/// }
723/// ```
724///
725/// _**Also you write mixed enum combining all above types.**_
726/// ```rust
727/// # use utoipa::ToSchema;
728/// #[derive(ToSchema)]
729/// enum ErrorResponse {
730///     InvalidCredentials,
731///     #[schema(default = String::default, example = "Pet not found")]
732///     NotFound(String),
733///     System {
734///         #[schema(example = "Unknown system failure")]
735///         details: String,
736///     }
737/// }
738/// ```
739///
740/// _**It is possible to specify the title of each variant to help generators create named structures.**_
741/// ```rust
742/// # use utoipa::ToSchema;
743/// #[derive(ToSchema)]
744/// enum ErrorResponse {
745///     #[schema(title = "InvalidCredentials")]
746///     InvalidCredentials,
747///     #[schema(title = "NotFound")]
748///     NotFound(String),
749/// }
750/// ```
751///
752/// _**Use `xml` attribute to manipulate xml output.**_
753/// ```rust
754/// # use utoipa::ToSchema;
755/// #[derive(ToSchema)]
756/// #[schema(xml(name = "user", prefix = "u", namespace = "https://user.xml.schema.test"))]
757/// struct User {
758///     #[schema(xml(attribute, prefix = "u"))]
759///     id: i64,
760///     #[schema(xml(name = "user_name", prefix = "u"))]
761///     username: String,
762///     #[schema(xml(wrapped(name = "linkList"), name = "link"))]
763///     links: Vec<String>,
764///     #[schema(xml(wrapped, name = "photo_url"))]
765///     photos_urls: Vec<String>
766/// }
767/// ```
768///
769/// _**Use of Rust's own `#[deprecated]` attribute will reflect to generated OpenAPI spec.**_
770/// ```rust
771/// # use utoipa::ToSchema;
772/// #[derive(ToSchema)]
773/// #[deprecated]
774/// struct User {
775///     id: i64,
776///     username: String,
777///     links: Vec<String>,
778///     #[deprecated]
779///     photos_urls: Vec<String>
780/// }
781/// ```
782///
783/// _**Enforce type being used in OpenAPI spec to [`String`] with `value_type` and set format to octet stream
784/// with [`SchemaFormat::KnownFormat(KnownFormat::Binary)`][binary].**_
785/// ```rust
786/// # use utoipa::ToSchema;
787/// #[derive(ToSchema)]
788/// struct Post {
789///     id: i32,
790///     #[schema(value_type = String, format = Binary)]
791///     value: Vec<u8>,
792/// }
793/// ```
794///
795/// _**Enforce type being used in OpenAPI spec to [`String`] with `value_type` option.**_
796/// ```rust
797/// # use utoipa::ToSchema;
798/// #[derive(ToSchema)]
799/// #[schema(value_type = String)]
800/// struct Value(i64);
801/// ```
802///
803/// _**Override the `Bar` reference with a `custom::NewBar` reference.**_
804/// ```rust
805/// # use utoipa::ToSchema;
806/// #  mod custom {
807/// #      #[derive(utoipa::ToSchema)]
808/// #      pub struct NewBar;
809/// #  }
810/// #
811/// # struct Bar;
812/// #[derive(ToSchema)]
813/// struct Value {
814///     #[schema(value_type = custom::NewBar)]
815///     field: Bar,
816/// };
817/// ```
818///
819/// _**Use a virtual `Object` type to render generic `object` _(`type: object`)_ in OpenAPI spec.**_
820/// ```rust
821/// # use utoipa::ToSchema;
822/// # mod custom {
823/// #    struct NewBar;
824/// # }
825/// #
826/// # struct Bar;
827/// #[derive(ToSchema)]
828/// struct Value {
829///     #[schema(value_type = Object)]
830///     field: Bar,
831/// };
832/// ```
833/// More examples for _`value_type`_ in [`IntoParams` derive docs][into_params].
834///
835/// _**Serde `rename` / `rename_all` will take precedence over schema `rename` / `rename_all`.**_
836/// ```rust
837/// #[derive(utoipa::ToSchema, serde::Deserialize)]
838/// #[serde(rename_all = "lowercase")]
839/// #[schema(rename_all = "UPPERCASE")]
840/// enum Random {
841///     #[serde(rename = "string_value")]
842///     #[schema(rename = "custom_value")]
843///     String(String),
844///
845///     Number {
846///         id: i32,
847///     }
848/// }
849/// ```
850///
851/// _**Add `title` to the enum.**_
852/// ```rust
853/// #[derive(utoipa::ToSchema)]
854/// #[schema(title = "UserType")]
855/// enum UserType {
856///     Admin,
857///     Moderator,
858///     User,
859/// }
860/// ```
861///
862/// _**Example with validation attributes.**_
863/// ```rust
864/// #[derive(utoipa::ToSchema)]
865/// struct Item {
866///     #[schema(maximum = 10, minimum = 5, multiple_of = 2.5)]
867///     id: i32,
868///     #[schema(max_length = 10, min_length = 5, pattern = "[a-z]*")]
869///     value: String,
870///     #[schema(max_items = 5, min_items = 1)]
871///     items: Vec<String>,
872/// }
873/// ````
874///
875/// _**Use `schema_with` to manually implement schema for a field.**_
876/// ```rust
877/// # use utoipa::openapi::schema::{Object, ObjectBuilder};
878/// fn custom_type() -> Object {
879///     ObjectBuilder::new()
880///         .schema_type(utoipa::openapi::schema::Type::String)
881///         .format(Some(utoipa::openapi::SchemaFormat::Custom(
882///             "email".to_string(),
883///         )))
884///         .description(Some("this is the description"))
885///         .build()
886/// }
887///
888/// #[derive(utoipa::ToSchema)]
889/// struct Value {
890///     #[schema(schema_with = custom_type)]
891///     id: String,
892/// }
893/// ```
894///
895/// _**Use `as` attribute to change the name and the path of the schema in the generated OpenAPI
896/// spec.**_
897/// ```rust
898///  #[derive(utoipa::ToSchema)]
899///  #[schema(as = api::models::person::Person)]
900///  struct Person {
901///      name: String,
902///  }
903/// ```
904///
905/// _**Use `bound` attribute to override the default impl bounds.**_
906///
907/// `bound = ...` accepts a string containing zero or more where-predicates separated by comma, as
908/// the similar syntax to [`serde(bound = ...)`](https://serde.rs/container-attrs.html#bound).
909/// If `bound = ...` exists, the default auto bounds (requiring all generic types to implement
910/// `ToSchema`) will not be applied anymore, and only the specified predicates are added to the
911/// `where` clause of generated `impl` blocks.
912///
913/// ```rust
914/// // Override the default bounds to only require `T: ToSchema`, ignoring unused `U`.
915/// #[derive(utoipa::ToSchema, serde::Serialize)]
916/// #[schema(bound = "T: utoipa::ToSchema")]
917/// struct Partial<T, U> {
918///     used_in_api: T,
919///     #[serde(skip)]
920///     not_in_api: std::marker::PhantomData<U>,
921/// }
922///
923/// // Just remove the auto-bounds. So we got `Unused<T>: ToSchema` for any `T`.
924/// #[derive(utoipa::ToSchema, serde::Serialize)]
925/// #[schema(bound = "")]
926/// struct Unused<T> {
927///     #[serde(skip)]
928///     _marker: std::marker::PhantomData<T>,
929/// }
930/// ```
931///
932/// _**Use `no_recursion` attribute to break from looping schema tree e.g. `Pet` -> `Owner` ->
933/// `Pet`.**_
934///
935/// `no_recursion` attribute can be provided on named field of a struct, on unnamed struct or unnamed
936/// enum variant. It must be provided in case of looping schema tree in order to stop recursion.
937/// Failing to do so will cause runtime **panic**.
938/// ```rust
939/// # use utoipa::ToSchema;
940/// #
941/// #[derive(ToSchema)]
942/// pub struct Pet {
943///     name: String,
944///     owner: Owner,
945/// }
946///
947/// #[derive(ToSchema)]
948/// pub struct Owner {
949///     name: String,
950///     #[schema(no_recursion)]
951///     pets: Vec<Pet>,
952/// }
953/// ```
954///
955/// [to_schema]: trait.ToSchema.html
956/// [known_format]: openapi/schema/enum.KnownFormat.html
957/// [binary]: openapi/schema/enum.KnownFormat.html#variant.Binary
958/// [xml]: openapi/xml/struct.Xml.html
959/// [into_params]: derive.IntoParams.html
960/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
961/// [serde attributes]: https://serde.rs/attributes.html
962/// [discriminator]: openapi/schema/struct.Discriminator.html
963/// [enum_schema]: derive.ToSchema.html#enum-optional-configuration-options-for-schema
964/// [openapi_derive]: derive.OpenApi.html
965/// [to_schema_xml]: macro@ToSchema#xml-attribute-configuration-options
966/// [schema_object_encoding]: openapi/schema/struct.Object.html#structfield.content_encoding
967/// [schema_object_media_type]: openapi/schema/struct.Object.html#structfield.content_media_type
968/// [path_macro]: macro@path
969/// [const]: https://doc.rust-lang.org/std/keyword.const.html
970pub fn derive_to_schema(input: TokenStream) -> TokenStream {
971    let DeriveInput {
972        attrs,
973        ident,
974        data,
975        generics,
976        ..
977    } = syn::parse_macro_input!(input);
978
979    Schema::new(&data, &attrs, &ident, &generics)
980        .as_ref()
981        .map_or_else(Diagnostics::to_token_stream, Schema::to_token_stream)
982        .into()
983}
984
985#[proc_macro_attribute]
986/// Path attribute macro implements OpenAPI path for the decorated function.
987///
988/// This is a `#[derive]` implementation for [`Path`][path] trait. Macro accepts set of attributes that can
989/// be used to configure and override default values what are resolved automatically.
990///
991/// You can use the Rust's own `#[deprecated]` attribute on functions to mark it as deprecated and it will
992/// reflect to the generated OpenAPI spec. Only **parameters** has a special **deprecated** attribute to define them as deprecated.
993///
994/// `#[deprecated]` attribute supports adding additional details such as a reason and or since version but this is is not supported in
995/// OpenAPI. OpenAPI has only a boolean flag to determine deprecation. While it is totally okay to declare deprecated with reason
996/// `#[deprecated  = "There is better way to do this"]` the reason would not render in OpenAPI spec.
997///
998/// Doc comment at decorated function will be used for _`description`_ and _`summary`_ of the path.
999/// First line of the doc comment will be used as the _`summary`_ while the remaining lines will be
1000/// used as _`description`_.
1001/// ```rust
1002/// /// This is a summary of the operation
1003/// ///
1004/// /// The rest of the doc comment will be included to operation description.
1005/// #[utoipa::path(get, path = "/operation")]
1006/// fn operation() {}
1007/// ```
1008///
1009/// # Path Attributes
1010///
1011/// * `operation` _**Must be first parameter!**_ Accepted values are known HTTP operations such as
1012///   _`get, post, put, delete, head, options, patch, trace`_.
1013///
1014/// * `method(get, head, ...)` Http methods for the operation. This allows defining multiple
1015///   HTTP methods at once for single operation. Either _`operation`_ or _`method(...)`_ _**must be
1016///   provided.**_
1017///
1018/// * `path = "..."` Must be OpenAPI format compatible str with arguments within curly braces. E.g _`{id}`_
1019///
1020/// * `impl_for = ...` Optional type to implement the [`Path`][path] trait. By default a new type
1021///   is used for the implementation.
1022///
1023/// * `operation_id = ...` Unique operation id for the endpoint. By default this is mapped to function name.
1024///   The operation_id can be any valid expression (e.g. string literals, macro invocations, variables) so long
1025///   as its result can be converted to a `String` using `String::from`.
1026///
1027/// * `context_path = "..."` Can add optional scope for **path**. The **context_path** will be prepended to beginning of **path**.
1028///   This is particularly useful when **path** does not contain the full path to the endpoint. For example if web framework
1029///   allows operation to be defined under some context path or scope which does not reflect to the resolved path then this
1030///   **context_path** can become handy to alter the path.
1031///
1032/// * `tag = "..."` Can be used to group operations. Operations with same tag are grouped together. By default
1033///   this is derived from the module path of the handler that is given to [`OpenApi`][openapi].
1034///
1035/// * `tags = ["tag1", ...]` Can be used to group operations. Operations with same tag are grouped
1036///   together. Tags attribute can be used to add additional _tags_ for the operation. If both
1037///   _`tag`_ and _`tags`_ are provided then they will be combined to a single _`tags`_ array.
1038///
1039/// * `request_body = ... | request_body(...)` Defining request body indicates that the request is expecting request body within
1040///   the performed request.
1041///
1042/// * `responses(...)` Slice of responses the endpoint is going to possibly return to the caller.
1043///
1044/// * `params(...)` Slice of params that the endpoint accepts.
1045///
1046/// * `security(...)` List of [`SecurityRequirement`][security]s local to the path operation.
1047///
1048/// * `summary = ...` Allows overriding summary of the path. Value can be literal string or valid
1049///   rust expression e.g. `include_str!(...)` or `const` reference.
1050///
1051/// * `description = ...` Allows overriding description of the path. Value can be literal string or valid
1052///   rust expression e.g. `include_str!(...)` or `const` reference.
1053///
1054/// * `extensions(...)` List of extensions local to the path operation.
1055///
1056/// # Request Body Attributes
1057///
1058/// ## Simple format definition by `request_body = ...`
1059/// * _`request_body = Type`_, _`request_body = inline(Type)`_ or _`request_body = ref("...")`_.
1060///   The given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec or Map etc.
1061///   With _`inline(...)`_ the schema will be inlined instead of a referenced which is the default for
1062///   [`ToSchema`][to_schema] types. _`ref("./external.json")`_ can be used to reference external
1063///   json file for body schema. **Note!** Utoipa does **not** guarantee that free form _`ref`_ is accessible via
1064///   OpenAPI doc or Swagger UI, users are responsible for making these guarantees.
1065///
1066/// ## Advanced format definition by `request_body(...)`
1067///
1068/// With advanced format the request body supports defining either one or multiple request bodies by `content` attribute.
1069///
1070/// ### Common request body attributes
1071///
1072/// * `description = "..."` Define the description for the request body object as str.
1073///
1074/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
1075///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
1076///
1077/// * `examples(...)` Define multiple examples for single request body. This attribute is mutually
1078///   exclusive to the _`example`_ attribute and if both are defined this will override the _`example`_.
1079///   This has same syntax as _`examples(...)`_ in [Response Attributes](#response-attributes)
1080///   _examples(...)_
1081///
1082/// ### Single request body content
1083///
1084/// * `content = ...` Can be _`content = Type`_, _`content = inline(Type)`_ or _`content = ref("...")`_. The
1085///   given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec
1086///   or Map etc. With _`inline(...)`_ the schema will be inlined instead of a referenced
1087///   which is the default for [`ToSchema`][to_schema] types. _`ref("./external.json")`_
1088///   can be used to reference external json file for body schema. **Note!** Utoipa does **not** guarantee
1089///   that free form _`ref`_ is accessible via OpenAPI doc or Swagger UI, users are responsible for making
1090///   these guarantees.
1091///
1092/// * `content_type = "..."` Can be used to override the default behavior
1093///   of auto resolving the content type from the `content` attribute. If defined the value should be valid
1094///   content type such as _`application/json`_ . By default the content type is _`text/plain`_
1095///   for [primitive Rust types][primitive], `application/octet-stream` for _`[u8]`_ and _`application/json`_
1096///   for struct and mixed enum types.
1097///
1098/// _**Example of single request body definitions.**_
1099/// ```text
1100///  request_body(content = String, description = "Xml as string request", content_type = "text/xml"),
1101///  request_body(content_type = "application/json"),
1102///  request_body = Pet,
1103///  request_body = Option<[Pet]>,
1104/// ```
1105///
1106/// ### Multiple request body content
1107///
1108/// * `content(...)` Can be tuple of content tuples according to format below.
1109///   ```text
1110///   ( schema )
1111///   ( schema = "content/type", example = ..., examples(..., ...)  )
1112///   ( "content/type", ),
1113///   ( "content/type", example = ..., examples(..., ...) )
1114///   ```
1115///
1116///   First argument of content tuple is _`schema`_, which is optional as long as either _`schema`_
1117///   or _`content/type`_ is defined. The _`schema`_ and _`content/type`_ is separated with equals
1118///   (=) sign. Optionally content tuple supports defining _`example`_  and _`examples`_ arguments. See
1119///   [common request body attributes][macro@path#common-request-body-attributes]
1120///
1121/// _**Example of multiple request body definitions.**_
1122///
1123/// ```text
1124///  // guess the content type for Pet and Pet2
1125///  request_body(description = "Common description",
1126///     content(
1127///         (Pet),
1128///         (Pet2)
1129///     )
1130///  ),
1131///  // define explicit content types
1132///  request_body(description = "Common description",
1133///     content(
1134///         (Pet = "application/json", examples(..., ...), example = ...),
1135///         (Pet2 = "text/xml", examples(..., ...), example = ...)
1136///     )
1137///  ),
1138///  // omit schema and accept arbitrary content types
1139///  request_body(description = "Common description",
1140///     content(
1141///         ("application/json"),
1142///         ("text/xml", examples(..., ...), example = ...)
1143///     )
1144///  ),
1145/// ```
1146///
1147/// # Response Attributes
1148///
1149/// * `status = ...` Is either a valid http status code integer. E.g. _`200`_ or a string value representing
1150///   a range such as _`"4XX"`_ or `"default"` or a valid _`http::status::StatusCode`_.
1151///   _`StatusCode`_ can either be use path to the status code or _status code_ constant directly.
1152///
1153/// * `description = "..."` Define description for the response as str.
1154///
1155/// * `body = ...` Optional response body object type. When left empty response does not expect to send any
1156///   response body. Can be _`body = Type`_, _`body = inline(Type)`_, or _`body = ref("...")`_.
1157///   The given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec or Map etc.
1158///   With _`inline(...)`_ the schema will be inlined instead of a referenced which is the default for
1159///   [`ToSchema`][to_schema] types. _`ref("./external.json")`_
1160///   can be used to reference external json file for body schema. **Note!** Utoipa does **not** guarantee
1161///   that free form _`ref`_ is accessible via OpenAPI doc or Swagger UI, users are responsible for making
1162///   these guarantees.
1163///
1164/// * `content_type = "..."` Can be used to override the default behavior
1165///   of auto resolving the content type from the `body` attribute. If defined the value should be valid
1166///   content type such as _`application/json`_ . By default the content type is _`text/plain`_
1167///   for [primitive Rust types][primitive], `application/octet-stream` for _`[u8]`_ and _`application/json`_
1168///   for struct and mixed enum types.
1169///
1170/// * `item_schema = ...` Optional schema describing each item of a streaming or event-based media
1171///   type such as `text/event-stream`, `application/jsonl` or `application/json-seq`. It maps to
1172///   OpenAPI 3.2's `itemSchema` media type keyword and accepts the same syntax as `body`, i.e.
1173///   _`item_schema = Type`_, _`item_schema = inline(Type)`_ or _`item_schema = ref("...")`_.
1174///   This attribute only emits the `itemSchema` keyword; opting the document in to OpenAPI 3.2
1175///   output (`openapi: 3.2.0`) is a separate, deliberate step done via
1176///   [`OpenApiVersion::Version32`][openapi_version].
1177///
1178/// * `headers(...)` Slice of response headers that are returned back to a caller.
1179///
1180/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
1181///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
1182///
1183/// * `response = ...` Type what implements [`ToResponse`][to_response_trait] trait. This can alternatively be used to
1184///   define response attributes. _`response`_ attribute cannot co-exist with other than _`status`_ attribute.
1185///
1186/// * `content((...), (...))` Can be used to define multiple return types for single response status. Supports same syntax as
1187///   [multiple request body content][`macro@path#multiple-request-body-content`].
1188///
1189/// * `examples(...)` Define multiple examples for single response. This attribute is mutually
1190///   exclusive to the _`example`_ attribute and if both are defined this will override the _`example`_.
1191///
1192/// * `links(...)` Define a map of operations links that can be followed from the response.
1193///
1194/// ## Response `examples(...)` syntax
1195///
1196/// * `name = ...` This is first attribute and value must be literal string.
1197/// * `summary = ...` Short description of example. Value must be literal string.
1198/// * `description = ...` Long description of example. Attribute supports markdown for rich text
1199///   representation. Value must be literal string.
1200/// * `value = ...` Example value. It must be _`json!(...)`_. _`json!(...)`_ should be something that
1201///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
1202/// * `external_value = ...` Define URI to literal example value. This is mutually exclusive to
1203///   the _`value`_ attribute. Value must be literal string.
1204///
1205///  _**Example of example definition.**_
1206/// ```text
1207///  ("John" = (summary = "This is John", value = json!({"name": "John"})))
1208/// ```
1209///
1210/// ## Response `links(...)` syntax
1211///
1212/// * `operation_ref = ...` Define a relative or absolute URI reference to an OAS operation. This field is
1213///   mutually exclusive of the _`operation_id`_ field, and **must** point to an [Operation Object][operation].
1214///   Value can be be [`str`] or an expression such as [`include_str!`][include_str] or static
1215///   [`const`][const] reference.
1216///
1217/// * `operation_id = ...` Define the name of an existing, resolvable OAS operation, as defined with a unique
1218///   _`operation_id`_. This field is mutually exclusive of the _`operation_ref`_ field.
1219///   Value can be be [`str`] or an expression such as [`include_str!`][include_str] or static
1220///   [`const`][const] reference.
1221///
1222/// * `parameters(...)` A map representing parameters to pass to an operation as specified with _`operation_id`_
1223///   or identified by _`operation_ref`_. The key is parameter name to be used and value can
1224///   be any value supported by JSON or an [expression][expression] e.g. `$path.id`
1225///     * `name = ...` Define name for the parameter.
1226///       Value can be be [`str`] or an expression such as [`include_str!`][include_str] or static
1227///       [`const`][const] reference.
1228///     * `value` = Any value that can be supported by JSON or an [expression][expression].
1229///
1230///     _**Example of parameters syntax:**_
1231///     ```text
1232///     parameters(
1233///          ("name" = value),
1234///          ("name" = value)
1235///     ),
1236///     ```
1237///
1238/// * `request_body = ...` Define a literal value or an [expression][expression] to be used as request body when
1239///   operation is called
1240///
1241/// * `description = ...` Define description of the link. Value supports Markdown syntax.Value can be be [`str`] or
1242///   an expression such as [`include_str!`][include_str] or static [`const`][const] reference.
1243///
1244/// * `server(...)` Define [Server][server] object to be used by the target operation. See
1245///   [server syntax][server_derive_syntax]
1246///
1247/// **Links syntax example:** See the full example below in [examples](#examples).
1248/// ```text
1249/// responses(
1250///     (status = 200, description = "success response",
1251///         links(
1252///             ("link_name" = (
1253///                 operation_id = "test_links",
1254///                 parameters(("key" = "value"), ("json_value" = json!(1))),
1255///                 request_body = "this is body",
1256///                 server(url = "http://localhost")
1257///             ))
1258///         )
1259///     )
1260/// )
1261/// ```
1262///
1263/// **Minimal response format:**
1264/// ```text
1265/// responses(
1266///     (status = 200, description = "success response"),
1267///     (status = 404, description = "resource missing"),
1268///     (status = "5XX", description = "server error"),
1269///     (status = StatusCode::INTERNAL_SERVER_ERROR, description = "internal server error"),
1270///     (status = IM_A_TEAPOT, description = "happy easter")
1271/// )
1272/// ```
1273///
1274/// **More complete Response:**
1275/// ```text
1276/// responses(
1277///     (status = 200, description = "Success response", body = Pet, content_type = "application/json",
1278///         headers(...),
1279///         example = json!({"id": 1, "name": "bob the cat"})
1280///     )
1281/// )
1282/// ```
1283///
1284/// **Multiple response return types with _`content(...)`_ attribute:**
1285///
1286/// _**Define multiple response return types for single response status with their own example.**_
1287/// ```text
1288/// responses(
1289///    (status = 200, content(
1290///            (User = "application/vnd.user.v1+json", example = json!(User {id: "id".to_string()})),
1291///            (User2 = "application/vnd.user.v2+json", example = json!(User2 {id: 2}))
1292///        )
1293///    )
1294/// )
1295/// ```
1296///
1297/// ### Using `ToResponse` for reusable responses
1298///
1299/// _**`ReusableResponse` must be a type that implements [`ToResponse`][to_response_trait].**_
1300/// ```text
1301/// responses(
1302///     (status = 200, response = ReusableResponse)
1303/// )
1304/// ```
1305///
1306/// _**[`ToResponse`][to_response_trait] can also be inlined to the responses map.**_
1307/// ```text
1308/// responses(
1309///     (status = 200, response = inline(ReusableResponse))
1310/// )
1311/// ```
1312///
1313/// ## Responses from `IntoResponses`
1314///
1315/// _**Responses for a path can be specified with one or more types that implement
1316/// [`IntoResponses`][into_responses_trait].**_
1317/// ```text
1318/// responses(MyResponse)
1319/// ```
1320///
1321/// # Response Header Attributes
1322///
1323/// * `name` Name of the header. E.g. _`x-csrf-token`_
1324///
1325/// * `type` Additional type of the header value. Can be `Type` or `inline(Type)`.
1326///   The given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec or Map etc.
1327///   With _`inline(...)`_ the schema will be inlined instead of a referenced which is the default for
1328///   [`ToSchema`][to_schema] types. **Reminder!** It's up to the user to use valid type for the
1329///   response header.
1330///
1331/// * `description = "..."` Can be used to define optional description for the response header as str.
1332///
1333/// **Header supported formats:**
1334///
1335/// ```text
1336/// ("x-csrf-token"),
1337/// ("x-csrf-token" = String, description = "New csrf token"),
1338/// ```
1339///
1340/// # Params Attributes
1341///
1342/// The list of attributes inside the `params(...)` attribute can take two forms: [Tuples](#tuples) or [IntoParams
1343/// Type](#intoparams-type).
1344///
1345/// ## Tuples
1346///
1347/// In the tuples format, parameters are specified using the following attributes inside a list of
1348/// tuples separated by commas:
1349///
1350/// * `name` _**Must be the first argument**_. Define the name for parameter.
1351///
1352/// * `parameter_type` Define possible type for the parameter. Can be `Type` or `inline(Type)`.
1353///   The given _`Type`_ can be any Rust type that is JSON parseable. It can be Option, Vec or Map etc.
1354///   With _`inline(...)`_ the schema will be inlined instead of a referenced which is the default for
1355///   [`ToSchema`][to_schema] types. Parameter type is placed after `name` with
1356///   equals sign E.g. _`"id" = string`_
1357///
1358/// * `in` _**Must be placed after name or parameter_type**_. Define the place of the parameter.
1359///   This must be one of the variants of [`openapi::path::ParameterIn`][in_enum].
1360///   E.g. _`Path, Query, Header, Cookie`_
1361///
1362/// * `deprecated` Define whether the parameter is deprecated or not. Can optionally be defined
1363///   with explicit `bool` value as _`deprecated = bool`_.
1364///
1365/// * `description = "..."` Define possible description for the parameter as str.
1366///
1367/// * `style = ...` Defines how parameters are serialized by [`ParameterStyle`][style]. Default values are based on _`in`_ attribute.
1368///
1369/// * `explode` Defines whether new _`parameter=value`_ is created for each parameter within _`object`_ or _`array`_.
1370///
1371/// * `allow_reserved` Defines whether reserved characters _`:/?#[]@!$&'()*+,;=`_ is allowed within value.
1372///
1373/// * `example = ...` Can method reference or _`json!(...)`_. Given example
1374///   will override any example in underlying parameter type.
1375///
1376/// * `extensions(...)` List of extensions local to the parameter
1377///
1378/// ##### Parameter type attributes
1379///
1380/// These attributes supported when _`parameter_type`_ is present. Either by manually providing one
1381/// or otherwise resolved e.g from path macro argument when _`actix_extras`_ crate feature is
1382/// enabled.
1383///
1384/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
1385///   an open value as a string. By default the format is derived from the type of the property
1386///   according OpenApi spec.
1387///
1388/// * `write_only` Defines property is only used in **write** operations *POST,PUT,PATCH* but not in *GET*
1389///
1390/// * `read_only` Defines property is only used in **read** operations *GET* but not in *POST,PUT,PATCH*
1391///
1392/// * `xml(...)` Can be used to define [`Xml`][xml] object properties for the parameter type.
1393///   See configuration options at xml attributes of [`ToSchema`][to_schema_xml]
1394///
1395/// * `nullable` Defines property is nullable (note this is different to non-required).
1396///
1397/// * `multiple_of = ...` Can be used to define multiplier for a value. Value is considered valid
1398///   division will result an `integer`. Value must be strictly above _`0`_.
1399///
1400/// * `maximum = ...` Can be used to define inclusive upper bound to a `number` value.
1401///
1402/// * `minimum = ...` Can be used to define inclusive lower bound to a `number` value.
1403///
1404/// * `exclusive_maximum = ...` Can be used to define exclusive upper bound to a `number` value.
1405///
1406/// * `exclusive_minimum = ...` Can be used to define exclusive lower bound to a `number` value.
1407///
1408/// * `max_length = ...` Can be used to define maximum length for `string` types.
1409///
1410/// * `min_length = ...` Can be used to define minimum length for `string` types.
1411///
1412/// * `pattern = ...` Can be used to define valid regular expression in _ECMA-262_ dialect the field value must match.
1413///
1414/// * `max_items = ...` Can be used to define maximum items allowed for `array` fields. Value must
1415///   be non-negative integer.
1416///
1417/// * `min_items = ...` Can be used to define minimum items allowed for `array` fields. Value must
1418///   be non-negative integer.
1419///
1420/// ##### Parameter Formats
1421/// ```test
1422/// ("name" = ParameterType, ParameterIn, ...)
1423/// ("name", ParameterIn, ...)
1424/// ```
1425///
1426/// **For example:**
1427///
1428/// ```text
1429/// params(
1430///     ("limit" = i32, Query),
1431///     ("x-custom-header" = String, Header, description = "Custom header"),
1432///     ("id" = String, Path, deprecated, description = "Pet database id"),
1433///     ("name", Path, deprecated, description = "Pet name"),
1434///     (
1435///         "value" = inline(Option<[String]>),
1436///         Query,
1437///         description = "Value description",
1438///         style = Form,
1439///         allow_reserved,
1440///         deprecated,
1441///         explode,
1442///         example = json!(["Value"])),
1443///         max_length = 10,
1444///         min_items = 1
1445///     )
1446/// )
1447/// ```
1448///
1449/// ## IntoParams Type
1450///
1451/// In the IntoParams parameters format, the parameters are specified using an identifier for a type
1452/// that implements [`IntoParams`][into_params]. See [`IntoParams`][into_params] for an
1453/// example.
1454///
1455/// ```text
1456/// params(MyParameters)
1457/// ```
1458///
1459/// **Note!** that `MyParameters` can also be used in combination with the [tuples
1460/// representation](#tuples) or other structs.
1461/// ```text
1462/// params(
1463///     MyParameters1,
1464///     MyParameters2,
1465///     ("id" = String, Path, deprecated, description = "Pet database id"),
1466/// )
1467/// ```
1468///
1469/// # Security Requirement Attributes
1470///
1471/// * `name` Define the name for security requirement. This must match to name of existing
1472///   [`SecurityScheme`][security_scheme].
1473/// * `scopes = [...]` Define the list of scopes needed. These must be scopes defined already in
1474///   existing [`SecurityScheme`][security_scheme].
1475///
1476/// **Security Requirement supported formats:**
1477///
1478/// ```text
1479/// (),
1480/// ("name" = []),
1481/// ("name" = ["scope1", "scope2"]),
1482/// ("name" = ["scope1", "scope2"], "name2" = []),
1483/// ```
1484///
1485/// Leaving empty _`()`_ creates an empty [`SecurityRequirement`][security] this is useful when
1486/// security requirement is optional for operation.
1487///
1488/// You can define multiple security requirements within same parenthesis separated by comma. This
1489/// allows you to define keys that must be simultaneously provided for the endpoint / API.
1490///
1491/// _**Following could be explained as: Security is optional and if provided it must either contain
1492/// `api_key` or `key AND key2`.**_
1493/// ```text
1494/// (),
1495/// ("api_key" = []),
1496/// ("key" = [], "key2" = []),
1497/// ```
1498///
1499/// # Extensions Requirements Attributes
1500///
1501/// * `x-property` defines the name of the extension.
1502/// * `json!(...)` defines the value associated with the named extension as a `serde_json::Value`.
1503///
1504/// **Extensions Requitement supported formats:**
1505///
1506/// ```text
1507/// ("x-property" = json!({ "type": "mock" }) ),
1508/// ("x-an-extension" = json!({ "type": "mock" }) ),
1509/// ("x-another-extension" = json!( "body" ) ),
1510/// ```
1511///
1512/// # actix_extras feature support for actix-web
1513///
1514/// **actix_extras** feature gives **utoipa** ability to parse path operation information from **actix-web** types and macros.
1515///
1516/// 1. Ability to parse `path` from **actix-web** path attribute macros e.g. _`#[get(...)]`_ or
1517///    `#[route(...)]`.
1518/// 2. Ability to parse [`std::primitive`]  or [`String`] or [`tuple`] typed `path` parameters from **actix-web** _`web::Path<...>`_.
1519/// 3. Ability to parse `path` and `query` parameters form **actix-web** _`web::Path<...>`_, _`web::Query<...>`_ types
1520///    with [`IntoParams`][into_params] trait.
1521///
1522/// See the **actix_extras** in action in examples [todo-actix](https://github.com/juhaku/utoipa/tree/master/examples/todo-actix).
1523///
1524/// With **actix_extras** feature enabled the you can leave out definitions for **path**, **operation**
1525/// and **parameter types**.
1526/// ```rust
1527/// use actix_web::{get, web, HttpResponse, Responder};
1528/// use serde_json::json;
1529///
1530/// /// Get Pet by id
1531/// #[utoipa::path(
1532///     responses(
1533///         (status = 200, description = "Pet found from database")
1534///     ),
1535///     params(
1536///         ("id", description = "Pet id"),
1537///     )
1538/// )]
1539/// #[get("/pet/{id}")]
1540/// async fn get_pet_by_id(id: web::Path<i32>) -> impl Responder {
1541///     HttpResponse::Ok().json(json!({ "pet": format!("{:?}", &id.into_inner()) }))
1542/// }
1543/// ```
1544///
1545/// With **actix_extras** you may also not to list any _**params**_ if you do not want to specify any description for them. Params are
1546/// resolved from path and the argument types of handler
1547/// ```rust
1548/// use actix_web::{get, web, HttpResponse, Responder};
1549/// use serde_json::json;
1550///
1551/// /// Get Pet by id
1552/// #[utoipa::path(
1553///     responses(
1554///         (status = 200, description = "Pet found from database")
1555///     )
1556/// )]
1557/// #[get("/pet/{id}")]
1558/// async fn get_pet_by_id(id: web::Path<i32>) -> impl Responder {
1559///     HttpResponse::Ok().json(json!({ "pet": format!("{:?}", &id.into_inner()) }))
1560/// }
1561/// ```
1562///
1563/// # rocket_extras feature support for rocket
1564///
1565/// **rocket_extras** feature enhances path operation parameter support. It gives **utoipa** ability to parse `path`, `path parameters`
1566/// and `query parameters` based on arguments given to **rocket**  proc macros such as _**`#[get(...)]`**_.
1567///
1568/// 1. It is able to parse parameter types for [primitive types][primitive], [`String`], [`Vec`], [`Option`] or [`std::path::PathBuf`]
1569///    type.
1570/// 2. It is able to determine `parameter_in` for [`IntoParams`][into_params] trait used for `FromForm` type of query parameters.
1571///
1572/// See the **rocket_extras** in action in examples [rocket-todo](https://github.com/juhaku/utoipa/tree/master/examples/rocket-todo).
1573///
1574///
1575/// # axum_extras feature support for axum
1576///
1577/// **axum_extras** feature enhances parameter support for path operation in following ways.
1578///
1579/// 1. It allows users to use tuple style path parameters e.g. _`Path((id, name)): Path<(i32, String)>`_ and resolves
1580///    parameter names and types from it.
1581/// 2. It enhances [`IntoParams` derive][into_params_derive] functionality by automatically resolving _`parameter_in`_ from
1582///    _`Path<...>`_ or _`Query<...>`_ handler function arguments.
1583///
1584/// _**Resole path argument types from tuple style handler arguments.**_
1585/// ```rust
1586/// # use axum::extract::Path;
1587/// /// Get todo by id and name.
1588/// #[utoipa::path(
1589///     get,
1590///     path = "/todo/{id}",
1591///     params(
1592///         ("id", description = "Todo id"),
1593///         ("name", description = "Todo name")
1594///     ),
1595///     responses(
1596///         (status = 200, description = "Get todo success", body = String)
1597///     )
1598/// )]
1599/// async fn get_todo(
1600///     Path((id, name)): Path<(i32, String)>
1601/// ) -> String {
1602///     String::new()
1603/// }
1604/// ```
1605///
1606/// _**Use `IntoParams` to resolve query parameters.**_
1607/// ```rust
1608/// # use serde::Deserialize;
1609/// # use utoipa::IntoParams;
1610/// # use axum::{extract::Query, Json};
1611/// #[derive(Deserialize, IntoParams)]
1612/// struct TodoSearchQuery {
1613///     /// Search by value. Search is incase sensitive.
1614///     value: String,
1615///     /// Search by `done` status.
1616///     done: bool,
1617/// }
1618///
1619/// /// Search Todos by query params.
1620/// #[utoipa::path(
1621///     get,
1622///     path = "/todo/search",
1623///     params(
1624///         TodoSearchQuery
1625///     ),
1626///     responses(
1627///         (status = 200, description = "List matching todos by query", body = [String])
1628///     )
1629/// )]
1630/// async fn search_todos(
1631///     query: Query<TodoSearchQuery>,
1632/// ) -> Json<Vec<String>> {
1633///     Json(vec![])
1634/// }
1635/// ```
1636///
1637/// # Defining file uploads
1638///
1639/// File uploads can be defined in accordance to Open API specification [file uploads][file_uploads].
1640///
1641///
1642/// _**Example sending `jpg` and `png` images as `application/octet-stream`.**_
1643/// ```rust
1644/// #[utoipa::path(
1645///     post,
1646///     request_body(
1647///         content(
1648///             ("image/png"),
1649///             ("image/jpg"),
1650///         ),
1651///     ),
1652///     path = "/test_images"
1653/// )]
1654/// async fn test_images(_body: Vec<u8>) {}
1655/// ```
1656///
1657/// _**Example of sending `multipart` form.**_
1658/// ```rust
1659/// #[derive(utoipa::ToSchema)]
1660/// struct MyForm {
1661///     order_id: i32,
1662///     #[schema(content_media_type = "application/octet-stream")]
1663///     file_bytes: Vec<u8>,
1664/// }
1665///
1666/// #[utoipa::path(
1667///     post,
1668///     request_body(content = inline(MyForm), content_type = "multipart/form-data"),
1669///     path = "/test_multipart"
1670/// )]
1671/// async fn test_multipart(_body: MyForm) {}
1672/// ```
1673///
1674/// _**Example of sending arbitrary binary content as `application/octet-stream`.**_
1675/// ```rust
1676/// #[utoipa::path(
1677///     post,
1678///     request_body = Vec<u8>,
1679///     path = "/test-octet-stream",
1680///     responses(
1681///         (status = 200, description = "success response")
1682///     ),
1683/// )]
1684/// async fn test_octet_stream(_body: Vec<u8>) {}
1685/// ```
1686///
1687/// _**Example of sending `png` image as `base64` encoded.**_
1688/// ```rust
1689/// #[derive(utoipa::ToSchema)]
1690/// #[schema(content_encoding = "base64")]
1691/// struct MyPng(String);
1692///
1693/// #[utoipa::path(
1694///     post,
1695///     request_body(content = inline(MyPng), content_type = "image/png"),
1696///     path = "/test_png",
1697///     responses(
1698///         (status = 200, description = "success response")
1699///     ),
1700/// )]
1701/// async fn test_png(_body: MyPng) {}
1702/// ```
1703///
1704/// # Examples
1705///
1706/// _**More complete example.**_
1707/// ```rust
1708/// # #[derive(utoipa::ToSchema)]
1709/// # struct Pet {
1710/// #    id: u64,
1711/// #    name: String,
1712/// # }
1713/// #
1714/// #[utoipa::path(
1715///    post,
1716///    operation_id = "custom_post_pet",
1717///    path = "/pet",
1718///    tag = "pet_handlers",
1719///    request_body(content = Pet, description = "Pet to store the database", content_type = "application/json"),
1720///    responses(
1721///         (status = 200, description = "Pet stored successfully", body = Pet, content_type = "application/json",
1722///             headers(
1723///                 ("x-cache-len" = String, description = "Cache length")
1724///             ),
1725///             example = json!({"id": 1, "name": "bob the cat"})
1726///         ),
1727///    ),
1728///    params(
1729///      ("x-csrf-token" = String, Header, deprecated, description = "Current csrf token of user"),
1730///    ),
1731///    security(
1732///        (),
1733///        ("my_auth" = ["read:items", "edit:items"]),
1734///        ("token_jwt" = [])
1735///    )
1736/// )]
1737/// fn post_pet(pet: Pet) -> Pet {
1738///     Pet {
1739///         id: 4,
1740///         name: "bob the cat".to_string(),
1741///     }
1742/// }
1743/// ```
1744///
1745/// _**More minimal example with the defaults.**_
1746/// ```rust
1747/// # #[derive(utoipa::ToSchema)]
1748/// # struct Pet {
1749/// #    id: u64,
1750/// #    name: String,
1751/// # }
1752/// #
1753/// #[utoipa::path(
1754///    post,
1755///    path = "/pet",
1756///    request_body = Pet,
1757///    responses(
1758///         (status = 200, description = "Pet stored successfully", body = Pet,
1759///             headers(
1760///                 ("x-cache-len", description = "Cache length")
1761///             )
1762///         ),
1763///    ),
1764///    params(
1765///      ("x-csrf-token", Header, description = "Current csrf token of user"),
1766///    )
1767/// )]
1768/// fn post_pet(pet: Pet) -> Pet {
1769///     Pet {
1770///         id: 4,
1771///         name: "bob the cat".to_string(),
1772///     }
1773/// }
1774/// ```
1775///
1776/// _**Use of Rust's own `#[deprecated]` attribute will reflect to the generated OpenAPI spec and mark this operation as deprecated.**_
1777/// ```rust
1778/// # use actix_web::{get, web, HttpResponse, Responder};
1779/// # use serde_json::json;
1780/// #[utoipa::path(
1781///     responses(
1782///         (status = 200, description = "Pet found from database")
1783///     ),
1784///     params(
1785///         ("id", description = "Pet id"),
1786///     )
1787/// )]
1788/// #[get("/pet/{id}")]
1789/// #[deprecated]
1790/// async fn get_pet_by_id(id: web::Path<i32>) -> impl Responder {
1791///     HttpResponse::Ok().json(json!({ "pet": format!("{:?}", &id.into_inner()) }))
1792/// }
1793/// ```
1794///
1795/// _**Define context path for endpoint. The resolved **path** shown in OpenAPI doc will be `/api/pet/{id}`.**_
1796/// ```rust
1797/// # use actix_web::{get, web, HttpResponse, Responder};
1798/// # use serde_json::json;
1799/// #[utoipa::path(
1800///     context_path = "/api",
1801///     responses(
1802///         (status = 200, description = "Pet found from database")
1803///     )
1804/// )]
1805/// #[get("/pet/{id}")]
1806/// async fn get_pet_by_id(id: web::Path<i32>) -> impl Responder {
1807///     HttpResponse::Ok().json(json!({ "pet": format!("{:?}", &id.into_inner()) }))
1808/// }
1809/// ```
1810///
1811/// _**Example with multiple return types**_
1812/// ```rust
1813/// # trait User {}
1814/// # #[derive(utoipa::ToSchema)]
1815/// # struct User1 {
1816/// #   id: String
1817/// # }
1818/// # impl User for User1 {}
1819/// # #[derive(utoipa::ToSchema)]
1820/// # struct User2 {
1821/// #   id: String
1822/// # }
1823/// # impl User for User2 {}
1824/// #[utoipa::path(
1825///     get,
1826///     path = "/user",
1827///     responses(
1828///         (status = 200, content(
1829///                 (User1 = "application/vnd.user.v1+json", example = json!({"id": "id".to_string()})),
1830///                 (User2 = "application/vnd.user.v2+json", example = json!({"id": 2}))
1831///             )
1832///         )
1833///     )
1834/// )]
1835/// fn get_user() -> Box<dyn User> {
1836///   Box::new(User1 {id: "id".to_string()})
1837/// }
1838/// ````
1839///
1840/// _**Example with multiple examples on single response.**_
1841/// ```rust
1842/// # #[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
1843/// # struct User {
1844/// #   name: String
1845/// # }
1846/// #[utoipa::path(
1847///     get,
1848///     path = "/user",
1849///     responses(
1850///         (status = 200, body = User,
1851///             examples(
1852///                 ("Demo" = (summary = "This is summary", description = "Long description",
1853///                             value = json!(User{name: "Demo".to_string()}))),
1854///                 ("John" = (summary = "Another user", value = json!({"name": "John"})))
1855///              )
1856///         )
1857///     )
1858/// )]
1859/// fn get_user() -> User {
1860///   User {name: "John".to_string()}
1861/// }
1862/// ```
1863///
1864/// _**Example of using links in response.**_
1865/// ```rust
1866/// # use serde_json::json;
1867///  #[utoipa::path(
1868///     get,
1869///     path = "/test-links",
1870///     responses(
1871///         (status = 200, description = "success response",
1872///             links(
1873///                 ("getFoo" = (
1874///                     operation_id = "test_links",
1875///                     parameters(("key" = "value"), ("json_value" = json!(1))),
1876///                     request_body = "this is body",
1877///                     server(url = "http://localhost")
1878///                 )),
1879///                 ("getBar" = (
1880///                     operation_ref = "this is ref"
1881///                 ))
1882///             )
1883///         )
1884///     ),
1885/// )]
1886/// async fn test_links() -> &'static str {
1887///     ""
1888/// }
1889/// ```
1890///
1891/// [in_enum]: openapi/path/enum.ParameterIn.html
1892/// [path]: trait.Path.html
1893/// [to_schema]: trait.ToSchema.html
1894/// [openapi]: derive.OpenApi.html
1895/// [security]: openapi/security/struct.SecurityRequirement.html
1896/// [security_scheme]: openapi/security/enum.SecurityScheme.html
1897/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
1898/// [into_params]: trait.IntoParams.html
1899/// [style]: openapi/path/enum.ParameterStyle.html
1900/// [into_responses_trait]: trait.IntoResponses.html
1901/// [into_params_derive]: derive.IntoParams.html
1902/// [to_response_trait]: trait.ToResponse.html
1903/// [known_format]: openapi/schema/enum.KnownFormat.html
1904/// [openapi_version]: openapi/enum.OpenApiVersion.html
1905/// [xml]: openapi/xml/struct.Xml.html
1906/// [to_schema_xml]: macro@ToSchema#xml-attribute-configuration-options
1907/// [relative_references]: https://spec.openapis.org/oas/latest.html#relative-references-in-uris
1908/// [operation]: openapi/path/struct.Operation.html
1909/// [expression]: https://spec.openapis.org/oas/latest.html#runtime-expressions
1910/// [const]: https://doc.rust-lang.org/std/keyword.const.html
1911/// [include_str]: https://doc.rust-lang.org/std/macro.include_str.html
1912/// [server_derive_syntax]: derive.OpenApi.html#servers-attribute-syntax
1913/// [server]: openapi/server/struct.Server.html
1914/// [file_uploads]: <https://spec.openapis.org/oas/v3.1.0.html#considerations-for-file-uploads>
1915pub fn path(attr: TokenStream, item: TokenStream) -> TokenStream {
1916    let path_attribute = syn::parse_macro_input!(attr as PathAttr);
1917
1918    #[cfg(any(
1919        feature = "actix_extras",
1920        feature = "rocket_extras",
1921        feature = "axum_extras",
1922        feature = "auto_into_responses"
1923    ))]
1924    let mut path_attribute = path_attribute;
1925
1926    let ast_fn = match syn::parse::<ItemFn>(item) {
1927        Ok(ast_fn) => ast_fn,
1928        Err(error) => return error.into_compile_error().into_token_stream().into(),
1929    };
1930
1931    #[cfg(feature = "auto_into_responses")]
1932    {
1933        if let Some(responses) = ext::auto_types::parse_fn_operation_responses(&ast_fn) {
1934            path_attribute.responses_from_into_responses(responses);
1935        };
1936    }
1937
1938    let mut resolved_methods = match PathOperations::resolve_operation(&ast_fn) {
1939        Ok(operation) => operation,
1940        Err(diagnostics) => return diagnostics.into_token_stream().into(),
1941    };
1942    let resolved_path = PathOperations::resolve_path(
1943        &resolved_methods
1944            .as_mut()
1945            .map(|operation| mem::take(&mut operation.path).to_string())
1946            .or_else(|| path_attribute.path.as_ref().map(|path| path.to_string())), // cannot use mem take because we need this later
1947    );
1948
1949    #[cfg(any(
1950        feature = "actix_extras",
1951        feature = "rocket_extras",
1952        feature = "axum_extras"
1953    ))]
1954    let mut resolved_path = resolved_path;
1955
1956    #[cfg(any(
1957        feature = "actix_extras",
1958        feature = "rocket_extras",
1959        feature = "axum_extras"
1960    ))]
1961    {
1962        use ext::ArgumentResolver;
1963        use path::parameter::Parameter;
1964        let path_args = resolved_path.as_mut().map(|path| mem::take(&mut path.args));
1965        let body = resolved_methods
1966            .as_mut()
1967            .map(|path| mem::take(&mut path.body))
1968            .unwrap_or_default();
1969
1970        let (arguments, into_params_types, body) =
1971            match PathOperations::resolve_arguments(&ast_fn.sig.inputs, path_args, body) {
1972                Ok(args) => args,
1973                Err(diagnostics) => return diagnostics.into_token_stream().into(),
1974            };
1975
1976        let parameters = arguments
1977            .into_iter()
1978            .flatten()
1979            .map(Parameter::from)
1980            .chain(into_params_types.into_iter().flatten().map(Parameter::from));
1981        path_attribute.update_parameters_ext(parameters);
1982
1983        path_attribute.update_request_body(body);
1984    }
1985
1986    let path = Path::new(path_attribute, &ast_fn.sig.ident)
1987        .ext_methods(resolved_methods.map(|operation| operation.methods))
1988        .path(resolved_path.map(|path| path.path))
1989        .doc_comments(CommentAttributes::from_attributes(&ast_fn.attrs).0)
1990        .deprecated(ast_fn.attrs.has_deprecated());
1991
1992    let handler = path::handler::Handler {
1993        path,
1994        handler_fn: &ast_fn,
1995    };
1996    handler.to_token_stream().into()
1997}
1998
1999#[proc_macro_derive(OpenApi, attributes(openapi))]
2000/// Generate OpenApi base object with defaults from
2001/// project settings.
2002///
2003/// This is `#[derive]` implementation for [`OpenApi`][openapi] trait. The macro accepts one `openapi` argument.
2004///
2005/// # OpenApi `#[openapi(...)]` attributes
2006///
2007/// * `paths(...)`  List of method references having attribute [`#[utoipa::path]`][path] macro.
2008/// * `components(schemas(...), responses(...))` Takes available _`component`_ configurations. Currently only
2009///   _`schema`_ and _`response`_ components are supported.
2010/// * `schemas(...)` List of [`ToSchema`][to_schema]s in OpenAPI schema.
2011/// * `responses(...)` List of types that implement [`ToResponse`][to_response_trait].
2012/// * `modifiers(...)` List of items implementing [`Modify`][modify] trait for runtime OpenApi modification.
2013///   See the [trait documentation][modify] for more details.
2014/// * `security(...)` List of [`SecurityRequirement`][security]s global to all operations.
2015///   See more details in [`#[utoipa::path(...)]`][path] [attribute macro security options][path_security].
2016/// * `tags(...)` List of [`Tag`][tags]s which must match the tag _**path operation**_.  Tags can be used to
2017///   define extra information for the API to produce richer documentation. See [tags attribute syntax][tags_syntax].
2018/// * `external_docs(...)` Can be used to reference external resource to the OpenAPI doc for extended documentation.
2019///   External docs can be in [`OpenApi`][openapi_struct] or in [`Tag`][tags] level.
2020/// * `servers(...)` Define [`servers`][servers] as derive argument to the _`OpenApi`_. Servers
2021///   are completely optional and thus can be omitted from the declaration. See [servers attribute
2022///   syntax][servers_syntax]
2023/// * `info(...)` Declare [`Info`][info] attribute values used to override the default values
2024///   generated from Cargo environment variables. **Note!** Defined attributes will override the
2025///   whole attribute from generated values of Cargo environment variables. E.g. defining
2026///   `contact(name = ...)` will ultimately override whole contact of info and not just partially
2027///   the name. See [info attribute syntax][info_syntax]
2028/// * `nest(...)` Allows nesting [`OpenApi`][openapi_struct]s to this _`OpenApi`_ instance. Nest
2029///   takes comma separated list of tuples of nested `OpenApi`s. _`OpenApi`_ instance must
2030///   implement [`OpenApi`][openapi] trait. Nesting allows defining one `OpenApi` per defined path.
2031///   If more instances is defined only latest one will be rentained.
2032///   See the _[nest(...) attribute syntax below]( #nest-attribute-syntax )_
2033/// * `version = "..."` Set the [`OpenApiVersion`][openapi_version] the document serializes as.
2034///   Accepts a full `X.Y.Z` version string: `"3.1.0"` (the default) or `"3.2.0"`. Opt in to
2035///   `"3.2.0"` to emit OpenAPI 3.2 keywords.
2036///
2037///
2038/// OpenApi derive macro will also derive [`Info`][info] for OpenApi specification using Cargo
2039/// environment variables.
2040///
2041/// * env `CARGO_PKG_NAME` map to info `title`
2042/// * env `CARGO_PKG_VERSION` map to info `version`
2043/// * env `CARGO_PKG_DESCRIPTION` map info `description`
2044/// * env `CARGO_PKG_AUTHORS` map to contact `name` and `email` **only first author will be used**
2045/// * env `CARGO_PKG_LICENSE` map to info `license`
2046///
2047/// # `info(...)` attribute syntax
2048///
2049/// * `title = ...` Define title of the API. It can be [`str`] or an
2050///   expression such as [`include_str!`][include_str] or static [`const`][const] reference.
2051/// * `terms_of_service = ...` Define URL to the Terms of Service for the API. It can be [`str`] or an
2052///   expression such as [`include_str!`][include_str] or static [`const`][const] reference. Value
2053///   must be valid URL.
2054/// * `description = ...` Define description of the API. Markdown can be used for rich text
2055///   representation. It can be [`str`] or an expression such as [`include_str!`][include_str] or static
2056///   [`const`][const] reference.
2057/// * `version = ...` Override default version from _`Cargo.toml`_. Value can be [`str`] or an
2058///   expression such as [`include_str!`][include_str] or static [`const`][const] reference.
2059/// * `contact(...)` Used to override the whole contact generated from environment variables.
2060///     * `name = ...` Define identifying name of contact person / organization. It Can be a literal string.
2061///     * `email = ...` Define email address of the contact person / organization. It can be a literal string.
2062///     * `url = ...` Define URL pointing to the contact information. It must be in URL formatted string.
2063/// * `license(...)` Used to override the whole license generated from environment variables.
2064///     * `name = ...` License name of the API. It can be a literal string.
2065///     * `url = ...` Define optional URL of the license. It must be URL formatted string.
2066///
2067/// # `tags(...)` attribute syntax
2068///
2069/// * `name = ...` Must be provided, can be [`str`] or an expression such as [`include_str!`][include_str]
2070///   or static [`const`][const] reference.
2071/// * `description = ...` Optional description for the tag. Can be either or static [`str`]
2072///   or an expression e.g. _`include_str!(...)`_ macro call or reference to static [`const`][const].
2073/// * `external_docs(...)` Optional links to external documents.
2074///      * `url = ...` Mandatory URL for external documentation.
2075///      * `description = ...` Optional description for the _`url`_ link.
2076///
2077/// # `servers(...)` attribute syntax
2078///
2079/// * `url = ...` Define the url for server. It can be literal string.
2080/// * `description = ...` Define description for the server. It can be literal string.
2081/// * `variables(...)` Can be used to define variables for the url.
2082///     * `name = ...` Is the first argument within parentheses. It must be literal string.
2083///     * `default = ...` Defines a default value for the variable if nothing else will be
2084///       provided. If _`enum_values`_ is defined the _`default`_ must be found within the enum
2085///       options. It can be a literal string.
2086///     * `description = ...` Define the description for the variable. It can be a literal string.
2087///     * `enum_values(...)` Define list of possible values for the variable. Values must be
2088///       literal strings.
2089///
2090/// _**Example server variable definition.**_
2091/// ```text
2092/// ("username" = (default = "demo", description = "Default username for API")),
2093/// ("port" = (enum_values("8080", "5000", "4545")))
2094/// ```
2095///
2096/// # `nest(...)` attribute syntax
2097///
2098/// * `path = ...` Define mandatory path for nesting the [`OpenApi`][openapi_struct].
2099/// * `api = ...` Define mandatory path to struct that implements [`OpenApi`][openapi] trait.
2100///   The fully qualified path (_`path::to`_) will become the default _`tag`_ for the nested
2101///   `OpenApi` endpoints if provided.
2102/// * `tags = [...]` Define optional tags what are appended to the existing list of tags.
2103///
2104///  _**Example of nest definition**_
2105///  ```text
2106///  (path = "path/to/nest", api = path::to::NestableApi),
2107///  (path = "path/to/nest", api = path::to::NestableApi, tags = ["nestableapi", ...])
2108///  ```
2109///
2110/// # Examples
2111///
2112/// _**Define OpenApi schema with some paths and components.**_
2113/// ```rust
2114/// # use utoipa::{OpenApi, ToSchema};
2115/// #
2116/// #[derive(ToSchema)]
2117/// struct Pet {
2118///     name: String,
2119///     age: i32,
2120/// }
2121///
2122/// #[derive(ToSchema)]
2123/// enum Status {
2124///     Active, InActive, Locked,
2125/// }
2126///
2127/// #[utoipa::path(get, path = "/pet")]
2128/// fn get_pet() -> Pet {
2129///     Pet {
2130///         name: "bob".to_string(),
2131///         age: 8,
2132///     }
2133/// }
2134///
2135/// #[utoipa::path(get, path = "/status")]
2136/// fn get_status() -> Status {
2137///     Status::Active
2138/// }
2139///
2140/// #[derive(OpenApi)]
2141/// #[openapi(
2142///     paths(get_pet, get_status),
2143///     components(schemas(Pet, Status)),
2144///     security(
2145///         (),
2146///         ("my_auth" = ["read:items", "edit:items"]),
2147///         ("token_jwt" = [])
2148///     ),
2149///     tags(
2150///         (name = "pets::api", description = "All about pets",
2151///             external_docs(url = "http://more.about.pets.api", description = "Find out more"))
2152///     ),
2153///     external_docs(url = "http://more.about.our.apis", description = "More about our APIs")
2154/// )]
2155/// struct ApiDoc;
2156/// ```
2157///
2158/// _**Define servers to OpenApi.**_
2159/// ```rust
2160/// # use utoipa::OpenApi;
2161/// #[derive(OpenApi)]
2162/// #[openapi(
2163///     servers(
2164///         (url = "http://localhost:8989", description = "Local server"),
2165///         (url = "http://api.{username}:{port}", description = "Remote API",
2166///             variables(
2167///                 ("username" = (default = "demo", description = "Default username for API")),
2168///                 ("port" = (default = "8080", enum_values("8080", "5000", "3030"), description = "Supported ports for API"))
2169///             )
2170///         )
2171///     )
2172/// )]
2173/// struct ApiDoc;
2174/// ```
2175///
2176/// _**Define info attribute values used to override auto generated ones from Cargo environment
2177/// variables.**_
2178/// ```compile_fail
2179/// # use utoipa::OpenApi;
2180/// #[derive(OpenApi)]
2181/// #[openapi(info(
2182///     title = "title override",
2183///     description = include_str!("./path/to/content"), // fail compile cause no such file
2184///     contact(name = "Test")
2185/// ))]
2186/// struct ApiDoc;
2187/// ```
2188///
2189/// _**Create OpenAPI with reusable response.**_
2190/// ```rust
2191/// #[derive(utoipa::ToSchema)]
2192/// struct Person {
2193///     name: String,
2194/// }
2195///
2196/// /// Person list response
2197/// #[derive(utoipa::ToResponse)]
2198/// struct PersonList(Vec<Person>);
2199///
2200/// #[utoipa::path(
2201///     get,
2202///     path = "/person-list",
2203///     responses(
2204///         (status = 200, response = PersonList)
2205///     )
2206/// )]
2207/// fn get_persons() -> Vec<Person> {
2208///     vec![]
2209/// }
2210///
2211/// #[derive(utoipa::OpenApi)]
2212/// #[openapi(
2213///     components(
2214///         schemas(Person),
2215///         responses(PersonList)
2216///     )
2217/// )]
2218/// struct ApiDoc;
2219/// ```
2220///
2221/// _**Nest _`UserApi`_ to the current api doc instance.**_
2222/// ```rust
2223/// # use utoipa::OpenApi;
2224/// #
2225///  #[utoipa::path(get, path = "/api/v1/status")]
2226///  fn test_path_status() {}
2227///
2228///  #[utoipa::path(get, path = "/test")]
2229///  fn user_test_path() {}
2230///
2231///  #[derive(OpenApi)]
2232///  #[openapi(paths(user_test_path))]
2233///  struct UserApi;
2234///
2235///  #[derive(OpenApi)]
2236///  #[openapi(
2237///      paths(
2238///          test_path_status
2239///      ),
2240///      nest(
2241///          (path = "/api/v1/user", api = UserApi),
2242///      )
2243///  )]
2244///  struct ApiDoc;
2245/// ```
2246///
2247/// [openapi]: trait.OpenApi.html
2248/// [openapi_struct]: openapi/struct.OpenApi.html
2249/// [openapi_version]: openapi/enum.OpenApiVersion.html
2250/// [to_schema]: derive.ToSchema.html
2251/// [path]: attr.path.html
2252/// [modify]: trait.Modify.html
2253/// [info]: openapi/info/struct.Info.html
2254/// [security]: openapi/security/struct.SecurityRequirement.html
2255/// [path_security]: attr.path.html#security-requirement-attributes
2256/// [tags]: openapi/tag/struct.Tag.html
2257/// [to_response_trait]: trait.ToResponse.html
2258/// [servers]: openapi/server/index.html
2259/// [const]: https://doc.rust-lang.org/std/keyword.const.html
2260/// [tags_syntax]: #tags-attribute-syntax
2261/// [info_syntax]: #info-attribute-syntax
2262/// [servers_syntax]: #servers-attribute-syntax
2263/// [include_str]: https://doc.rust-lang.org/std/macro.include_str.html
2264pub fn openapi(input: TokenStream) -> TokenStream {
2265    let DeriveInput { attrs, ident, .. } = syn::parse_macro_input!(input);
2266
2267    parse_openapi_attrs(&attrs)
2268        .map(|openapi_attr| OpenApi(openapi_attr, ident).to_token_stream())
2269        .map_or_else(syn::Error::into_compile_error, ToTokens::into_token_stream)
2270        .into()
2271}
2272
2273#[proc_macro_derive(IntoParams, attributes(param, into_params))]
2274/// Generate [path parameters][path_params] from struct's
2275/// fields.
2276///
2277/// This is `#[derive]` implementation for [`IntoParams`][into_params] trait.
2278///
2279/// Typically path parameters need to be defined within [`#[utoipa::path(...params(...))]`][path_params] section
2280/// for the endpoint. But this trait eliminates the need for that when [`struct`][struct]s are used to define parameters.
2281/// Still [`std::primitive`] and [`String`] path parameters or [`tuple`] style path parameters need to be defined
2282/// within `params(...)` section if description or other than default configuration need to be given.
2283///
2284/// You can use the Rust's own `#[deprecated]` attribute on field to mark it as
2285/// deprecated and it will reflect to the generated OpenAPI spec.
2286///
2287/// `#[deprecated]` attribute supports adding additional details such as a reason and or since version
2288/// but this is is not supported in OpenAPI. OpenAPI has only a boolean flag to determine deprecation.
2289/// While it is totally okay to declare deprecated with reason
2290/// `#[deprecated  = "There is better way to do this"]` the reason would not render in OpenAPI spec.
2291///
2292/// Doc comment on struct fields will be used as description for the generated parameters.
2293/// ```rust
2294/// #[derive(utoipa::IntoParams)]
2295/// struct Query {
2296///     /// Query todo items by name.
2297///     name: String
2298/// }
2299/// ```
2300///
2301/// # IntoParams Container Attributes for `#[into_params(...)]`
2302///
2303/// The following attributes are available for use in on the container attribute `#[into_params(...)]` for the struct
2304/// deriving `IntoParams`:
2305///
2306/// * `names(...)` Define comma separated list of names for unnamed fields of struct used as a path parameter.
2307///   __Only__ supported on __unnamed structs__.
2308/// * `style = ...` Defines how all parameters are serialized by [`ParameterStyle`][style]. Default
2309///   values are based on _`parameter_in`_ attribute.
2310/// * `parameter_in = ...` =  Defines where the parameters of this field are used with a value from
2311///   [`openapi::path::ParameterIn`][in_enum]. There is no default value, if this attribute is not
2312///   supplied, then the value is determined by the `parameter_in_provider` in
2313///   [`IntoParams::into_params()`](trait.IntoParams.html#tymethod.into_params).
2314/// * `rename_all = ...` Can be provided to alternatively to the serde's `rename_all` attribute. Effectively provides same functionality.
2315///
2316/// Use `names` to define name for single unnamed argument.
2317/// ```rust
2318/// # use utoipa::IntoParams;
2319/// #
2320/// #[derive(IntoParams)]
2321/// #[into_params(names("id"))]
2322/// struct Id(u64);
2323/// ```
2324///
2325/// Use `names` to define names for multiple unnamed arguments.
2326/// ```rust
2327/// # use utoipa::IntoParams;
2328/// #
2329/// #[derive(IntoParams)]
2330/// #[into_params(names("id", "name"))]
2331/// struct IdAndName(u64, String);
2332/// ```
2333///
2334/// # IntoParams Field Attributes for `#[param(...)]`
2335///
2336/// The following attributes are available for use in the `#[param(...)]` on struct fields:
2337///
2338/// * `style = ...` Defines how the parameter is serialized by [`ParameterStyle`][style]. Default values are based on _`parameter_in`_ attribute.
2339///
2340/// * `explode` Defines whether new _`parameter=value`_ pair is created for each parameter within _`object`_ or _`array`_.
2341///
2342/// * `allow_reserved` Defines whether reserved characters _`:/?#[]@!$&'()*+,;=`_ is allowed within value.
2343///
2344/// * `example = ...` Can be method reference or _`json!(...)`_. Given example
2345///   will override any example in underlying parameter type.
2346///
2347/// * `value_type = ...` Can be used to override default type derived from type of the field used in OpenAPI spec.
2348///   This is useful in cases where the default type does not correspond to the actual type e.g. when
2349///   any third-party types are used which are not [`ToSchema`][to_schema]s nor [`primitive` types][primitive].
2350///   The value can be any Rust type what normally could be used to serialize to JSON, or either virtual type _`Object`_
2351///   or _`Value`_.
2352///   _`Object`_ will be rendered as generic OpenAPI object _(`type: object`)_.
2353///   _`Value`_ will be rendered as any OpenAPI value (i.e. no `type` restriction).
2354///
2355/// * `inline` If set, the schema for this field's type needs to be a [`ToSchema`][to_schema], and
2356///   the schema definition will be inlined.
2357///
2358/// * `default = ...` Can be method reference or _`json!(...)`_.
2359///
2360/// * `format = ...` May either be variant of the [`KnownFormat`][known_format] enum, or otherwise
2361///   an open value as a string. By default the format is derived from the type of the property
2362///   according OpenApi spec.
2363///
2364/// * `write_only` Defines property is only used in **write** operations *POST,PUT,PATCH* but not in *GET*.
2365///
2366/// * `read_only` Defines property is only used in **read** operations *GET* but not in *POST,PUT,PATCH*.
2367///
2368/// * `xml(...)` Can be used to define [`Xml`][xml] object properties applicable to named fields.
2369///   See configuration options at xml attributes of [`ToSchema`][to_schema_xml]
2370///
2371/// * `nullable` Defines property is nullable (note this is different to non-required).
2372///
2373/// * `required = ...` Can be used to enforce required status for the parameter. [See
2374///   rules][derive@IntoParams#field-nullability-and-required-rules]
2375///
2376/// * `rename = ...` Can be provided to alternatively to the serde's `rename` attribute. Effectively provides same functionality.
2377///
2378/// * `multiple_of = ...` Can be used to define multiplier for a value. Value is considered valid
2379///   division will result an `integer`. Value must be strictly above _`0`_.
2380///
2381/// * `maximum = ...` Can be used to define inclusive upper bound to a `number` value.
2382///
2383/// * `minimum = ...` Can be used to define inclusive lower bound to a `number` value.
2384///
2385/// * `exclusive_maximum = ...` Can be used to define exclusive upper bound to a `number` value.
2386///
2387/// * `exclusive_minimum = ...` Can be used to define exclusive lower bound to a `number` value.
2388///
2389/// * `max_length = ...` Can be used to define maximum length for `string` types.
2390///
2391/// * `min_length = ...` Can be used to define minimum length for `string` types.
2392///
2393/// * `pattern = ...` Can be used to define valid regular expression in _ECMA-262_ dialect the field value must match.
2394///
2395/// * `max_items = ...` Can be used to define maximum items allowed for `array` fields. Value must
2396///   be non-negative integer.
2397///
2398/// * `min_items = ...` Can be used to define minimum items allowed for `array` fields. Value must
2399///   be non-negative integer.
2400///
2401/// * `schema_with = ...` Use _`schema`_ created by provided function reference instead of the
2402///   default derived _`schema`_. The function must match to `fn() -> Into<RefOr<Schema>>`. It does
2403///   not accept arguments and must return anything that can be converted into `RefOr<Schema>`.
2404///
2405/// * `additional_properties = ...` Can be used to define free form types for maps such as
2406///   [`HashMap`](std::collections::HashMap) and [`BTreeMap`](std::collections::BTreeMap).
2407///   Free form type enables use of arbitrary types within map values.
2408///   Supports formats _`additional_properties`_ and _`additional_properties = true`_.
2409///
2410/// * `ignore` or `ignore = ...` Can be used to skip the field from being serialized to OpenAPI schema Only literal `bool` value is allowed.
2411///
2412/// #### Field nullability and required rules
2413///
2414/// Same rules for nullability and required status apply for _`IntoParams`_ field attributes as for
2415/// _`ToSchema`_ field attributes. [See the rules][`derive@ToSchema#field-nullability-and-required-rules`].
2416///
2417/// # Partial `#[serde(...)]` attributes support
2418///
2419/// IntoParams derive has partial support for [serde attributes]. These supported attributes will reflect to the
2420/// generated OpenAPI doc. The following attributes are currently supported:
2421///
2422/// * `rename_all = "..."` Supported at the container level.
2423/// * `rename = "..."` Supported **only** at the field level.
2424/// * `default` Supported at the container level and field level according to [serde attributes].
2425/// * `skip_serializing_if = "..."` Supported  **only** at the field level.
2426/// * `with = ...` Supported **only** at field level.
2427/// * `skip_serializing = "..."` Supported  **only** at the field or variant level.
2428/// * `skip_deserializing = "..."` Supported  **only** at the field or variant level.
2429/// * `skip = "..."` Supported  **only** at the field level.
2430///
2431/// Other _`serde`_ attributes will impact the serialization but will not be reflected on the generated OpenAPI doc.
2432///
2433/// # Examples
2434///
2435/// _**Demonstrate [`IntoParams`][into_params] usage with resolving `Path` and `Query` parameters
2436/// with _`actix-web`_**_.
2437/// ```rust
2438/// use actix_web::{get, HttpResponse, Responder};
2439/// use actix_web::web::{Path, Query};
2440/// use serde::Deserialize;
2441/// use serde_json::json;
2442/// use utoipa::IntoParams;
2443///
2444/// #[derive(Deserialize, IntoParams)]
2445/// struct PetPathArgs {
2446///     /// Id of pet
2447///     id: i64,
2448///     /// Name of pet
2449///     name: String,
2450/// }
2451///
2452/// #[derive(Deserialize, IntoParams)]
2453/// struct Filter {
2454///     /// Age filter for pets
2455///     #[deprecated]
2456///     #[param(style = Form, explode, allow_reserved, example = json!([10]))]
2457///     age: Option<Vec<i32>>,
2458/// }
2459///
2460/// #[utoipa::path(
2461///     params(PetPathArgs, Filter),
2462///     responses(
2463///         (status = 200, description = "success response")
2464///     )
2465/// )]
2466/// #[get("/pet/{id}/{name}")]
2467/// async fn get_pet(pet: Path<PetPathArgs>, query: Query<Filter>) -> impl Responder {
2468///     HttpResponse::Ok().json(json!({ "id": pet.id }))
2469/// }
2470/// ```
2471///
2472/// _**Demonstrate [`IntoParams`][into_params] usage with the `#[into_params(...)]` container attribute to
2473/// be used as a path query, and inlining a schema query field:**_
2474/// ```rust
2475/// use serde::Deserialize;
2476/// use utoipa::{IntoParams, ToSchema};
2477///
2478/// #[derive(Deserialize, ToSchema)]
2479/// #[serde(rename_all = "snake_case")]
2480/// enum PetKind {
2481///     Dog,
2482///     Cat,
2483/// }
2484///
2485/// #[derive(Deserialize, IntoParams)]
2486/// #[into_params(style = Form, parameter_in = Query)]
2487/// struct PetQuery {
2488///     /// Name of pet
2489///     name: Option<String>,
2490///     /// Age of pet
2491///     age: Option<i32>,
2492///     /// Kind of pet
2493///     #[param(inline)]
2494///     kind: PetKind
2495/// }
2496///
2497/// #[utoipa::path(
2498///     get,
2499///     path = "/get_pet",
2500///     params(PetQuery),
2501///     responses(
2502///         (status = 200, description = "success response")
2503///     )
2504/// )]
2505/// async fn get_pet(query: PetQuery) {
2506///     // ...
2507/// }
2508/// ```
2509///
2510/// _**Override `String` with `i64` using `value_type` attribute.**_
2511/// ```rust
2512/// # use utoipa::IntoParams;
2513/// #
2514/// #[derive(IntoParams)]
2515/// #[into_params(parameter_in = Query)]
2516/// struct Filter {
2517///     #[param(value_type = i64)]
2518///     id: String,
2519/// }
2520/// ```
2521///
2522/// _**Override `String` with `Object` using `value_type` attribute. _`Object`_ will render as `type: object` in OpenAPI spec.**_
2523/// ```rust
2524/// # use utoipa::IntoParams;
2525/// #
2526/// #[derive(IntoParams)]
2527/// #[into_params(parameter_in = Query)]
2528/// struct Filter {
2529///     #[param(value_type = Object)]
2530///     id: String,
2531/// }
2532/// ```
2533///
2534/// _**You can use a generic type to override the default type of the field.**_
2535/// ```rust
2536/// # use utoipa::IntoParams;
2537/// #
2538/// #[derive(IntoParams)]
2539/// #[into_params(parameter_in = Query)]
2540/// struct Filter {
2541///     #[param(value_type = Option<String>)]
2542///     id: String
2543/// }
2544/// ```
2545///
2546/// _**You can even override a [`Vec`] with another one.**_
2547/// ```rust
2548/// # use utoipa::IntoParams;
2549/// #
2550/// #[derive(IntoParams)]
2551/// #[into_params(parameter_in = Query)]
2552/// struct Filter {
2553///     #[param(value_type = Vec<i32>)]
2554///     id: Vec<String>
2555/// }
2556/// ```
2557///
2558/// _**We can override value with another [`ToSchema`][to_schema].**_
2559/// ```rust
2560/// # use utoipa::{IntoParams, ToSchema};
2561/// #
2562/// #[derive(ToSchema)]
2563/// struct Id {
2564///     value: i64,
2565/// }
2566///
2567/// #[derive(IntoParams)]
2568/// #[into_params(parameter_in = Query)]
2569/// struct Filter {
2570///     #[param(value_type = Id)]
2571///     id: String
2572/// }
2573/// ```
2574///
2575/// _**Example with validation attributes.**_
2576/// ```rust
2577/// #[derive(utoipa::IntoParams)]
2578/// struct Item {
2579///     #[param(maximum = 10, minimum = 5, multiple_of = 2.5)]
2580///     id: i32,
2581///     #[param(max_length = 10, min_length = 5, pattern = "[a-z]*")]
2582///     value: String,
2583///     #[param(max_items = 5, min_items = 1)]
2584///     items: Vec<String>,
2585/// }
2586/// ````
2587///
2588/// _**Use `schema_with` to manually implement schema for a field.**_
2589/// ```rust
2590/// # use utoipa::openapi::schema::{Object, ObjectBuilder};
2591/// fn custom_type() -> Object {
2592///     ObjectBuilder::new()
2593///         .schema_type(utoipa::openapi::schema::Type::String)
2594///         .format(Some(utoipa::openapi::SchemaFormat::Custom(
2595///             "email".to_string(),
2596///         )))
2597///         .description(Some("this is the description"))
2598///         .build()
2599/// }
2600///
2601/// #[derive(utoipa::IntoParams)]
2602/// #[into_params(parameter_in = Query)]
2603/// struct Query {
2604///     #[param(schema_with = custom_type)]
2605///     email: String,
2606/// }
2607/// ```
2608///
2609/// [to_schema]: trait.ToSchema.html
2610/// [known_format]: openapi/schema/enum.KnownFormat.html
2611/// [xml]: openapi/xml/struct.Xml.html
2612/// [into_params]: trait.IntoParams.html
2613/// [path_params]: attr.path.html#params-attributes
2614/// [struct]: https://doc.rust-lang.org/std/keyword.struct.html
2615/// [style]: openapi/path/enum.ParameterStyle.html
2616/// [in_enum]: openapi/path/enum.ParameterIn.html
2617/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
2618/// [serde attributes]: https://serde.rs/attributes.html
2619/// [to_schema_xml]: macro@ToSchema#xml-attribute-configuration-options
2620pub fn into_params(input: TokenStream) -> TokenStream {
2621    let DeriveInput {
2622        attrs,
2623        ident,
2624        generics,
2625        data,
2626        ..
2627    } = syn::parse_macro_input!(input);
2628
2629    let into_params = IntoParams {
2630        attrs,
2631        generics,
2632        data,
2633        ident,
2634    };
2635
2636    into_params.to_token_stream().into()
2637}
2638
2639#[proc_macro_derive(ToResponse, attributes(response, content, to_schema))]
2640/// Generate reusable OpenAPI response that can be used
2641/// in [`utoipa::path`][path] or in [`OpenApi`][openapi].
2642///
2643/// This is `#[derive]` implementation for [`ToResponse`][to_response] trait.
2644///
2645///
2646/// _`#[response]`_ attribute can be used to alter and add [response attributes](#toresponse-response-attributes).
2647///
2648/// _`#[content]`_ attributes is used to make enum variant a content of a specific type for the
2649/// response.
2650///
2651/// _`#[to_schema]`_ attribute is used to inline a schema for a response in unnamed structs or
2652/// enum variants with `#[content]` attribute. **Note!** [`ToSchema`] need to be implemented for
2653/// the field or variant type.
2654///
2655/// Type derived with _`ToResponse`_ uses provided doc comment as a description for the response. It
2656/// can alternatively be overridden with _`description = ...`_ attribute.
2657///
2658/// _`ToResponse`_ can be used in four different ways to generate OpenAPI response component.
2659///
2660/// 1. By decorating `struct` or `enum` with [`derive@ToResponse`] derive macro. This will create a
2661///    response with inlined schema resolved from the fields of the `struct` or `variants` of the
2662///    enum.
2663///
2664///    ```rust
2665///     # use utoipa::ToResponse;
2666///     #[derive(ToResponse)]
2667///     #[response(description = "Person response returns single Person entity")]
2668///     struct Person {
2669///         name: String,
2670///     }
2671///    ```
2672///
2673/// 2. By decorating unnamed field `struct` with [`derive@ToResponse`] derive macro. Unnamed field struct
2674///    allows users to use new type pattern to define one inner field which is used as a schema for
2675///    the generated response. This allows users to define `Vec` and `Option` response types.
2676///    Additionally these types can also be used with `#[to_schema]` attribute to inline the
2677///    field's type schema if it implements [`ToSchema`] derive macro.
2678///
2679///    ```rust
2680///     # #[derive(utoipa::ToSchema)]
2681///     # struct Person {
2682///     #     name: String,
2683///     # }
2684///     /// Person list response
2685///     #[derive(utoipa::ToResponse)]
2686///     struct PersonList(Vec<Person>);
2687///    ```
2688///
2689/// 3. By decorating unit struct with [`derive@ToResponse`] derive macro. Unit structs will produce a
2690///    response without body.
2691///
2692///    ```rust
2693///     /// Success response which does not have body.
2694///     #[derive(utoipa::ToResponse)]
2695///     struct SuccessResponse;
2696///    ```
2697///
2698/// 4. By decorating `enum` with variants having `#[content(...)]` attribute. This allows users to
2699///    define multiple response content schemas to single response according to OpenAPI spec.
2700///    **Note!** Enum with _`content`_ attribute in variants cannot have enum level _`example`_ or
2701///    _`examples`_ defined. Instead examples need to be defined per variant basis. Additionally
2702///    these variants can also be used with `#[to_schema]` attribute to inline the variant's type schema
2703///    if it implements [`ToSchema`] derive macro.
2704///
2705///    ```rust
2706///     #[derive(utoipa::ToSchema)]
2707///     struct Admin {
2708///         name: String,
2709///     }
2710///     #[derive(utoipa::ToSchema)]
2711///     struct Admin2 {
2712///         name: String,
2713///         id: i32,
2714///     }
2715///
2716///     #[derive(utoipa::ToResponse)]
2717///     enum Person {
2718///         #[response(examples(
2719///             ("Person1" = (value = json!({"name": "name1"}))),
2720///             ("Person2" = (value = json!({"name": "name2"})))
2721///         ))]
2722///         Admin(#[content("application/vnd-custom-v1+json")] Admin),
2723///
2724///         #[response(example = json!({"name": "name3", "id": 1}))]
2725///         Admin2(#[content("application/vnd-custom-v2+json")] #[to_schema] Admin2),
2726///     }
2727///    ```
2728///
2729/// # ToResponse `#[response(...)]` attributes
2730///
2731/// * `description = "..."` Define description for the response as str. This can be used to
2732///   override the default description resolved from doc comments if present.
2733///
2734/// * `content_type = "..."` Can be used to override the default behavior
2735///   of auto resolving the content type from the `body` attribute. If defined the value should be valid
2736///   content type such as _`application/json`_ . By default the content type is _`text/plain`_
2737///   for [primitive Rust types][primitive], `application/octet-stream` for _`[u8]`_ and _`application/json`_
2738///   for struct and mixed enum types.
2739///
2740/// * `headers(...)` Slice of response headers that are returned back to a caller.
2741///
2742/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
2743///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
2744///
2745/// * `examples(...)` Define multiple examples for single response. This attribute is mutually
2746///   exclusive to the _`example`_ attribute and if both are defined this will override the _`example`_.
2747///     * `name = ...` This is first attribute and value must be literal string.
2748///     * `summary = ...` Short description of example. Value must be literal string.
2749///     * `description = ...` Long description of example. Attribute supports markdown for rich text
2750///       representation. Value must be literal string.
2751///     * `value = ...` Example value. It must be _`json!(...)`_. _`json!(...)`_ should be something that
2752///       _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
2753///     * `external_value = ...` Define URI to literal example value. This is mutually exclusive to
2754///       the _`value`_ attribute. Value must be literal string.
2755///
2756///      _**Example of example definition.**_
2757///     ```text
2758///      ("John" = (summary = "This is John", value = json!({"name": "John"})))
2759///     ```
2760///
2761/// # Examples
2762///
2763/// _**Use reusable response in operation handler.**_
2764/// ```rust
2765/// #[derive(utoipa::ToResponse)]
2766/// struct PersonResponse {
2767///    value: String
2768/// }
2769///
2770/// #[derive(utoipa::OpenApi)]
2771/// #[openapi(components(responses(PersonResponse)))]
2772/// struct Doc;
2773///
2774/// #[utoipa::path(
2775///     get,
2776///     path = "/api/person",
2777///     responses(
2778///         (status = 200, response = PersonResponse)
2779///     )
2780/// )]
2781/// fn get_person() -> PersonResponse {
2782///     PersonResponse { value: "person".to_string() }
2783/// }
2784/// ```
2785///
2786/// _**Create a response from named struct.**_
2787/// ```rust
2788///  /// This is description
2789///  ///
2790///  /// It will also be used in `ToSchema` if present
2791///  #[derive(utoipa::ToSchema, utoipa::ToResponse)]
2792///  #[response(
2793///      description = "Override description for response",
2794///      content_type = "text/xml"
2795///  )]
2796///  #[response(
2797///      example = json!({"name": "the name"}),
2798///      headers(
2799///          ("csrf-token", description = "response csrf token"),
2800///          ("random-id" = i32)
2801///      )
2802///  )]
2803///  struct Person {
2804///      name: String,
2805///  }
2806/// ```
2807///
2808/// _**Create inlined person list response.**_
2809/// ```rust
2810///  # #[derive(utoipa::ToSchema)]
2811///  # struct Person {
2812///  #     name: String,
2813///  # }
2814///  /// Person list response
2815///  #[derive(utoipa::ToResponse)]
2816///  struct PersonList(#[to_schema] Vec<Person>);
2817/// ```
2818///
2819/// _**Create enum response from variants.**_
2820/// ```rust
2821///  #[derive(utoipa::ToResponse)]
2822///  enum PersonType {
2823///      Value(String),
2824///      Foobar,
2825///  }
2826/// ```
2827///
2828/// [to_response]: trait.ToResponse.html
2829/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
2830/// [path]: attr.path.html
2831/// [openapi]: derive.OpenApi.html
2832pub fn to_response(input: TokenStream) -> TokenStream {
2833    let DeriveInput {
2834        attrs,
2835        ident,
2836        generics,
2837        data,
2838        ..
2839    } = syn::parse_macro_input!(input);
2840
2841    ToResponse::new(attrs, &data, generics, ident)
2842        .as_ref()
2843        .map_or_else(Diagnostics::to_token_stream, ToResponse::to_token_stream)
2844        .into()
2845}
2846
2847#[proc_macro_derive(
2848    IntoResponses,
2849    attributes(response, to_schema, ref_response, to_response)
2850)]
2851/// Generate responses with status codes what
2852/// can be attached to the [`utoipa::path`][path_into_responses].
2853///
2854/// This is `#[derive]` implementation of [`IntoResponses`][into_responses] trait. [`derive@IntoResponses`]
2855/// can be used to decorate _`structs`_ and _`enums`_ to generate response maps that can be used in
2856/// [`utoipa::path`][path_into_responses]. If _`struct`_ is decorated with [`derive@IntoResponses`] it will be
2857/// used to create a map of responses containing single response. Decorating _`enum`_ with
2858/// [`derive@IntoResponses`] will create a map of responses with a response for each variant of the _`enum`_.
2859///
2860/// Named field _`struct`_ decorated with [`derive@IntoResponses`] will create a response with inlined schema
2861/// generated from the body of the struct. This is a conveniency which allows users to directly
2862/// create responses with schemas without first creating a separate [response][to_response] type.
2863///
2864/// Unit _`struct`_ behaves similarly to then named field struct. Only difference is that it will create
2865/// a response without content since there is no inner fields.
2866///
2867/// Unnamed field _`struct`_ decorated with [`derive@IntoResponses`] will by default create a response with
2868/// referenced [schema][to_schema] if field is object or schema if type is [primitive
2869/// type][primitive]. _`#[to_schema]`_ attribute at field of unnamed _`struct`_ can be used to inline
2870/// the schema if type of the field implements [`ToSchema`][to_schema] trait. Alternatively
2871/// _`#[to_response]`_ and _`#[ref_response]`_ can be used at field to either reference a reusable
2872/// [response][to_response] or inline a reusable [response][to_response]. In both cases the field
2873/// type is expected to implement [`ToResponse`][to_response] trait.
2874///
2875///
2876/// Enum decorated with [`derive@IntoResponses`] will create a response for each variant of the _`enum`_.
2877/// Each variant must have it's own _`#[response(...)]`_ definition. Unit variant will behave same
2878/// as unit _`struct`_ by creating a response without content. Similarly named field variant and
2879/// unnamed field variant behaves the same as it was named field _`struct`_ and unnamed field
2880/// _`struct`_.
2881///
2882/// _`#[response]`_ attribute can be used at named structs, unnamed structs, unit structs and enum
2883/// variants to alter [response attributes](#intoresponses-response-attributes) of responses.
2884///
2885/// Doc comment on a _`struct`_ or _`enum`_ variant will be used as a description for the response.
2886/// It can also be overridden with _`description = "..."`_ attribute.
2887///
2888/// # IntoResponses `#[response(...)]` attributes
2889///
2890/// * `status = ...` Must be provided. Is either a valid http status code integer. E.g. _`200`_ or a
2891///   string value representing a range such as _`"4XX"`_ or `"default"` or a valid _`http::status::StatusCode`_.
2892///   _`StatusCode`_ can either be use path to the status code or _status code_ constant directly.
2893///
2894/// * `description = "..."` Define description for the response as str. This can be used to
2895///   override the default description resolved from doc comments if present.
2896///
2897/// * `content_type = "..."` Can be used to override the default behavior
2898///   of auto resolving the content type from the `body` attribute. If defined the value should be valid
2899///   content type such as _`application/json`_ . By default the content type is _`text/plain`_
2900///   for [primitive Rust types][primitive], `application/octet-stream` for _`[u8]`_ and _`application/json`_
2901///   for struct and mixed enum types.
2902///
2903/// * `headers(...)` Slice of response headers that are returned back to a caller.
2904///
2905/// * `example = ...` Can be _`json!(...)`_. _`json!(...)`_ should be something that
2906///   _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
2907///
2908/// * `examples(...)` Define multiple examples for single response. This attribute is mutually
2909///   exclusive to the _`example`_ attribute and if both are defined this will override the _`example`_.
2910///     * `name = ...` This is first attribute and value must be literal string.
2911///     * `summary = ...` Short description of example. Value must be literal string.
2912///     * `description = ...` Long description of example. Attribute supports markdown for rich text
2913///       representation. Value must be literal string.
2914///     * `value = ...` Example value. It must be _`json!(...)`_. _`json!(...)`_ should be something that
2915///       _`serde_json::json!`_ can parse as a _`serde_json::Value`_.
2916///     * `external_value = ...` Define URI to literal example value. This is mutually exclusive to
2917///       the _`value`_ attribute. Value must be literal string.
2918///
2919///      _**Example of example definition.**_
2920///     ```text
2921///      ("John" = (summary = "This is John", value = json!({"name": "John"})))
2922///     ```
2923///
2924/// # Examples
2925///
2926/// _**Use `IntoResponses` to define [`utoipa::path`][path] responses.**_
2927/// ```rust
2928/// #[derive(utoipa::ToSchema)]
2929/// struct BadRequest {
2930///     message: String,
2931/// }
2932///
2933/// #[derive(utoipa::IntoResponses)]
2934/// enum UserResponses {
2935///     /// Success response
2936///     #[response(status = 200)]
2937///     Success { value: String },
2938///
2939///     #[response(status = 404)]
2940///     NotFound,
2941///
2942///     #[response(status = 400)]
2943///     BadRequest(BadRequest),
2944/// }
2945///
2946/// #[utoipa::path(
2947///     get,
2948///     path = "/api/user",
2949///     responses(
2950///         UserResponses
2951///     )
2952/// )]
2953/// fn get_user() -> UserResponses {
2954///    UserResponses::NotFound
2955/// }
2956/// ```
2957/// _**Named struct response with inlined schema.**_
2958/// ```rust
2959/// /// This is success response
2960/// #[derive(utoipa::IntoResponses)]
2961/// #[response(status = 200)]
2962/// struct SuccessResponse {
2963///     value: String,
2964/// }
2965/// ```
2966///
2967/// _**Unit struct response without content.**_
2968/// ```rust
2969/// #[derive(utoipa::IntoResponses)]
2970/// #[response(status = NOT_FOUND)]
2971/// struct NotFound;
2972/// ```
2973///
2974/// _**Unnamed struct response with inlined response schema.**_
2975/// ```rust
2976/// # #[derive(utoipa::ToSchema)]
2977/// # struct Foo;
2978/// #[derive(utoipa::IntoResponses)]
2979/// #[response(status = 201)]
2980/// struct CreatedResponse(#[to_schema] Foo);
2981/// ```
2982///
2983/// _**Enum with multiple responses.**_
2984/// ```rust
2985/// # #[derive(utoipa::ToResponse)]
2986/// # struct Response {
2987/// #     message: String,
2988/// # }
2989/// # #[derive(utoipa::ToSchema)]
2990/// # struct BadRequest {}
2991/// #[derive(utoipa::IntoResponses)]
2992/// enum UserResponses {
2993///     /// Success response description.
2994///     #[response(status = 200)]
2995///     Success { value: String },
2996///
2997///     #[response(status = 404)]
2998///     NotFound,
2999///
3000///     #[response(status = 400)]
3001///     BadRequest(BadRequest),
3002///
3003///     #[response(status = 500)]
3004///     ServerError(#[ref_response] Response),
3005///
3006///     #[response(status = 418)]
3007///     TeaPot(#[to_response] Response),
3008/// }
3009/// ```
3010///
3011/// [into_responses]: trait.IntoResponses.html
3012/// [to_schema]: trait.ToSchema.html
3013/// [to_response]: trait.ToResponse.html
3014/// [path_into_responses]: attr.path.html#responses-from-intoresponses
3015/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
3016/// [path]: macro@crate::path
3017pub fn into_responses(input: TokenStream) -> TokenStream {
3018    let DeriveInput {
3019        attrs,
3020        ident,
3021        generics,
3022        data,
3023        ..
3024    } = syn::parse_macro_input!(input);
3025
3026    let into_responses = IntoResponses {
3027        attributes: attrs,
3028        ident,
3029        generics,
3030        data,
3031    };
3032
3033    into_responses.to_token_stream().into()
3034}
3035
3036/// Create OpenAPI Schema from arbitrary type.
3037///
3038/// This macro provides a quick way to render arbitrary types as OpenAPI Schema Objects. It
3039/// supports two call formats.
3040/// 1. With type only
3041/// 2. With _`#[inline]`_ attribute to inline the referenced schemas.
3042///
3043/// By default the macro will create references `($ref)` for non primitive types like _`Pet`_.
3044/// However when used with _`#[inline]`_ the non [`primitive`][primitive] type schemas will
3045/// be inlined to the schema output.
3046///
3047/// ```rust
3048/// # use utoipa::openapi::{RefOr, schema::Schema};
3049/// # #[derive(utoipa::ToSchema)]
3050/// # struct Pet {id: i32};
3051/// let schema: RefOr<Schema> = utoipa::schema!(Vec<Pet>).into();
3052///
3053/// // with inline
3054/// let schema: RefOr<Schema> = utoipa::schema!(#[inline] Vec<Pet>).into();
3055/// ```
3056///
3057/// # Examples
3058///
3059/// _**Create vec of pets schema.**_
3060/// ```rust
3061/// # use utoipa::openapi::schema::{Schema, Array, Object, ObjectBuilder, SchemaFormat,
3062/// # KnownFormat, Type};
3063/// # use utoipa::openapi::RefOr;
3064/// #[derive(utoipa::ToSchema)]
3065/// struct Pet {
3066///     id: i32,
3067///     name: String,
3068/// }
3069///
3070/// let schema: RefOr<Schema> = utoipa::schema!(#[inline] Vec<Pet>).into();
3071/// // will output
3072/// let generated = RefOr::T(Schema::Array(
3073///     Array::new(
3074///         ObjectBuilder::new()
3075///             .property("id", ObjectBuilder::new()
3076///                 .schema_type(Type::Integer)
3077///                 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
3078///                 .build())
3079///             .required("id")
3080///             .property("name", Object::with_type(Type::String))
3081///             .required("name")
3082///     )
3083/// ));
3084/// # insta::assert_json_snapshot!("schema", &schema);
3085/// ```
3086///
3087/// [primitive]: https://doc.rust-lang.org/std/primitive/index.html
3088#[proc_macro]
3089pub fn schema(input: TokenStream) -> TokenStream {
3090    struct Schema {
3091        inline: bool,
3092        ty: syn::Type,
3093    }
3094    impl Parse for Schema {
3095        fn parse(input: ParseStream) -> syn::Result<Self> {
3096            let inline = if input.peek(Token![#]) && input.peek2(Bracket) {
3097                input.parse::<Token![#]>()?;
3098
3099                let inline;
3100                bracketed!(inline in input);
3101                let i = inline.parse::<Ident>()?;
3102                i == "inline"
3103            } else {
3104                false
3105            };
3106
3107            let ty = input.parse()?;
3108
3109            Ok(Self { inline, ty })
3110        }
3111    }
3112
3113    let schema = syn::parse_macro_input!(input as Schema);
3114    let type_tree = match TypeTree::from_type(&schema.ty) {
3115        Ok(type_tree) => type_tree,
3116        Err(diagnostics) => return diagnostics.into_token_stream().into(),
3117    };
3118
3119    let generics = match type_tree.get_path_generics() {
3120        Ok(generics) => generics,
3121        Err(error) => return error.into_compile_error().into(),
3122    };
3123
3124    let schema = ComponentSchema::new(ComponentSchemaProps {
3125        features: vec![Feature::Inline(schema.inline.into())],
3126        type_tree: &type_tree,
3127        description: None,
3128        container: &component::Container {
3129            generics: &generics,
3130        },
3131    });
3132
3133    let schema = match schema {
3134        Ok(schema) => schema.to_token_stream(),
3135        Err(diagnostics) => return diagnostics.to_token_stream().into(),
3136    };
3137
3138    quote! {
3139        {
3140            let mut generics: Vec<utoipa::openapi::RefOr<utoipa::openapi::schema::Schema>> = Vec::new();
3141            #schema
3142        }
3143    }
3144    .into()
3145}
3146
3147/// Tokenizes slice or Vec of tokenizable items as array either with reference (`&[...]`)
3148/// or without correctly to OpenAPI JSON.
3149#[cfg_attr(feature = "debug", derive(Debug))]
3150enum Array<'a, T>
3151where
3152    T: Sized + ToTokens,
3153{
3154    Owned(Vec<T>),
3155    #[allow(dead_code)]
3156    Borrowed(&'a [T]),
3157}
3158
3159impl<V> FromIterator<V> for Array<'_, V>
3160where
3161    V: Sized + ToTokens,
3162{
3163    fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
3164        Self::Owned(iter.into_iter().collect())
3165    }
3166}
3167
3168impl<'a, T> Deref for Array<'a, T>
3169where
3170    T: Sized + ToTokens,
3171{
3172    type Target = [T];
3173
3174    fn deref(&self) -> &Self::Target {
3175        match self {
3176            Self::Owned(vec) => vec.as_slice(),
3177            Self::Borrowed(slice) => slice,
3178        }
3179    }
3180}
3181
3182impl<T> ToTokens for Array<'_, T>
3183where
3184    T: Sized + ToTokens,
3185{
3186    fn to_tokens(&self, tokens: &mut TokenStream2) {
3187        let values = match self {
3188            Self::Owned(values) => values.iter(),
3189            Self::Borrowed(values) => values.iter(),
3190        };
3191
3192        // Emit `vec![...]` rather than a stack array literal `[...]` to avoid
3193        // large stack allocations for wide types (juhaku/utoipa#1454).
3194        let items = values
3195            .fold(Punctuated::new(), |mut punctuated, item| {
3196                punctuated.push_value(item);
3197                punctuated.push_punct(Punct::new(',', proc_macro2::Spacing::Alone));
3198
3199                punctuated
3200            })
3201            .to_token_stream();
3202
3203        tokens.extend(quote! { vec![#items] });
3204    }
3205}
3206
3207#[cfg_attr(feature = "debug", derive(Debug))]
3208enum Deprecated {
3209    True,
3210    False,
3211}
3212
3213impl From<bool> for Deprecated {
3214    fn from(bool: bool) -> Self {
3215        if bool {
3216            Self::True
3217        } else {
3218            Self::False
3219        }
3220    }
3221}
3222
3223impl ToTokens for Deprecated {
3224    fn to_tokens(&self, tokens: &mut TokenStream2) {
3225        tokens.extend(match self {
3226            Self::False => quote! { utoipa::openapi::Deprecated::False },
3227            Self::True => quote! { utoipa::openapi::Deprecated::True },
3228        })
3229    }
3230}
3231
3232#[derive(PartialEq, Eq)]
3233#[cfg_attr(feature = "debug", derive(Debug))]
3234enum Required {
3235    True,
3236    False,
3237}
3238
3239impl From<bool> for Required {
3240    fn from(bool: bool) -> Self {
3241        if bool {
3242            Self::True
3243        } else {
3244            Self::False
3245        }
3246    }
3247}
3248
3249impl From<features::attributes::Required> for Required {
3250    fn from(value: features::attributes::Required) -> Self {
3251        let features::attributes::Required(required) = value;
3252        crate::Required::from(required)
3253    }
3254}
3255
3256impl ToTokens for Required {
3257    fn to_tokens(&self, tokens: &mut TokenStream2) {
3258        tokens.extend(match self {
3259            Self::False => quote! { utoipa::openapi::Required::False },
3260            Self::True => quote! { utoipa::openapi::Required::True },
3261        })
3262    }
3263}
3264
3265#[derive(Default)]
3266#[cfg_attr(feature = "debug", derive(Debug))]
3267struct ExternalDocs {
3268    url: String,
3269    description: Option<String>,
3270}
3271
3272impl Parse for ExternalDocs {
3273    fn parse(input: ParseStream) -> syn::Result<Self> {
3274        const EXPECTED_ATTRIBUTE: &str = "unexpected attribute, expected any of: url, description";
3275
3276        let mut external_docs = ExternalDocs::default();
3277
3278        while !input.is_empty() {
3279            let ident = input.parse::<Ident>().map_err(|error| {
3280                syn::Error::new(error.span(), format!("{EXPECTED_ATTRIBUTE}, {error}"))
3281            })?;
3282            let attribute_name = &*ident.to_string();
3283
3284            match attribute_name {
3285                "url" => {
3286                    external_docs.url = parse_utils::parse_next_literal_str(input)?;
3287                }
3288                "description" => {
3289                    external_docs.description = Some(parse_utils::parse_next_literal_str(input)?);
3290                }
3291                _ => return Err(syn::Error::new(ident.span(), EXPECTED_ATTRIBUTE)),
3292            }
3293
3294            if !input.is_empty() {
3295                input.parse::<Token![,]>()?;
3296            }
3297        }
3298
3299        Ok(external_docs)
3300    }
3301}
3302
3303impl ToTokens for ExternalDocs {
3304    fn to_tokens(&self, tokens: &mut TokenStream2) {
3305        let url = &self.url;
3306        tokens.extend(quote! {
3307            utoipa::openapi::external_docs::ExternalDocsBuilder::new()
3308                .url(#url)
3309        });
3310
3311        if let Some(ref description) = self.description {
3312            tokens.extend(quote! {
3313                .description(Some(#description))
3314            });
3315        }
3316
3317        tokens.extend(quote! { .build() })
3318    }
3319}
3320
3321/// Represents OpenAPI Any value used in example and default fields.
3322#[derive(Clone)]
3323#[cfg_attr(feature = "debug", derive(Debug))]
3324enum AnyValue {
3325    String(TokenStream2),
3326    Json(TokenStream2),
3327    DefaultTrait {
3328        struct_ident: Ident,
3329        field_ident: Member,
3330    },
3331}
3332
3333impl AnyValue {
3334    /// Parse `json!(...)` as [`AnyValue::Json`]
3335    fn parse_json(input: ParseStream) -> syn::Result<Self> {
3336        parse_utils::parse_json_token_stream(input).map(AnyValue::Json)
3337    }
3338
3339    fn parse_any(input: ParseStream) -> syn::Result<Self> {
3340        if input.peek(Lit) {
3341            let punct = input.parse::<Option<Token![-]>>()?;
3342            let lit = input.parse::<Lit>().unwrap();
3343
3344            Ok(AnyValue::Json(quote! { #punct #lit}))
3345        } else {
3346            let fork = input.fork();
3347            let is_json = if fork.peek(syn::Ident) && fork.peek2(Token![!]) {
3348                let ident = fork.parse::<Ident>().unwrap();
3349                ident == "json"
3350            } else {
3351                false
3352            };
3353
3354            if is_json {
3355                let json = parse_utils::parse_json_token_stream(input)?;
3356
3357                Ok(AnyValue::Json(json))
3358            } else {
3359                let method = input.parse::<ExprPath>().map_err(|error| {
3360                    syn::Error::new(
3361                        error.span(),
3362                        "expected literal value, json!(...) or method reference",
3363                    )
3364                })?;
3365
3366                Ok(AnyValue::Json(quote! { #method() }))
3367            }
3368        }
3369    }
3370
3371    fn parse_lit_str_or_json(input: ParseStream) -> syn::Result<Self> {
3372        if input.peek(LitStr) {
3373            Ok(AnyValue::String(
3374                input.parse::<LitStr>().unwrap().to_token_stream(),
3375            ))
3376        } else {
3377            Ok(AnyValue::Json(parse_utils::parse_json_token_stream(input)?))
3378        }
3379    }
3380
3381    fn new_default_trait(struct_ident: Ident, field_ident: Member) -> Self {
3382        Self::DefaultTrait {
3383            struct_ident,
3384            field_ident,
3385        }
3386    }
3387}
3388
3389impl ToTokens for AnyValue {
3390    fn to_tokens(&self, tokens: &mut TokenStream2) {
3391        match self {
3392            Self::Json(json) => tokens.extend(quote! {
3393                utoipa::gen::serde_json::json!(#json)
3394            }),
3395            Self::String(string) => string.to_tokens(tokens),
3396            Self::DefaultTrait {
3397                struct_ident,
3398                field_ident,
3399            } => tokens.extend(quote! {
3400                utoipa::gen::serde_json::to_value(#struct_ident::default().#field_ident).unwrap()
3401            }),
3402        }
3403    }
3404}
3405
3406trait OptionExt<T> {
3407    fn map_try<F, U, E>(self, f: F) -> Result<Option<U>, E>
3408    where
3409        F: FnOnce(T) -> Result<U, E>;
3410    fn and_then_try<F, U, E>(self, f: F) -> Result<Option<U>, E>
3411    where
3412        F: FnOnce(T) -> Result<Option<U>, E>;
3413    fn or_else_try<F, U>(self, f: F) -> Result<Option<T>, U>
3414    where
3415        F: FnOnce() -> Result<Option<T>, U>;
3416}
3417
3418impl<T> OptionExt<T> for Option<T> {
3419    fn map_try<F, U, E>(self, f: F) -> Result<Option<U>, E>
3420    where
3421        F: FnOnce(T) -> Result<U, E>,
3422    {
3423        if let Some(v) = self {
3424            f(v).map(Some)
3425        } else {
3426            Ok(None)
3427        }
3428    }
3429
3430    fn and_then_try<F, U, E>(self, f: F) -> Result<Option<U>, E>
3431    where
3432        F: FnOnce(T) -> Result<Option<U>, E>,
3433    {
3434        if let Some(v) = self {
3435            match f(v) {
3436                Ok(inner) => Ok(inner),
3437                Err(error) => Err(error),
3438            }
3439        } else {
3440            Ok(None)
3441        }
3442    }
3443
3444    fn or_else_try<F, U>(self, f: F) -> Result<Option<T>, U>
3445    where
3446        F: FnOnce() -> Result<Option<T>, U>,
3447    {
3448        if self.is_none() {
3449            f()
3450        } else {
3451            Ok(self)
3452        }
3453    }
3454}
3455
3456trait GenericsExt {
3457    /// Get index of `GenericParam::Type` ignoring other generic param types.
3458    fn get_generic_type_param_index(&self, type_tree: &TypeTree) -> Option<usize>;
3459}
3460
3461impl GenericsExt for &syn::Generics {
3462    fn get_generic_type_param_index(&self, type_tree: &TypeTree) -> Option<usize> {
3463        let ident = &type_tree
3464            .path
3465            .as_ref()
3466            .expect("TypeTree of generic object must have a path")
3467            .segments
3468            .last()
3469            .expect("Generic object path must have at least one segment")
3470            .ident;
3471
3472        self.params
3473            .iter()
3474            .filter(|generic| matches!(generic, GenericParam::Type(_)))
3475            .enumerate()
3476            .find_map(|(index, generic)| {
3477                if matches!(generic, GenericParam::Type(ty) if ty.ident == *ident) {
3478                    Some(index)
3479                } else {
3480                    None
3481                }
3482            })
3483    }
3484}
3485
3486trait AttributesExt {
3487    fn has_deprecated(&self) -> bool;
3488}
3489
3490impl AttributesExt for Vec<syn::Attribute> {
3491    fn has_deprecated(&self) -> bool {
3492        let this = &**self;
3493        this.has_deprecated()
3494    }
3495}
3496
3497impl AttributesExt for &[syn::Attribute] {
3498    fn has_deprecated(&self) -> bool {
3499        self.iter().any(|attr| {
3500            matches!(attr.path().get_ident(), Some(ident) if &*ident.to_string() == "deprecated")
3501        })
3502    }
3503}
3504
3505#[cfg(test)]
3506mod tests {
3507    use super::*;
3508
3509    #[test]
3510    fn diagnostics_ordering_help_comes_before_note() {
3511        let diagnostics = Diagnostics::new("this an error")
3512            .note("you could do this to solve the error")
3513            .help("try this thing");
3514
3515        let tokens = diagnostics.into_token_stream();
3516
3517        let expected_tokens = quote::quote!(::core::compile_error!(
3518            "this an error\n\nhelp = try this thing\nnote = you could do this to solve the error"
3519        ););
3520
3521        assert_eq!(tokens.to_string(), expected_tokens.to_string());
3522    }
3523}
3524
3525/// Parsing utils
3526mod parse_utils {
3527    use std::fmt::Display;
3528
3529    use proc_macro2::{Group, Ident, TokenStream};
3530    use quote::{quote, ToTokens};
3531    use syn::{
3532        parenthesized,
3533        parse::{Parse, ParseStream},
3534        punctuated::Punctuated,
3535        spanned::Spanned,
3536        token::Comma,
3537        Error, Expr, ExprPath, LitBool, LitStr, Token,
3538    };
3539
3540    #[cfg_attr(feature = "debug", derive(Debug))]
3541    #[derive(Clone)]
3542    pub enum LitStrOrExpr {
3543        LitStr(LitStr),
3544        Expr(Expr),
3545    }
3546
3547    impl From<String> for LitStrOrExpr {
3548        fn from(value: String) -> Self {
3549            Self::LitStr(LitStr::new(&value, proc_macro2::Span::call_site()))
3550        }
3551    }
3552
3553    impl LitStrOrExpr {
3554        pub(crate) fn is_empty_litstr(&self) -> bool {
3555            matches!(self, Self::LitStr(s) if s.value().is_empty())
3556        }
3557    }
3558
3559    impl Default for LitStrOrExpr {
3560        fn default() -> Self {
3561            Self::LitStr(LitStr::new("", proc_macro2::Span::call_site()))
3562        }
3563    }
3564
3565    impl Parse for LitStrOrExpr {
3566        fn parse(input: ParseStream) -> syn::Result<Self> {
3567            if input.peek(LitStr) {
3568                Ok::<LitStrOrExpr, Error>(LitStrOrExpr::LitStr(input.parse::<LitStr>()?))
3569            } else {
3570                Ok(LitStrOrExpr::Expr(input.parse::<Expr>()?))
3571            }
3572        }
3573    }
3574
3575    impl ToTokens for LitStrOrExpr {
3576        fn to_tokens(&self, tokens: &mut TokenStream) {
3577            match self {
3578                Self::LitStr(str) => str.to_tokens(tokens),
3579                Self::Expr(expr) => expr.to_tokens(tokens),
3580            }
3581        }
3582    }
3583
3584    impl Display for LitStrOrExpr {
3585        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3586            match self {
3587                Self::LitStr(str) => write!(f, "{str}", str = str.value()),
3588                Self::Expr(expr) => write!(f, "{expr}", expr = expr.into_token_stream()),
3589            }
3590        }
3591    }
3592
3593    pub fn parse_next<T: FnOnce() -> Result<R, syn::Error>, R: Sized>(
3594        input: ParseStream,
3595        next: T,
3596    ) -> Result<R, syn::Error> {
3597        input.parse::<Token![=]>()?;
3598        next()
3599    }
3600
3601    pub fn parse_next_literal_str(input: ParseStream) -> syn::Result<String> {
3602        Ok(parse_next(input, || input.parse::<LitStr>())?.value())
3603    }
3604
3605    pub fn parse_next_literal_str_or_expr(input: ParseStream) -> syn::Result<LitStrOrExpr> {
3606        parse_next(input, || LitStrOrExpr::parse(input)).map_err(|error| {
3607            syn::Error::new(
3608                error.span(),
3609                format!("expected literal string or expression argument: {error}"),
3610            )
3611        })
3612    }
3613
3614    pub fn parse_groups_collect<T, R>(input: ParseStream) -> syn::Result<R>
3615    where
3616        T: Sized,
3617        T: Parse,
3618        R: FromIterator<T>,
3619    {
3620        Punctuated::<Group, Comma>::parse_terminated(input).and_then(|groups| {
3621            groups
3622                .into_iter()
3623                .map(|group| syn::parse2::<T>(group.stream()))
3624                .collect::<syn::Result<R>>()
3625        })
3626    }
3627
3628    pub fn parse_parethesized_terminated<T: Parse, S: Parse>(
3629        input: ParseStream,
3630    ) -> syn::Result<Punctuated<T, S>> {
3631        let group;
3632        syn::parenthesized!(group in input);
3633        Punctuated::parse_terminated(&group)
3634    }
3635
3636    pub fn parse_comma_separated_within_parenthesis_with<T>(
3637        input: ParseStream,
3638        with: fn(ParseStream) -> syn::Result<T>,
3639    ) -> syn::Result<Punctuated<T, Comma>>
3640    where
3641        T: Parse,
3642    {
3643        let content;
3644        parenthesized!(content in input);
3645        Punctuated::<T, Comma>::parse_terminated_with(&content, with)
3646    }
3647
3648    pub fn parse_comma_separated_within_parenthesis<T>(
3649        input: ParseStream,
3650    ) -> syn::Result<Punctuated<T, Comma>>
3651    where
3652        T: Parse,
3653    {
3654        let content;
3655        parenthesized!(content in input);
3656        Punctuated::<T, Comma>::parse_terminated(&content)
3657    }
3658
3659    pub fn parse_bool_or_true(input: ParseStream) -> syn::Result<bool> {
3660        if input.peek(Token![=]) && input.peek2(LitBool) {
3661            input.parse::<Token![=]>()?;
3662
3663            Ok(input.parse::<LitBool>()?.value())
3664        } else {
3665            Ok(true)
3666        }
3667    }
3668
3669    /// Parse `json!(...)` as a [`TokenStream`].
3670    pub fn parse_json_token_stream(input: ParseStream) -> syn::Result<TokenStream> {
3671        if input.peek(syn::Ident) && input.peek2(Token![!]) {
3672            input.parse::<Ident>().and_then(|ident| {
3673                if ident != "json" {
3674                    return Err(Error::new(
3675                        ident.span(),
3676                        format!("unexpected token {ident}, expected: json!(...)"),
3677                    ));
3678                }
3679
3680                Ok(ident)
3681            })?;
3682            input.parse::<Token![!]>()?;
3683
3684            Ok(input.parse::<Group>()?.stream())
3685        } else {
3686            Err(Error::new(
3687                input.span(),
3688                "unexpected token, expected json!(...)",
3689            ))
3690        }
3691    }
3692
3693    #[cfg_attr(feature = "debug", derive(Debug))]
3694    #[derive(Clone)]
3695    pub enum LitBoolOrExprPath {
3696        LitBool(LitBool),
3697        ExprPath(ExprPath),
3698    }
3699
3700    impl From<bool> for LitBoolOrExprPath {
3701        fn from(value: bool) -> Self {
3702            Self::LitBool(LitBool::new(value, proc_macro2::Span::call_site()))
3703        }
3704    }
3705
3706    impl Default for LitBoolOrExprPath {
3707        fn default() -> Self {
3708            Self::LitBool(LitBool::new(false, proc_macro2::Span::call_site()))
3709        }
3710    }
3711
3712    impl Parse for LitBoolOrExprPath {
3713        fn parse(input: ParseStream) -> syn::Result<Self> {
3714            if input.peek(LitBool) {
3715                Ok(LitBoolOrExprPath::LitBool(input.parse::<LitBool>()?))
3716            } else {
3717                let expr = input.parse::<Expr>()?;
3718
3719                match expr {
3720                    Expr::Path(expr_path) => Ok(LitBoolOrExprPath::ExprPath(expr_path)),
3721                    _ => Err(syn::Error::new(
3722                        expr.span(),
3723                        format!(
3724                            "expected literal bool or path to a function that returns bool, found: {}",
3725                            quote! {#expr}
3726                        ),
3727                    )),
3728                }
3729            }
3730        }
3731    }
3732
3733    impl ToTokens for LitBoolOrExprPath {
3734        fn to_tokens(&self, tokens: &mut TokenStream) {
3735            match self {
3736                Self::LitBool(bool) => bool.to_tokens(tokens),
3737                Self::ExprPath(call) => call.to_tokens(tokens),
3738            }
3739        }
3740    }
3741}