#![allow(clippy::option_if_let_else, clippy::pattern_type_mismatch)]
use crate::{format, schema::Type, Rc, Schema, Value};
use alloc::collections::BTreeMap;
type String = Rc<str>;
use super::{Target, TargetError};
pub fn populate_target_lookup_fields(target: &mut Target) -> Result<(), TargetError> {
target.resource_schema_lookup.clear();
target.default_resource_schema = None;
let mut value_to_index = BTreeMap::new();
for (index, schema) in target.resource_schemas.iter().enumerate() {
if let Some(constant_value) =
find_constant_property(schema, &target.resource_schema_selector)
{
if let Some(existing_index) = value_to_index.get(&constant_value) {
return Err(TargetError::DuplicateConstantValue(format!(
"Duplicate constant value '{}' found for resource schema selector field '{}' in schemas at indexes {} and {}",
constant_value,
target.resource_schema_selector,
existing_index,
index
).into()));
}
value_to_index.insert(constant_value.clone(), index);
target
.resource_schema_lookup
.insert(constant_value, schema.clone());
} else {
if target.default_resource_schema.is_some() {
return Err(TargetError::MultipleDefaultSchemas(format!(
"Multiple schemas found without discriminator property '{}'. Only one default resource schema is allowed.",
target.resource_schema_selector
).into()));
}
target.default_resource_schema = Some(schema.clone());
}
}
Ok(())
}
fn find_constant_property(schema: &Rc<Schema>, field_name: &str) -> Option<Value> {
match schema.as_type() {
Type::Object { properties, .. } => {
if let Some(property_schema) = properties.get(field_name) {
match property_schema.as_type() {
Type::Const { value, .. } => {
Some(value.clone())
}
_ => {
None
}
}
} else {
None
}
}
_ => {
None
}
}
}