1use indexmap::IndexMap;
2use serde::Deserialize;
3
4#[derive(Debug, Deserialize)]
6pub struct OpenApiSpec {
7 pub openapi: String,
8 pub info: Info,
9 #[serde(default)]
10 pub paths: IndexMap<String, PathItem>,
11 #[serde(default)]
12 pub components: Option<Components>,
13}
14
15#[derive(Debug, Deserialize)]
16pub struct Info {
17 pub title: String,
18 pub version: String,
19 #[serde(default)]
20 pub description: Option<String>,
21}
22
23#[derive(Debug, Clone, Deserialize)]
24pub struct PathItem {
25 #[serde(default)]
26 pub get: Option<Operation>,
27 #[serde(default)]
28 pub post: Option<Operation>,
29 #[serde(default)]
30 pub put: Option<Operation>,
31 #[serde(default)]
32 pub patch: Option<Operation>,
33 #[serde(default)]
34 pub delete: Option<Operation>,
35 #[serde(default)]
36 pub parameters: Vec<ParameterOrRef>,
37}
38
39impl PathItem {
40 pub fn operations(&self) -> impl Iterator<Item = (&'static str, &Operation)> {
42 [
43 ("get", &self.get),
44 ("post", &self.post),
45 ("put", &self.put),
46 ("patch", &self.patch),
47 ("delete", &self.delete),
48 ]
49 .into_iter()
50 .filter_map(|(method, op)| op.as_ref().map(|o| (method, o)))
51 }
52
53 pub fn operations_mut(&mut self) -> impl Iterator<Item = (&'static str, &mut Operation)> {
55 [
56 ("get", &mut self.get),
57 ("post", &mut self.post),
58 ("put", &mut self.put),
59 ("patch", &mut self.patch),
60 ("delete", &mut self.delete),
61 ]
62 .into_iter()
63 .filter_map(|(method, op)| op.as_mut().map(|o| (method, o)))
64 }
65}
66
67#[derive(Debug, Clone, Deserialize)]
68#[serde(rename_all = "camelCase")]
69pub struct Operation {
70 #[serde(default)]
71 pub operation_id: Option<String>,
72 #[serde(default)]
73 pub summary: Option<String>,
74 #[serde(default)]
75 pub tags: Vec<String>,
76 #[serde(default)]
77 pub parameters: Vec<ParameterOrRef>,
78 #[serde(default)]
79 pub request_body: Option<RequestBodyOrRef>,
80 #[serde(default)]
81 pub responses: IndexMap<String, ResponseOrRef>,
82}
83
84#[derive(Debug, Clone, Deserialize)]
85pub struct Parameter {
86 pub name: String,
87 #[serde(rename = "in")]
88 pub location: String,
89 #[serde(default)]
90 pub required: bool,
91 #[serde(default)]
92 pub schema: Option<SchemaOrRef>,
93 #[serde(default)]
94 pub description: Option<String>,
95 #[serde(default)]
96 pub style: Option<String>,
97 #[serde(default)]
98 pub explode: Option<bool>,
99}
100
101#[derive(Debug, Clone, Deserialize)]
103#[serde(untagged)]
104pub enum ParameterOrRef {
105 Ref {
106 #[serde(rename = "$ref")]
107 ref_path: String,
108 },
109 Parameter(Parameter),
110}
111
112#[derive(Debug, Clone, Deserialize)]
113pub struct RequestBody {
114 #[serde(default)]
115 pub required: bool,
116 #[serde(default)]
117 pub content: IndexMap<String, MediaType>,
118 #[serde(default)]
119 pub description: Option<String>,
120}
121
122#[derive(Debug, Clone, Deserialize)]
124#[serde(untagged)]
125pub enum RequestBodyOrRef {
126 Ref {
127 #[serde(rename = "$ref")]
128 ref_path: String,
129 },
130 RequestBody(RequestBody),
131}
132
133#[derive(Debug, Clone, Deserialize)]
134pub struct Response {
135 #[serde(default)]
136 pub description: Option<String>,
137 #[serde(default)]
138 pub content: Option<IndexMap<String, MediaType>>,
139}
140
141#[derive(Debug, Clone, Deserialize)]
143#[serde(untagged)]
144pub enum ResponseOrRef {
145 Ref {
146 #[serde(rename = "$ref")]
147 ref_path: String,
148 },
149 Response(Response),
150}
151
152#[derive(Debug, Clone, Deserialize)]
153pub struct MediaType {
154 #[serde(default)]
155 pub schema: Option<SchemaOrRef>,
156}
157
158#[derive(Debug, Clone, Deserialize)]
160#[serde(untagged)]
161pub enum SchemaOrRef {
162 Ref {
163 #[serde(rename = "$ref")]
164 ref_path: String,
165 },
166 Schema(Box<Schema>),
167}
168
169#[derive(Debug, Clone, Deserialize)]
172#[serde(untagged)]
173pub enum SchemaType {
174 Single(String),
175 Array(Vec<String>),
176}
177
178#[derive(Debug, Clone, Deserialize)]
179#[serde(rename_all = "camelCase")]
180pub struct Schema {
181 #[serde(rename = "type", default)]
182 pub schema_type: Option<SchemaType>,
183 #[serde(default)]
184 pub format: Option<String>,
185 #[serde(default)]
186 pub properties: IndexMap<String, SchemaOrRef>,
187 #[serde(default)]
188 pub required: Vec<String>,
189 #[serde(default)]
190 pub items: Option<Box<SchemaOrRef>>,
191 #[serde(default)]
193 pub prefix_items: Option<Vec<SchemaOrRef>>,
194 #[serde(rename = "enum", default)]
195 pub enum_values: Vec<serde_json::Value>,
196 #[serde(default)]
197 pub all_of: Option<Vec<SchemaOrRef>>,
198 #[serde(default)]
199 pub one_of: Option<Vec<SchemaOrRef>>,
200 #[serde(default)]
201 pub any_of: Option<Vec<SchemaOrRef>>,
202 #[serde(default)]
203 pub discriminator: Option<Discriminator>,
204 #[serde(default)]
205 pub additional_properties: Option<Box<SchemaOrRef>>,
206 #[serde(default)]
207 pub nullable: bool,
208 #[serde(default)]
209 pub read_only: bool,
210 #[serde(default)]
211 pub description: Option<String>,
212 #[serde(default)]
213 pub default: Option<serde_json::Value>,
214 #[serde(default)]
216 pub min_length: Option<u64>,
217 #[serde(default)]
218 pub max_length: Option<u64>,
219 #[serde(default)]
220 pub pattern: Option<String>,
221 #[serde(default)]
222 pub minimum: Option<f64>,
223 #[serde(default)]
224 pub maximum: Option<f64>,
225 #[serde(default)]
226 pub exclusive_minimum: Option<f64>,
227 #[serde(default)]
228 pub exclusive_maximum: Option<f64>,
229 #[serde(default)]
230 pub multiple_of: Option<f64>,
231 #[serde(default)]
232 pub min_items: Option<u64>,
233 #[serde(default)]
234 pub max_items: Option<u64>,
235 #[serde(rename = "$defs", default)]
237 pub defs: Option<IndexMap<String, SchemaOrRef>>,
238}
239
240#[derive(Debug, Clone, Deserialize)]
241#[serde(rename_all = "camelCase")]
242pub struct Discriminator {
243 pub property_name: String,
244 #[serde(default)]
245 pub mapping: IndexMap<String, String>,
246}
247
248#[derive(Debug, Deserialize)]
249#[serde(rename_all = "camelCase")]
250pub struct Components {
251 #[serde(default)]
252 pub schemas: IndexMap<String, SchemaOrRef>,
253 #[serde(default)]
254 pub parameters: IndexMap<String, ParameterOrRef>,
255 #[serde(default)]
256 pub request_bodies: IndexMap<String, RequestBodyOrRef>,
257 #[serde(default)]
258 pub responses: IndexMap<String, ResponseOrRef>,
259}