Skip to main content

openapi_nexus_core/traits/
openapi_parameter_ext.rs

1use openapi_nexus_spec::oas31::spec::{Components, ObjectOrReference, ObjectSchema, Parameter};
2
3use super::openapi_ref_ext::COMPONENTS_PREFIX;
4
5/// Extension trait for OpenAPI `Parameter` to provide convenience methods.
6pub trait OpenApiParameterExt {
7    /// Returns `true` if the parameter is required.
8    fn required(&self) -> bool;
9
10    /// Returns `true` if the parameter is deprecated.
11    fn deprecated(&self) -> bool;
12
13    /// Extract default value from the parameter's schema.
14    ///
15    /// Returns `None` if the parameter has no schema or no default value is specified.
16    /// For referenced schemas, resolves the reference using the provided `Components`.
17    fn default_value(&self, components: Option<&Components>) -> Option<serde_json::Value>;
18}
19
20impl OpenApiParameterExt for Parameter {
21    fn required(&self) -> bool {
22        self.required.unwrap_or(false)
23    }
24
25    fn deprecated(&self) -> bool {
26        self.deprecated.unwrap_or(false)
27    }
28
29    fn default_value(&self, components: Option<&Components>) -> Option<serde_json::Value> {
30        let schema_ref = self.schema.as_ref()?;
31        extract_default_value_from_schema(schema_ref, components)
32    }
33}
34
35/// Extract default value from a schema reference (helper for recursive resolution)
36fn extract_default_value_from_schema(
37    schema_ref: &ObjectOrReference<ObjectSchema>,
38    components: Option<&Components>,
39) -> Option<serde_json::Value> {
40    match schema_ref {
41        ObjectOrReference::Object(schema) => schema.default.clone(),
42        ObjectOrReference::Ref { ref_path, .. } => {
43            // Extract schema name from ref_path
44            let schema_name = extract_component_name(ref_path, "schemas")?;
45            components?
46                .schemas
47                .get(schema_name)
48                .and_then(|resolved_schema| {
49                    extract_default_value_from_schema(resolved_schema, components)
50                })
51        }
52    }
53}
54
55fn extract_component_name<'a>(reference: &'a str, component: &str) -> Option<&'a str> {
56    let remainder = reference.strip_prefix(COMPONENTS_PREFIX)?;
57    let remainder = remainder.strip_prefix(component)?;
58    remainder.strip_prefix('/')
59}