openapi_nexus_core/traits/
openapi_ref_ext.rs1use utoipa::openapi;
2
3const COMPONENTS_PREFIX: &str = "#/components/";
4
5pub trait OpenApiRefExt {
7 fn schema_name(&self) -> Option<&str> {
9 self.component_name("schemas")
10 }
11
12 fn response_name(&self) -> Option<&str> {
14 self.component_name("responses")
15 }
16
17 fn parameter_name(&self) -> Option<&str> {
19 self.component_name("parameters")
20 }
21
22 fn example_name(&self) -> Option<&str> {
24 self.component_name("examples")
25 }
26
27 fn request_body_name(&self) -> Option<&str> {
29 self.component_name("requestBodies")
30 }
31
32 fn header_name(&self) -> Option<&str> {
34 self.component_name("headers")
35 }
36
37 fn security_scheme_name(&self) -> Option<&str> {
39 self.component_name("securitySchemes")
40 }
41
42 fn link_name(&self) -> Option<&str> {
44 self.component_name("links")
45 }
46
47 fn callback_name(&self) -> Option<&str> {
49 self.component_name("callbacks")
50 }
51
52 fn path_item_name(&self) -> Option<&str> {
54 self.component_name("pathItems")
55 }
56
57 fn component_name(&self, component: &str) -> Option<&str>;
59
60 fn resolve_response<'a>(
62 &self,
63 components: Option<&'a openapi::Components>,
64 ) -> Option<&'a openapi::Response>;
65}
66
67impl OpenApiRefExt for openapi::Ref {
68 fn component_name(&self, component: &str) -> Option<&str> {
69 extract_component_name(&self.ref_location, component)
70 }
71
72 fn resolve_response<'a>(
73 &self,
74 components: Option<&'a openapi::Components>,
75 ) -> Option<&'a openapi::Response> {
76 let components = components?;
77 let response_name = self.response_name()?;
78 match components.responses.get(response_name)? {
79 openapi::RefOr::T(response) => Some(response),
80 openapi::RefOr::Ref(inner_reference) => {
81 inner_reference.resolve_response(Some(components))
82 }
83 }
84 }
85}
86
87fn extract_component_name<'a>(reference: &'a str, component: &str) -> Option<&'a str> {
88 let remainder = reference.strip_prefix(COMPONENTS_PREFIX)?;
89 let remainder = remainder.strip_prefix(component)?;
90 remainder.strip_prefix('/')
91}