openapi_nexus_core/traits/
openapi_ref_ext.rs1use openapi_nexus_spec::oas31::spec::{Components, ObjectOrReference, ObjectSchema, Response};
2
3pub const 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>(&self, components: Option<&'a Components>) -> Option<&'a Response>;
62}
63
64impl OpenApiRefExt for ObjectOrReference<Response> {
65 fn component_name(&self, component: &str) -> Option<&str> {
66 match self {
67 ObjectOrReference::Ref { ref_path, .. } => extract_component_name(ref_path, component),
68 ObjectOrReference::Object(_) => None,
69 }
70 }
71
72 fn resolve_response<'a>(&self, components: Option<&'a Components>) -> Option<&'a Response> {
73 let components = components?;
74 let response_name = self.response_name()?;
75 match components.responses.get(response_name)? {
76 ObjectOrReference::Object(response) => Some(response),
77 ObjectOrReference::Ref { .. } => {
78 None
80 }
81 }
82 }
83}
84
85impl OpenApiRefExt for ObjectOrReference<ObjectSchema> {
86 fn component_name(&self, component: &str) -> Option<&str> {
87 match self {
88 ObjectOrReference::Ref { ref_path, .. } => extract_component_name(ref_path, component),
89 ObjectOrReference::Object(_) => None,
90 }
91 }
92
93 fn resolve_response<'a>(&self, _components: Option<&'a Components>) -> Option<&'a Response> {
94 None
95 }
96}
97
98fn extract_component_name<'a>(reference: &'a str, component: &str) -> Option<&'a str> {
99 let remainder = reference.strip_prefix(COMPONENTS_PREFIX)?;
100 let remainder = remainder.strip_prefix(component)?;
101 remainder.strip_prefix('/')
102}