From 5df51a46fad25ca566aaec5e7a8d454e605f6e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABlle=20Huisman?= Date: Sat, 14 Feb 2026 23:27:08 +0100 Subject: [PATCH] fix: merge one of schemas --- packages/breach/src/utoipa.rs | 46 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/packages/breach/src/utoipa.rs b/packages/breach/src/utoipa.rs index e9367ab..22aa44c 100644 --- a/packages/breach/src/utoipa.rs +++ b/packages/breach/src/utoipa.rs @@ -16,37 +16,26 @@ pub fn merge_responses( .flatten() .chunk_by(|(code, _)| code.clone()) .into_iter() - .filter_map(|(code, chunk)| { + .map(|(code, chunk)| { let response = merge_response( StatusCode::from_bytes(code.as_bytes()).expect("valid status code"), chunk.map(|(_, response)| response), ); - response.map(|response| (code, RefOr::T(response))) + (code, RefOr::T(response)) }) .collect() } /// Merge multiple [`RefOr`] into a single [`Response`]. -fn merge_response( - code: StatusCode, - responses: impl Iterator>, -) -> Option { - let mut responses = responses - .filter_map(|response| match response { - RefOr::Ref(_) => None, - RefOr::T(response) => Some(response), - }) - .collect::>(); +fn merge_response(code: StatusCode, responses: impl Iterator>) -> Response { + let responses = responses.filter_map(|response| match response { + RefOr::Ref(_) => None, + RefOr::T(response) => Some(response), + }); let mut builder = ResponseBuilder::new(); - if responses.is_empty() { - return None; - } else if responses.len() == 1 { - return Some(responses.remove(0)); - } - if let Some(canonical_reason) = code.canonical_reason() { builder = builder.description(canonical_reason) } @@ -64,7 +53,6 @@ fn merge_response( .into_iter(), ); - // TODO: Merge content. if let Some(content) = content { builder.content(content_type, content) } else { @@ -74,7 +62,7 @@ fn merge_response( // TODO: Merge headers, extensions, links. - Some(builder.build()) + builder.build() } fn merge_content(mut contents: impl ExactSizeIterator) -> Option { @@ -97,7 +85,7 @@ fn merge_content(mut contents: impl ExactSizeIterator) -> Option } if let Some(schema) = content.schema { - one_of_builder = one_of_builder.item(schema); + one_of_builder = merge_into_one_of_builder(one_of_builder, schema); } // TODO: Merge extensions. @@ -110,3 +98,19 @@ fn merge_content(mut contents: impl ExactSizeIterator) -> Option Some(builder.build()) } + +fn merge_into_one_of_builder(mut builder: OneOfBuilder, schema: RefOr) -> OneOfBuilder { + if let RefOr::T(schema) = schema { + if let Schema::OneOf(one_of) = schema { + for item in one_of.items { + builder = merge_into_one_of_builder(builder, item); + } + + builder + } else { + builder.item(RefOr::T(schema)) + } + } else { + builder.item(schema) + } +}