paperclip_core/v3/models/
openapi.rs

1use super::v2;
2
3impl From<v2::DefaultApiRaw> for openapiv3::OpenAPI {
4    fn from(v2: v2::DefaultApiRaw) -> Self {
5        let mut spec = openapiv3::OpenAPI {
6            openapi: "3.0.0".into(),
7            tags: v2.tags.iter().cloned().map(From::from).collect(),
8            info: v2.info.clone().into(),
9            servers: openapi3_servers(v2.schemes, v2.host, v2.base_path),
10            external_docs: v2.external_docs.map(From::from),
11            ..Default::default()
12        };
13
14        let mut components = openapiv3::Components::default();
15        for (name, scheme) in v2.security_definitions {
16            components
17                .security_schemes
18                .insert(name, openapiv3::ReferenceOr::Item(scheme.into()));
19        }
20        components.responses = v2.responses.iter().fold(Default::default(), |mut i, b| {
21            i.insert(b.0.to_string(), b.1.clone().into());
22            i
23        });
24        spec.extensions = v2
25            .extensions
26            .into_iter()
27            .fold(Default::default(), |mut i, (k, v)| {
28                i.insert(k, v);
29                i
30            });
31        spec.paths = openapiv3::Paths {
32            paths: v2.paths.iter().fold(Default::default(), |mut i, b| {
33                i.insert(
34                    b.0.to_string(),
35                    openapiv3::ReferenceOr::Item(b.1.clone().into()),
36                );
37                i
38            }),
39            ..Default::default()
40        };
41
42        components.schemas = v2.definitions.iter().fold(Default::default(), |mut i, b| {
43            i.insert(b.0.to_string(), b.1.clone().into());
44            i
45        });
46        spec.components = Some(components);
47
48        spec
49    }
50}
51
52fn openapi3_servers(
53    schemes: std::collections::BTreeSet<v2::OperationProtocol>,
54    host: Option<String>,
55    base: Option<String>,
56) -> Vec<openapiv3::Server> {
57    if schemes.is_empty() && host.is_none() && base.is_none() {
58        vec![]
59    } else if let Some(host) = host {
60        if !schemes.is_empty() {
61            schemes
62                .into_iter()
63                .map(|scheme| {
64                    let scheme_str = match scheme {
65                        v2::OperationProtocol::Http => "http",
66                        v2::OperationProtocol::Https => "https",
67                        v2::OperationProtocol::Ws => "ws",
68                        v2::OperationProtocol::Wss => "wss",
69                    };
70                    openapiv3::Server {
71                        url: format!("{}://{}{}", scheme_str, host, base.as_deref().unwrap_or("")),
72                        description: None,
73                        variables: None,
74                        extensions: Default::default(),
75                    }
76                })
77                .collect()
78        } else {
79            vec![openapiv3::Server {
80                url: format!("//{}{}", host, base.as_deref().unwrap_or("")),
81                description: None,
82                variables: None,
83                extensions: Default::default(),
84            }]
85        }
86    } else {
87        vec![openapiv3::Server {
88            url: base.unwrap_or_else(|| "/".to_string()),
89            description: None,
90            variables: None,
91            extensions: Default::default(),
92        }]
93    }
94}