use crate::{
dtos::schema::Schema,
entities::{DepthTracker, ReferenceResolver},
};
use mycelium_base::utils::errors::{execution_err, MappedErrors};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct SchemaOrOneOf {
#[serde(skip_serializing_if = "Option::is_none")]
one_of: Option<Vec<Schema>>,
#[serde(flatten)]
schema: Schema,
}
impl ReferenceResolver for SchemaOrOneOf {
fn resolve_ref(
&self,
components: &serde_json::Value,
depth_tracker: &mut DepthTracker,
) -> Result<serde_json::Value, MappedErrors> {
if depth_tracker.should_stop() {
return Ok(depth_tracker.empty_value());
}
depth_tracker.increment();
if let Some(one_of) = &self.one_of {
let one_of_resolved = one_of
.iter()
.filter_map(|item| {
let mut tracker_clone = depth_tracker.clone();
item.resolve_ref(components, &mut tracker_clone)
.map_err(|e| {
execution_err(format!(
"Failed to resolve schema: {e}"
))
})
.ok()
})
.collect::<Vec<_>>();
if one_of_resolved.is_empty() {
return Ok(depth_tracker.empty_value());
}
return Ok(one_of_resolved.into());
}
return self.schema.resolve_ref(components, depth_tracker);
}
}