salvo_oapi/openapi/
info.rs1use serde::{Deserialize, Serialize};
11
12use crate::PropMap;
13
14#[non_exhaustive]
28#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
29#[serde(rename_all = "camelCase")]
30pub struct Info {
31 pub title: String,
33
34 #[serde(skip_serializing_if = "Option::is_none")]
38 pub description: Option<String>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub terms_of_service: Option<String>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
48 pub contact: Option<Contact>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
54 pub license: Option<License>,
55
56 pub version: String,
58
59 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
61 pub extensions: PropMap<String, serde_json::Value>,
62}
63
64impl Info {
65 #[must_use]
77 pub fn new(title: impl Into<String>, version: impl Into<String>) -> Self {
78 Self {
79 title: title.into(),
80 version: version.into(),
81 ..Default::default()
82 }
83 }
84 #[must_use]
86 pub fn title<I: Into<String>>(mut self, title: I) -> Self {
87 self.title = title.into();
88 self
89 }
90
91 #[must_use]
93 pub fn version<I: Into<String>>(mut self, version: I) -> Self {
94 self.version = version.into();
95 self
96 }
97
98 #[must_use]
100 pub fn description<S: Into<String>>(mut self, description: S) -> Self {
101 self.description = Some(description.into());
102 self
103 }
104
105 #[must_use]
107 pub fn terms_of_service<S: Into<String>>(mut self, terms_of_service: S) -> Self {
108 self.terms_of_service = Some(terms_of_service.into());
109 self
110 }
111
112 #[must_use]
114 pub fn contact(mut self, contact: Contact) -> Self {
115 self.contact = Some(contact);
116 self
117 }
118
119 #[must_use]
121 pub fn license(mut self, license: License) -> Self {
122 self.license = Some(license);
123 self
124 }
125}
126
127#[non_exhaustive]
133#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
134#[serde(rename_all = "camelCase")]
135pub struct Contact {
136 #[serde(skip_serializing_if = "Option::is_none")]
138 pub name: Option<String>,
139
140 #[serde(skip_serializing_if = "Option::is_none")]
142 pub url: Option<String>,
143
144 #[serde(skip_serializing_if = "Option::is_none")]
146 pub email: Option<String>,
147
148 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
150 pub extensions: PropMap<String, serde_json::Value>,
151}
152
153impl Contact {
154 #[must_use]
156 pub fn new() -> Self {
157 Default::default()
158 }
159 #[must_use]
161 pub fn name<S: Into<String>>(mut self, name: S) -> Self {
162 self.name = Some(name.into());
163 self
164 }
165
166 #[must_use]
168 pub fn url<S: Into<String>>(mut self, url: S) -> Self {
169 self.url = Some(url.into());
170 self
171 }
172
173 #[must_use]
175 pub fn email<S: Into<String>>(mut self, email: S) -> Self {
176 self.email = Some(email.into());
177 self
178 }
179
180 #[must_use]
182 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
183 self.extensions = extensions;
184 self
185 }
186}
187
188#[non_exhaustive]
192#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, Debug)]
193#[serde(rename_all = "camelCase")]
194pub struct License {
195 pub name: String,
197
198 #[serde(skip_serializing_if = "Option::is_none")]
200 pub url: Option<String>,
201
202 #[serde(skip_serializing_if = "Option::is_none")]
207 pub identifier: Option<String>,
208
209 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
211 pub extensions: PropMap<String, serde_json::Value>,
212}
213
214impl License {
215 #[must_use]
219 pub fn new<S: Into<String>>(name: S) -> Self {
220 Self {
221 name: name.into(),
222 ..Default::default()
223 }
224 }
225 #[must_use]
227 pub fn name<S: Into<String>>(mut self, name: S) -> Self {
228 self.name = name.into();
229 self
230 }
231
232 #[must_use]
234 pub fn url<S: Into<String>>(mut self, url: S) -> Self {
235 self.url = Some(url.into());
236 self.identifier = None;
237 self
238 }
239
240 #[must_use]
245 pub fn identifier<S: Into<String>>(mut self, identifier: S) -> Self {
246 self.identifier = Some(identifier.into());
247 self.url = None;
248 self
249 }
250
251 #[must_use]
253 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
254 self.extensions = extensions;
255 self
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use assert_json_diff::assert_json_eq;
262 use serde_json::json;
263
264 use super::Contact;
265 use crate::License;
266
267 #[test]
268 fn build_contact() {
269 let contact = Contact::new();
270
271 assert!(contact.name.is_none());
272 assert!(contact.url.is_none());
273 assert!(contact.email.is_none());
274
275 let contact = contact
276 .name("salvo api")
277 .url("https://github.com/salvo-rs/salvo")
278 .email("salvo.rs@some.mail.com");
279 assert_json_eq!(
280 contact,
281 json!({
282 "name": "salvo api",
283 "url": "https://github.com/salvo-rs/salvo",
284 "email": "salvo.rs@some.mail.com"
285 })
286 );
287 }
288
289 #[test]
290 fn test_license_set_name() {
291 let license = License::default();
292 assert!(license.name.is_empty());
293
294 let license = license.name("MIT");
295 assert_json_eq!(license, json!({ "name": "MIT" }));
296 }
297}