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