1use std::cmp::Ordering;
44use std::collections::BTreeSet;
45use std::ops::{Deref, DerefMut};
46
47use serde::{Deserialize, Serialize};
48
49use crate::PropMap;
50
51#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Debug)]
52
53pub struct Servers(pub BTreeSet<Server>);
55impl Deref for Servers {
56 type Target = BTreeSet<Server>;
57
58 fn deref(&self) -> &Self::Target {
59 &self.0
60 }
61}
62impl DerefMut for Servers {
63 fn deref_mut(&mut self) -> &mut Self::Target {
64 &mut self.0
65 }
66}
67impl IntoIterator for Servers {
68 type Item = Server;
69 type IntoIter = <BTreeSet<Server> as IntoIterator>::IntoIter;
70
71 fn into_iter(self) -> Self::IntoIter {
72 self.0.into_iter()
73 }
74}
75impl Servers {
76 #[must_use]
78 pub fn new() -> Self {
79 Default::default()
80 }
81 #[must_use]
83 pub fn is_empty(&self) -> bool {
84 self.0.is_empty()
85 }
86 #[must_use]
88 pub fn server<S: Into<Server>>(mut self, server: S) -> Self {
89 self.insert(server);
90 self
91 }
92 pub fn insert<S: Into<Server>>(&mut self, server: S) {
94 let server = server.into();
95 let exist_server = self.0.iter().find(|s| s.url == server.url).cloned();
96 if let Some(mut exist_server) = exist_server {
97 let Server {
98 description,
99 mut variables,
100 extensions,
101 ..
102 } = server;
103 exist_server.variables.append(&mut variables);
104 if description.is_some() {
105 exist_server.description = description;
106 }
107 exist_server.extensions.extend(extensions);
108 self.0.remove(&exist_server);
109 self.0.insert(exist_server);
110 } else {
111 self.0.insert(server);
112 }
113 }
114
115 pub fn append(&mut self, other: &mut Self) {
120 let servers = std::mem::take(&mut other.0);
121 for server in servers {
122 self.insert(server);
123 }
124 }
125 pub fn extend<I>(&mut self, iter: I)
127 where
128 I: IntoIterator<Item = Server>,
129 {
130 for server in iter.into_iter() {
131 self.insert(server);
132 }
133 }
134}
135
136#[non_exhaustive]
144#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
145#[serde(rename_all = "camelCase")]
146pub struct Server {
147 pub url: String,
152
153 #[serde(skip_serializing_if = "Option::is_none")]
156 pub description: Option<String>,
157
158 #[serde(skip_serializing_if = "ServerVariables::is_empty")]
160 pub variables: ServerVariables,
161
162 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
164 pub extensions: PropMap<String, serde_json::Value>,
165}
166
167impl Ord for Server {
168 fn cmp(&self, other: &Self) -> Ordering {
169 self.url.cmp(&other.url)
170 }
171}
172impl PartialOrd for Server {
173 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
174 Some(self.cmp(other))
175 }
176}
177
178impl Server {
179 #[must_use]
203 pub fn new<S: Into<String>>(url: S) -> Self {
204 Self {
205 url: url.into(),
206 ..Default::default()
207 }
208 }
209 #[must_use]
211 pub fn url<U: Into<String>>(mut self, url: U) -> Self {
212 self.url = url.into();
213 self
214 }
215
216 #[must_use]
218 pub fn description<S: Into<String>>(mut self, description: S) -> Self {
219 self.description = Some(description.into());
220 self
221 }
222
223 #[must_use]
231 pub fn add_variable<N: Into<String>, V: Into<ServerVariable>>(
232 mut self,
233 name: N,
234 variable: V,
235 ) -> Self {
236 self.variables.insert(name.into(), variable.into());
237 self
238 }
239
240 #[must_use]
242 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
243 self.extensions = extensions;
244 self
245 }
246}
247
248#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, Debug)]
250pub struct ServerVariables(pub PropMap<String, ServerVariable>);
251impl Deref for ServerVariables {
252 type Target = PropMap<String, ServerVariable>;
253
254 fn deref(&self) -> &Self::Target {
255 &self.0
256 }
257}
258impl DerefMut for ServerVariables {
259 fn deref_mut(&mut self) -> &mut Self::Target {
260 &mut self.0
261 }
262}
263impl ServerVariables {
264 #[must_use]
267 pub fn new() -> Self {
268 Default::default()
269 }
270 #[must_use]
272 pub fn is_empty(&self) -> bool {
273 self.0.is_empty()
274 }
275 #[must_use]
277 pub fn server_variable<K: Into<String>, V: Into<ServerVariable>>(
278 mut self,
279 key: K,
280 variable: V,
281 ) -> Self {
282 self.insert(key, variable);
283 self
284 }
285 pub fn insert<K: Into<String>, V: Into<ServerVariable>>(&mut self, key: K, variable: V) {
287 let key = key.into();
288 let mut variable = variable.into();
289 self.0
290 .entry(key)
291 .and_modify(|item| {
292 if variable.description.is_some() {
293 item.description = variable.description.take();
294 }
295 item.default_value.clone_from(&variable.default_value);
296 item.enum_values.append(&mut variable.enum_values);
297 })
298 .or_insert(variable);
299 }
300 pub fn append(&mut self, other: &mut Self) {
305 let variables = std::mem::take(&mut other.0);
306 for (key, variable) in variables {
307 self.insert(key, variable);
308 }
309 }
310 pub fn extend<I>(&mut self, iter: I)
312 where
313 I: IntoIterator<Item = (String, ServerVariable)>,
314 {
315 for (key, variable) in iter.into_iter() {
316 self.insert(key, variable);
317 }
318 }
319}
320
321#[non_exhaustive]
326#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
327pub struct ServerVariable {
328 #[serde(rename = "default")]
330 default_value: String,
331
332 #[serde(skip_serializing_if = "Option::is_none")]
334 description: Option<String>,
335
336 #[serde(rename = "enum", skip_serializing_if = "BTreeSet::is_empty")]
339 enum_values: BTreeSet<String>,
340
341 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
343 pub extensions: PropMap<String, serde_json::Value>,
344}
345
346impl ServerVariable {
347 #[must_use]
350 pub fn new() -> Self {
351 Default::default()
352 }
353 #[must_use]
355 pub fn default_value<S: Into<String>>(mut self, default_value: S) -> Self {
356 self.default_value = default_value.into();
357 self
358 }
359
360 #[must_use]
362 pub fn description<S: Into<String>>(mut self, description: S) -> Self {
363 self.description = Some(description.into());
364 self
365 }
366
367 #[must_use]
369 pub fn enum_values<I: IntoIterator<Item = V>, V: Into<String>>(
370 mut self,
371 enum_values: I,
372 ) -> Self {
373 self.enum_values = enum_values.into_iter().map(|value| value.into()).collect();
374 self
375 }
376
377 #[must_use]
379 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
380 self.extensions = extensions;
381 self
382 }
383}
384
385#[cfg(test)]
386mod tests {
387 use assert_json_diff::assert_json_eq;
388 use serde_json::json;
389
390 use super::*;
391
392 macro_rules! test_fn {
393 ($name:ident : $schema:expr; $expected:literal) => {
394 #[test]
395 fn $name() {
396 let value = serde_json::to_value($schema).unwrap();
397 let expected_value: serde_json::Value = serde_json::from_str($expected).unwrap();
398
399 assert_eq!(
400 value,
401 expected_value,
402 "testing serializing \"{}\": \nactual:\n{}\nexpected:\n{}",
403 stringify!($name),
404 value,
405 expected_value
406 );
407
408 println!("{}", &serde_json::to_string_pretty(&$schema).unwrap());
409 }
410 };
411 }
412
413 test_fn! {
414 create_server_with_builder_and_variable_substitution:
415 Server::new("/api/{version}/{username}")
416 .add_variable(
417 "version",
418 ServerVariable::new()
419 .enum_values(["v1", "v2"])
420 .description("api version")
421 .default_value("v1")
422 )
423 .add_variable(
424 "username",
425 ServerVariable::new().default_value("the_user")
426 );
427 r###"{
428 "url": "/api/{version}/{username}",
429 "variables": {
430 "version": {
431 "enum": ["v1", "v2"],
432 "default": "v1",
433 "description": "api version"
434 },
435 "username": {
436 "default": "the_user"
437 }
438 }
439}"###
440 }
441
442 #[test]
443 fn test_servers_is_empty() {
444 let servers = Servers::new();
445 assert!(servers.is_empty());
446 }
447
448 #[test]
449 fn test_servers_server() {
450 let servers = Servers::new();
451 let server = Server::new("/api/v1").description("api v1");
452 let servers = servers.server(server);
453 assert!(servers.len() == 1);
454 }
455
456 #[test]
457 fn test_servers_insert() {
458 let mut servers = Servers::new();
459 let server = Server::new("/api/v1").description("api v1");
460 servers.insert(server);
461 assert!(servers.len() == 1);
462 }
463
464 #[test]
465 fn test_servers_insert_existed_server() {
466 let mut servers = Servers::new();
467 let server1 = Server::new("/api/v1".to_owned())
468 .description("api v1")
469 .add_variable("key1", ServerVariable::new());
470 servers.insert(server1);
471
472 let server2 = Server::new("/api/v1".to_owned())
473 .description("api v1 new description")
474 .add_variable("key2", ServerVariable::new());
475 servers.insert(server2);
476
477 assert!(servers.len() == 1);
478 assert_json_eq!(
479 servers,
480 json!([
481 {
482 "description": "api v1 new description",
483 "url": "/api/v1",
484 "variables": {
485 "key1": {
486 "default": ""
487 },
488 "key2": {
489 "default": ""
490 }
491 }
492 }
493 ])
494 )
495 }
496
497 #[test]
498 fn test_servers_append() {
499 let mut servers = Servers::new();
500
501 let server = Server::new("/api/v1").description("api v1");
502 let mut other_servers: Servers = Servers::new();
503
504 other_servers.insert(server);
505 assert!(!other_servers.is_empty());
506
507 servers.append(&mut other_servers);
508 assert!(!servers.is_empty());
509 }
510
511 #[test]
512 fn test_servers_extend() {
513 let mut servers = Servers::new();
514
515 let server = Server::new("/api/v1").description("api v1");
516 let mut other_servers: Servers = Servers::new();
517
518 other_servers.insert(server);
519 assert!(!other_servers.is_empty());
520
521 servers.extend(other_servers);
522 assert!(!servers.is_empty());
523 }
524
525 #[test]
526 fn test_servers_deref() {
527 let mut servers = Servers::new();
528 let server = Server::new("/api/v1").description("api v1");
529 servers.insert(server);
530 assert!(servers.len() == 1);
531 assert!(servers.deref().len() == 1);
532
533 servers.deref_mut().clear();
534 assert!(servers.is_empty());
535 }
536
537 #[test]
538 fn test_server_set_url() {
539 let server = Server::new("/api/v1");
540 assert_eq!(server.url, "/api/v1");
541
542 let server = server.url("/new/api/v1");
543 assert_eq!(server.url, "/new/api/v1");
544 }
545
546 #[test]
547 fn test_server_cmp() {
548 let server_a = Server::new("/api/v1");
549 let server_b = Server::new("/api/v2");
550 assert!(server_a < server_b);
551 }
552
553 #[test]
554 fn test_server_variables_is_empty() {
555 let server_variables = ServerVariables::new();
556 assert!(server_variables.is_empty());
557 }
558
559 #[test]
560 fn test_server_variables_server_variable() {
561 let server_variables = ServerVariables::new();
562 let variable = ServerVariable::new();
563 let server_variables = server_variables.server_variable("key", variable);
564
565 assert!(!server_variables.is_empty());
566 }
567
568 #[test]
569 fn test_server_variables_insert() {
570 let mut server_variables = ServerVariables::new();
571 let variable = ServerVariable::new();
572 server_variables.insert("key", variable);
573 assert!(server_variables.len() == 1);
574
575 let new_variable = ServerVariable::new().description("description");
576 server_variables.insert("key", new_variable);
577 assert!(server_variables.len() == 1);
578 }
579
580 #[test]
581 fn test_server_variables_append() {
582 let mut server_variables = ServerVariables::new();
583
584 let mut other_server_variables = ServerVariables::new();
585 let variable = ServerVariable::new();
586 other_server_variables.insert("key", variable);
587
588 server_variables.append(&mut other_server_variables);
589 assert!(server_variables.len() == 1);
590 }
591
592 #[test]
593 fn test_server_variables_extend() {
594 let mut server_variables = ServerVariables::new();
595
596 let mut other_server_variables = ServerVariables::new();
597 let variable = ServerVariable::new();
598 other_server_variables.insert("key", variable);
599
600 server_variables.extend(other_server_variables.0);
601 assert!(server_variables.len() == 1);
602 }
603
604 #[test]
605 fn test_server_variables_deref() {
606 let mut server_variables = ServerVariables::new();
607
608 let variable = ServerVariable::new().default_value("default_value");
609 server_variables.insert("key", variable);
610
611 assert!(!server_variables.is_empty());
612 assert!(server_variables.deref().len() == 1);
613
614 server_variables.deref_mut().clear();
615 assert!(server_variables.is_empty());
616 }
617}