use crate::{
model::entity::EntityModel,
model::field::{FieldKind, RelationStrength},
traits::EntityKind,
types::EntityTag,
};
#[derive(Clone, Copy)]
pub(super) struct StrongRelationInfo {
pub(super) field_index: usize,
pub(super) field_name: &'static str,
pub(super) field_kind: FieldKind,
pub(super) target_path: &'static str,
pub(super) target_entity_name: &'static str,
pub(super) target_entity_tag: EntityTag,
pub(super) target_store_path: &'static str,
}
#[expect(clippy::struct_field_names)]
#[derive(Clone, Copy)]
pub(crate) struct StrongRelationTargetInfo {
pub(in crate::db::relation) target_path: &'static str,
pub(in crate::db::relation) target_entity_name: &'static str,
pub(in crate::db::relation) target_entity_tag: EntityTag,
pub(in crate::db::relation) target_store_path: &'static str,
}
pub(crate) const fn strong_relation_target_from_kind(
kind: &FieldKind,
) -> Option<StrongRelationTargetInfo> {
match kind {
FieldKind::Relation {
target_path,
target_entity_name,
target_entity_tag,
target_store_path,
strength: RelationStrength::Strong,
..
}
| FieldKind::List(FieldKind::Relation {
target_path,
target_entity_name,
target_entity_tag,
target_store_path,
strength: RelationStrength::Strong,
..
})
| FieldKind::Set(FieldKind::Relation {
target_path,
target_entity_name,
target_entity_tag,
target_store_path,
strength: RelationStrength::Strong,
..
}) => Some(StrongRelationTargetInfo {
target_path,
target_entity_name,
target_entity_tag: *target_entity_tag,
target_store_path,
}),
_ => None,
}
}
const fn strong_relation_from_field(
field_index: usize,
field_name: &'static str,
kind: &FieldKind,
) -> Option<StrongRelationInfo> {
let Some(target) = strong_relation_target_from_kind(kind) else {
return None;
};
Some(StrongRelationInfo {
field_index,
field_name,
field_kind: *kind,
target_path: target.target_path,
target_entity_name: target.target_entity_name,
target_entity_tag: target.target_entity_tag,
target_store_path: target.target_store_path,
})
}
pub(super) fn strong_relations_for_source<S>(
target_path_filter: Option<&str>,
) -> Vec<StrongRelationInfo>
where
S: EntityKind,
{
strong_relations_for_model(S::MODEL, target_path_filter)
}
pub(super) fn strong_relations_for_model(
model: &'static EntityModel,
target_path_filter: Option<&str>,
) -> Vec<StrongRelationInfo> {
model
.fields
.iter()
.enumerate()
.filter_map(|(field_index, field)| {
strong_relation_from_field(field_index, field.name, &field.kind)
})
.filter(|relation| {
target_path_filter.is_none_or(|target_path| relation.target_path == target_path)
})
.collect()
}