Skip to content

Commit d3d8974

Browse files
committed
fail if merge unique values are not the same
1 parent e97fa7f commit d3d8974

File tree

1 file changed

+35
-31
lines changed

1 file changed

+35
-31
lines changed

src/merger.rs

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use indexmap::IndexMap;
22
use openapiv3::{Components, ExternalDocumentation, OpenAPI, Paths};
33

44
use crate::Error;
5+
use crate::Result;
56

6-
pub(crate) fn merge_all_openapi_specs(openapi_specs: Vec<OpenAPI>) -> crate::Result<OpenAPI> {
7+
pub(crate) fn merge_all_openapi_specs(openapi_specs: Vec<OpenAPI>) -> Result<OpenAPI> {
78
if openapi_specs.is_empty() {
89
Err(Error::unexpected("No OpenAPI specs provided"))
910
} else if openapi_specs.len() == 1 {
@@ -22,7 +23,7 @@ pub(crate) fn merge_all_openapi_specs(openapi_specs: Vec<OpenAPI>) -> crate::Res
2223
}
2324
}
2425

25-
fn merge_openapi_specs(a: OpenAPI, b: OpenAPI) -> crate::Result<OpenAPI> {
26+
fn merge_openapi_specs(a: OpenAPI, b: OpenAPI) -> Result<OpenAPI> {
2627
let openapi_version = {
2728
if a.openapi != b.openapi {
2829
return Err(Error::unexpected("OpenAPI versions do not match"));
@@ -60,17 +61,17 @@ fn merge_openapi_specs(a: OpenAPI, b: OpenAPI) -> crate::Result<OpenAPI> {
6061
paths: b_paths,
6162
extensions: b_extensions,
6263
} = b.paths;
63-
let all_paths = merge_unique(a_paths, b_paths);
64-
let all_extensions = merge_unique(a_extensions, b_extensions);
64+
let all_paths = merge_unique(a_paths, b_paths)?;
65+
let all_extensions = merge_unique(a_extensions, b_extensions)?;
6566
Paths {
6667
paths: all_paths,
6768
extensions: all_extensions,
6869
}
6970
};
7071

71-
let components = merge_components(a.components, b.components);
72+
let components = merge_components(a.components, b.components)?;
7273
let security = merge_unique_option_list(a.security, b.security);
73-
let extensions = merge_unique(a.extensions, b.extensions);
74+
let extensions = merge_unique(a.extensions, b.extensions)?;
7475

7576
let external_docs = merge_external_docs(a.external_docs, b.external_docs)?;
7677

@@ -89,8 +90,8 @@ fn merge_openapi_specs(a: OpenAPI, b: OpenAPI) -> crate::Result<OpenAPI> {
8990
Ok(result)
9091
}
9192

92-
fn merge_components(a: Option<Components>, b: Option<Components>) -> Option<Components> {
93-
match (a, b) {
93+
fn merge_components(a: Option<Components>, b: Option<Components>) -> Result<Option<Components>> {
94+
let result = match (a, b) {
9495
(Some(a), Some(b)) => {
9596
let Components {
9697
schemas: a_schemas,
@@ -119,23 +120,25 @@ fn merge_components(a: Option<Components>, b: Option<Components>) -> Option<Comp
119120
} = b;
120121

121122
let merged = Components {
122-
schemas: merge_unique(a_schemas, b_schemas),
123-
responses: merge_unique(a_responses, b_responses),
124-
parameters: merge_unique(a_parameters, b_parameters),
125-
examples: merge_unique(a_examples, b_examples),
126-
request_bodies: merge_unique(a_request_bodies, b_request_bodies),
127-
headers: merge_unique(a_headers, b_headers),
128-
security_schemes: merge_unique(a_security_schemes, b_security_schemes),
129-
links: merge_unique(a_links, b_links),
130-
callbacks: merge_unique(a_callbacks, b_callbacks),
131-
extensions: merge_unique(a_extensions, b_extensions),
123+
schemas: merge_unique(a_schemas, b_schemas)?,
124+
responses: merge_unique(a_responses, b_responses)?,
125+
parameters: merge_unique(a_parameters, b_parameters)?,
126+
examples: merge_unique(a_examples, b_examples)?,
127+
request_bodies: merge_unique(a_request_bodies, b_request_bodies)?,
128+
headers: merge_unique(a_headers, b_headers)?,
129+
security_schemes: merge_unique(a_security_schemes, b_security_schemes)?,
130+
links: merge_unique(a_links, b_links)?,
131+
callbacks: merge_unique(a_callbacks, b_callbacks)?,
132+
extensions: merge_unique(a_extensions, b_extensions)?,
132133
};
133134
Some(merged)
134135
}
135136
(Some(a), None) => Some(a),
136137
(None, Some(b)) => Some(b),
137138
(None, None) => None,
138-
}
139+
};
140+
141+
Ok(result)
139142
}
140143

141144
fn merge_external_docs(
@@ -179,7 +182,7 @@ fn merge_external_docs(
179182
a_url
180183
};
181184

182-
let extensions = merge_unique(a_extensions, b_extensions);
185+
let extensions = merge_unique(a_extensions, b_extensions)?;
183186

184187
Some(ExternalDocumentation {
185188
description,
@@ -211,26 +214,27 @@ fn merge_unique_option_list<Key, Item>(
211214
}
212215

213216
fn merge_unique<Key, Item>(
214-
a: impl IntoIterator<Item = (Key, Item)>,
215-
b: impl IntoIterator<Item = (Key, Item)>,
216-
) -> IndexMap<Key, Item>
217+
mut a: IndexMap<Key, Item>,
218+
b: IndexMap<Key, Item>,
219+
) -> Result<IndexMap<Key, Item>>
217220
where
218221
Key: std::fmt::Debug + Eq + std::hash::Hash,
222+
Item: PartialEq,
219223
{
220-
let mut map = IndexMap::new();
221-
for (key, value) in a {
222-
map.insert(key, value);
223-
}
224224
for (key, value) in b {
225-
match map.entry(key) {
225+
match a.entry(key) {
226226
indexmap::map::Entry::Occupied(entry) => {
227-
#[cfg(debug_assertions)]
228-
println!("Entry is already occupied {:?}", entry.key());
227+
if entry.get() != &value {
228+
return Err(Error::unexpected(format!(
229+
"Duplicate key {:?} with different values",
230+
entry.key()
231+
)));
232+
}
229233
}
230234
indexmap::map::Entry::Vacant(entry) => {
231235
entry.insert(value);
232236
}
233237
}
234238
}
235-
map
239+
Ok(a)
236240
}

0 commit comments

Comments
 (0)