1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use std::collections::{BTreeMap, HashMap};
use serde::{
ser::{SerializeMap, SerializeStruct},
Serialize, Serializer,
};
use crate::registry::{
MetaApi, MetaInfo, MetaPath, MetaResponses, MetaSchema, MetaSchemaRef, MetaSecurityScheme,
MetaServer, Registry,
};
const OPENAPI_VERSION: &str = "3.0.0";
impl<'a> Serialize for MetaSchemaRef {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
MetaSchemaRef::Inline(schema) => schema.serialize(serializer),
MetaSchemaRef::Reference(name) => {
let mut s = serializer.serialize_struct("MetaSchemaRef", 1)?;
s.serialize_field("$ref", &format!("#/components/schemas/{}", name))?;
s.end()
}
}
}
}
struct PathMap<'a>(&'a [MetaApi]);
impl<'a> Serialize for PathMap<'a> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut s = serializer.serialize_map(Some(self.0.len()))?;
for api in self.0 {
for path in &api.paths {
s.serialize_entry(path.path, path)?;
}
}
s.end()
}
}
impl Serialize for MetaPath {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut s = serializer.serialize_map(None)?;
for operation in &self.operations {
s.serialize_entry(&operation.method.to_string().to_lowercase(), operation)?;
}
s.end()
}
}
impl Serialize for MetaResponses {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut s = serializer.serialize_map(None)?;
for resp in &self.responses {
match resp.status {
Some(status) => s.serialize_entry(&format!("{}", status), resp)?,
None => s.serialize_entry("default", resp)?,
}
}
s.end()
}
}
pub(crate) struct Document<'a> {
pub(crate) info: Option<&'a MetaInfo>,
pub(crate) servers: &'a [MetaServer],
pub(crate) apis: &'a [MetaApi],
pub(crate) registry: &'a Registry,
}
impl<'a> Serialize for Document<'a> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
#[derive(Serialize)]
struct Components<'a> {
schemas: &'a HashMap<&'static str, MetaSchema>,
#[serde(rename = "securitySchemes")]
security_schemes: &'a BTreeMap<&'static str, MetaSecurityScheme>,
}
let mut s = serializer.serialize_struct("OpenAPI", 6)?;
s.serialize_field("openapi", OPENAPI_VERSION)?;
s.serialize_field("info", &self.info)?;
s.serialize_field("servers", self.servers)?;
s.serialize_field("tags", &self.registry.tags)?;
s.serialize_field("paths", &PathMap(self.apis))?;
s.serialize_field(
"components",
&Components {
schemas: &self.registry.schemas,
security_schemes: &self.registry.security_schemes,
},
)?;
s.end()
}
}