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 summary: Option<String>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
44 pub description: Option<String>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub terms_of_service: Option<String>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
54 pub contact: Option<Contact>,
55
56 #[serde(skip_serializing_if = "Option::is_none")]
60 pub license: Option<License>,
61
62 pub version: String,
64
65 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
67 pub extensions: PropMap<String, serde_json::Value>,
68}
69
70impl Info {
71 #[must_use]
83 pub fn new(title: impl Into<String>, version: impl Into<String>) -> Self {
84 Self {
85 title: title.into(),
86 version: version.into(),
87 ..Default::default()
88 }
89 }
90 #[must_use]
92 pub fn title<I: Into<String>>(mut self, title: I) -> Self {
93 self.title = title.into();
94 self
95 }
96
97 #[must_use]
99 pub fn version<I: Into<String>>(mut self, version: I) -> Self {
100 self.version = version.into();
101 self
102 }
103
104 #[must_use]
106 pub fn summary<S: Into<String>>(mut self, summary: S) -> Self {
107 self.summary = Some(summary.into());
108 self
109 }
110
111 #[must_use]
113 pub fn description<S: Into<String>>(mut self, description: S) -> Self {
114 self.description = Some(description.into());
115 self
116 }
117
118 #[must_use]
120 pub fn terms_of_service<S: Into<String>>(mut self, terms_of_service: S) -> Self {
121 self.terms_of_service = Some(terms_of_service.into());
122 self
123 }
124
125 #[must_use]
127 pub fn contact(mut self, contact: Contact) -> Self {
128 self.contact = Some(contact);
129 self
130 }
131
132 #[must_use]
134 pub fn license(mut self, license: License) -> Self {
135 self.license = Some(license);
136 self
137 }
138}
139
140#[non_exhaustive]
146#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
147#[serde(rename_all = "camelCase")]
148pub struct Contact {
149 #[serde(skip_serializing_if = "Option::is_none")]
151 pub name: Option<String>,
152
153 #[serde(skip_serializing_if = "Option::is_none")]
155 pub url: Option<String>,
156
157 #[serde(skip_serializing_if = "Option::is_none")]
159 pub email: Option<String>,
160
161 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
163 pub extensions: PropMap<String, serde_json::Value>,
164}
165
166impl Contact {
167 #[must_use]
169 pub fn new() -> Self {
170 Default::default()
171 }
172 #[must_use]
174 pub fn name<S: Into<String>>(mut self, name: S) -> Self {
175 self.name = Some(name.into());
176 self
177 }
178
179 #[must_use]
181 pub fn url<S: Into<String>>(mut self, url: S) -> Self {
182 self.url = Some(url.into());
183 self
184 }
185
186 #[must_use]
188 pub fn email<S: Into<String>>(mut self, email: S) -> Self {
189 self.email = Some(email.into());
190 self
191 }
192
193 #[must_use]
195 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
196 self.extensions = extensions;
197 self
198 }
199}
200
201#[non_exhaustive]
205#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, Debug)]
206#[serde(rename_all = "camelCase")]
207pub struct License {
208 pub name: String,
210
211 #[serde(skip_serializing_if = "Option::is_none")]
213 pub url: Option<String>,
214
215 #[serde(skip_serializing_if = "Option::is_none")]
220 pub identifier: Option<String>,
221
222 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
224 pub extensions: PropMap<String, serde_json::Value>,
225}
226
227impl License {
228 #[must_use]
232 pub fn new<S: Into<String>>(name: S) -> Self {
233 Self {
234 name: name.into(),
235 ..Default::default()
236 }
237 }
238 #[must_use]
240 pub fn name<S: Into<String>>(mut self, name: S) -> Self {
241 self.name = name.into();
242 self
243 }
244
245 #[must_use]
247 pub fn url<S: Into<String>>(mut self, url: S) -> Self {
248 self.url = Some(url.into());
249 self.identifier = None;
250 self
251 }
252
253 #[must_use]
258 pub fn identifier<S: Into<String>>(mut self, identifier: S) -> Self {
259 self.identifier = Some(identifier.into());
260 self.url = None;
261 self
262 }
263
264 #[must_use]
266 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
267 self.extensions = extensions;
268 self
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use assert_json_diff::assert_json_eq;
275 use serde_json::json;
276
277 use super::Contact;
278 use crate::License;
279
280 #[test]
281 fn build_contact() {
282 let contact = Contact::new();
283
284 assert!(contact.name.is_none());
285 assert!(contact.url.is_none());
286 assert!(contact.email.is_none());
287
288 let contact = contact
289 .name("salvo api")
290 .url("https://github.com/salvo-rs/salvo")
291 .email("salvo.rs@some.mail.com");
292 assert_json_eq!(
293 contact,
294 json!({
295 "name": "salvo api",
296 "url": "https://github.com/salvo-rs/salvo",
297 "email": "salvo.rs@some.mail.com"
298 })
299 );
300 }
301
302 #[test]
303 fn test_license_set_name() {
304 let license = License::default();
305 assert!(license.name.is_empty());
306
307 let license = license.name("MIT");
308 assert_json_eq!(license, json!({ "name": "MIT" }));
309 }
310}