use crate::{
model::entity::EntityModel,
model::field::{FieldKind, RelationStrength},
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db) enum RelationDescriptorCardinality {
Single,
List,
Set,
}
#[derive(Clone, Copy)]
#[cfg_attr(not(test), allow(dead_code))]
pub(in crate::db) struct RelationDescriptor {
field_name: &'static str,
target_path: &'static str,
target_entity_name: &'static str,
target_store_path: &'static str,
strength: RelationStrength,
cardinality: RelationDescriptorCardinality,
}
#[cfg_attr(not(test), allow(dead_code))]
impl RelationDescriptor {
const fn new(field_name: &'static str, target: RelationTargetInfo) -> Self {
Self {
field_name,
target_path: target.path,
target_entity_name: target.entity_name,
target_store_path: target.store_path,
strength: target.strength,
cardinality: target.cardinality,
}
}
#[must_use]
pub(in crate::db) const fn field_name(self) -> &'static str {
self.field_name
}
#[must_use]
pub(in crate::db) const fn target_path(self) -> &'static str {
self.target_path
}
#[must_use]
pub(in crate::db) const fn target_entity_name(self) -> &'static str {
self.target_entity_name
}
#[must_use]
pub(in crate::db) const fn target_store_path(self) -> &'static str {
self.target_store_path
}
#[must_use]
pub(in crate::db) const fn strength(self) -> RelationStrength {
self.strength
}
#[must_use]
pub(in crate::db) const fn cardinality(self) -> RelationDescriptorCardinality {
self.cardinality
}
}
#[derive(Clone, Copy)]
struct RelationTargetInfo {
path: &'static str,
entity_name: &'static str,
store_path: &'static str,
strength: RelationStrength,
cardinality: RelationDescriptorCardinality,
}
const fn relation_target_from_kind(kind: &FieldKind) -> Option<RelationTargetInfo> {
match kind {
FieldKind::Relation {
target_path,
target_entity_name,
target_store_path,
strength,
..
} => Some(RelationTargetInfo {
path: target_path,
entity_name: target_entity_name,
store_path: target_store_path,
strength: *strength,
cardinality: RelationDescriptorCardinality::Single,
}),
FieldKind::List(FieldKind::Relation {
target_path,
target_entity_name,
target_store_path,
strength,
..
}) => Some(RelationTargetInfo {
path: target_path,
entity_name: target_entity_name,
store_path: target_store_path,
strength: *strength,
cardinality: RelationDescriptorCardinality::List,
}),
FieldKind::Set(FieldKind::Relation {
target_path,
target_entity_name,
target_store_path,
strength,
..
}) => Some(RelationTargetInfo {
path: target_path,
entity_name: target_entity_name,
store_path: target_store_path,
strength: *strength,
cardinality: RelationDescriptorCardinality::Set,
}),
_ => None,
}
}
const fn relation_descriptor_from_field(
field_name: &'static str,
kind: &FieldKind,
) -> Option<RelationDescriptor> {
let Some(target) = relation_target_from_kind(kind) else {
return None;
};
Some(RelationDescriptor::new(field_name, target))
}
pub(in crate::db) fn relation_descriptors_for_model_iter(
model: &EntityModel,
) -> impl Iterator<Item = RelationDescriptor> + '_ {
model
.fields
.iter()
.filter_map(|field| relation_descriptor_from_field(field.name, &field.kind))
}
impl EntityModel {
#[must_use]
pub(in crate::db) fn has_any_strong_relations(&self) -> bool {
relation_descriptors_for_model_iter(self)
.any(|descriptor| descriptor.strength() == RelationStrength::Strong)
}
}