openapiv3_1/
info.rs

1//! Implements [OpenAPI Metadata][info] types.
2//!
3//! [info]: <https://spec.openapis.org/oas/latest.html#info-object>
4
5use serde_derive::{Deserialize, Serialize};
6
7use super::extensions::Extensions;
8
9/// OpenAPI [Info][info] object represents metadata of the API.
10///
11/// You can use [`Info::new`] to construct a new [`Info`] object or alternatively use [`Info::builder`]
12/// to construct a new [`Info`] with chainable configuration methods.
13///
14/// [info]: <https://spec.openapis.org/oas/latest.html#info-object>
15#[non_exhaustive]
16#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, bon::Builder)]
17#[cfg_attr(feature = "debug", derive(Debug))]
18#[serde(rename_all = "camelCase")]
19#[builder(on(_, into))]
20pub struct Info {
21    /// Title of the API.
22    pub title: String,
23
24    /// Optional description of the API.
25    ///
26    /// Value supports markdown syntax.
27    #[serde(skip_serializing_if = "Option::is_none", default)]
28    pub description: Option<String>,
29
30    /// Optional url for terms of service.
31    #[serde(skip_serializing_if = "Option::is_none", default)]
32    pub terms_of_service: Option<String>,
33
34    /// Contact information of exposed API.
35    ///
36    /// See more details at: <https://spec.openapis.org/oas/latest.html#contact-object>.
37    #[serde(skip_serializing_if = "Option::is_none", default)]
38    pub contact: Option<Contact>,
39
40    /// License of the API.
41    ///
42    /// See more details at: <https://spec.openapis.org/oas/latest.html#license-object>.
43    #[serde(skip_serializing_if = "Option::is_none", default)]
44    pub license: Option<License>,
45
46    /// Document version typically the API version.
47    pub version: String,
48
49    /// Optional extensions "x-something".
50    #[serde(skip_serializing_if = "Option::is_none", default, flatten)]
51    pub extensions: Option<Extensions>,
52}
53
54impl<S: info_builder::IsComplete> From<InfoBuilder<S>> for Info {
55    fn from(builder: InfoBuilder<S>) -> Self {
56        builder.build()
57    }
58}
59
60impl Info {
61    /// Construct a new [`Info`] object.
62    ///
63    /// This function accepts two arguments. One which is the title of the API and two the
64    /// version of the api document typically the API version.
65    ///
66    /// # Examples
67    ///
68    /// ```rust
69    /// # use openapiv3_1::Info;
70    /// let info = Info::new("Pet api", "1.1.0");
71    /// ```
72    pub fn new<S: Into<String>>(title: S, version: S) -> Self {
73        Self {
74            title: title.into(),
75            version: version.into(),
76            ..Default::default()
77        }
78    }
79}
80
81/// OpenAPI [`Contact`][contact] object represents metadata of the API.
82///
83/// You can use [`Contact::new`] to construct a new [`Contact`] object or alternatively use [`Contact::builder`]
84/// to construct a new [`Contact`] with chainable configuration methods.
85///
86/// [contact]: <https://spec.openapis.org/oas/latest.html#contact-object>
87#[non_exhaustive]
88#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, bon::Builder)]
89#[cfg_attr(feature = "debug", derive(Debug))]
90#[serde(rename_all = "camelCase")]
91#[builder(on(_, into))]
92pub struct Contact {
93    /// Identifying name of the contact person or organization of the API.
94    #[serde(skip_serializing_if = "Option::is_none", default)]
95    pub name: Option<String>,
96
97    /// Url pointing to contact information of the API.
98    #[serde(skip_serializing_if = "Option::is_none", default)]
99    pub url: Option<String>,
100
101    /// Email of the contact person or the organization of the API.
102    #[serde(skip_serializing_if = "Option::is_none", default)]
103    pub email: Option<String>,
104
105    /// Optional extensions "x-something".
106    #[serde(skip_serializing_if = "Option::is_none", default, flatten)]
107    pub extensions: Option<Extensions>,
108}
109
110impl Contact {
111    /// Construct a new [`Contact`].
112    pub fn new() -> Self {
113        Default::default()
114    }
115}
116
117impl<S: contact_builder::IsComplete> From<ContactBuilder<S>> for Contact {
118    fn from(builder: ContactBuilder<S>) -> Self {
119        builder.build()
120    }
121}
122
123/// OpenAPI [License][license] information of the API.
124///
125/// [license]: <https://spec.openapis.org/oas/latest.html#license-object>
126#[non_exhaustive]
127#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, bon::Builder)]
128#[cfg_attr(feature = "debug", derive(Debug))]
129#[serde(rename_all = "camelCase")]
130#[builder(on(_, into))]
131pub struct License {
132    /// Name of the license used e.g MIT or Apache-2.0.
133    pub name: String,
134
135    /// Optional url pointing to the license.
136    #[serde(skip_serializing_if = "Option::is_none", default)]
137    pub url: Option<String>,
138
139    /// An [SPDX-Licenses][spdx_licence] expression for the API. The _`identifier`_ field
140    /// is mutually exclusive of the _`url`_ field. E.g. Apache-2.0
141    ///
142    /// [spdx_licence]: <https://spdx.org/licenses/>
143    #[serde(skip_serializing_if = "Option::is_none", default)]
144    pub identifier: Option<String>,
145
146    /// Optional extensions "x-something".
147    #[serde(skip_serializing_if = "Option::is_none", default, flatten)]
148    pub extensions: Option<Extensions>,
149}
150
151impl License {
152    /// Construct a new [`License`] object.
153    ///
154    /// Function takes name of the license as an argument e.g MIT.
155    pub fn new<S: Into<String>>(name: S) -> Self {
156        Self {
157            name: name.into(),
158            ..Default::default()
159        }
160    }
161}
162
163impl<S: license_builder::IsComplete> From<LicenseBuilder<S>> for License {
164    fn from(builder: LicenseBuilder<S>) -> Self {
165        builder.build()
166    }
167}
168
169#[cfg(test)]
170#[cfg_attr(coverage_nightly, coverage(off))]
171mod tests {
172    use super::Contact;
173
174    #[test]
175    fn contact_new() {
176        let contact = Contact::new();
177
178        assert!(contact.name.is_none());
179        assert!(contact.url.is_none());
180        assert!(contact.email.is_none());
181    }
182}