solverforge-core 0.15.2

Core types and traits for SolverForge constraint solver
Documentation
use crate::domain::{EntityClassId, SolutionDescriptor, VariableId};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum DynamicVariableKind {
    Scalar,
    List,
}

pub(super) fn resolve_dynamic_descriptor_index(
    descriptor: &SolutionDescriptor,
    entity: EntityClassId,
    variable: VariableId,
    entity_type_name: &'static str,
    variable_name: &'static str,
    kind: DynamicVariableKind,
) -> Result<usize, String> {
    let Some(descriptor_index) = descriptor.entity_descriptor_index_by_logical_id(entity) else {
        return Err(format!(
            "dynamic variable {entity_type_name}.{variable_name} refers to logical entity ID {}, but the solution descriptor has no matching entity descriptor",
            entity.0
        ));
    };
    let entity_descriptor = descriptor
        .entity_descriptors
        .get(descriptor_index)
        .expect("logical entity index must point at an entity descriptor");
    if entity_descriptor.type_name != entity_type_name {
        return Err(format!(
            "dynamic variable {entity_type_name}.{variable_name} resolved logical entity ID {} to descriptor index {descriptor_index} ({})",
            entity.0, entity_descriptor.type_name
        ));
    }

    let Some(variable_descriptor) = entity_descriptor
        .variable_descriptors
        .iter()
        .find(|descriptor| descriptor.logical_id == Some(variable))
    else {
        return Err(format!(
            "dynamic variable {entity_type_name}.{variable_name} refers to logical variable ID {}, but descriptor {entity_type_name} has no matching variable descriptor",
            variable.0
        ));
    };
    if variable_descriptor.name != variable_name {
        return Err(format!(
            "dynamic variable {entity_type_name}.{variable_name} resolved logical variable ID {} to descriptor variable {}",
            variable.0, variable_descriptor.name
        ));
    }
    match kind {
        DynamicVariableKind::Scalar if variable_descriptor.variable_type.is_list() => Err(
            format!(
                "dynamic scalar variable {entity_type_name}.{variable_name} resolves to a list variable descriptor"
            ),
        ),
        DynamicVariableKind::List if !variable_descriptor.variable_type.is_list() => Err(
            format!(
                "dynamic list variable {entity_type_name}.{variable_name} resolves to a non-list variable descriptor"
            ),
        ),
        DynamicVariableKind::Scalar | DynamicVariableKind::List => Ok(descriptor_index),
    }
}