Skip to main content

solverforge_core/domain/dynamic/
assignment.rs

1//! Dynamic metadata for declarative scalar-assignment groups.
2//!
3//! This is intentionally a metadata boundary, not a construction-phase API.
4//! Host-language bindings register one metadata object with one scalar group;
5//! the solver owns all candidate generation, construction, and local search.
6
7/// Structural capabilities supplied by a dynamic scalar-assignment group.
8///
9/// A capability says whether metadata is declared, rather than inferring that
10/// fact from a value returned while solving.  The solver uses this distinction
11/// when validating construction heuristics and assignment-rule dependencies.
12#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
13pub struct DynamicScalarAssignmentMetadataCapabilities {
14    pub required_entity: bool,
15    pub capacity_key: bool,
16    pub position_key: bool,
17    pub sequence_key: bool,
18    pub entity_order: bool,
19    pub value_order: bool,
20    pub assignment_rule: bool,
21}
22
23/// Object-safe metadata access for one dynamic scalar-assignment group.
24///
25/// Implementors are bound to a concrete group at model compilation time.  They
26/// must not select a group indirectly from thread-local state, a runtime name
27/// lookup, or the active phase.  Typed Rust groups retain their direct
28/// function-pointer metadata and never use this dynamic boundary.
29pub trait DynamicScalarAssignmentMetadata<S>: Send + Sync {
30    fn capabilities(&self) -> DynamicScalarAssignmentMetadataCapabilities;
31
32    fn required_entity(&self, solution: &S, entity_index: usize) -> bool;
33
34    fn capacity_key(&self, solution: &S, entity_index: usize, value: usize) -> Option<usize>;
35
36    fn position_key(&self, solution: &S, entity_index: usize) -> Option<i64>;
37
38    fn sequence_key(&self, solution: &S, entity_index: usize, value: usize) -> Option<usize>;
39
40    fn entity_order_key(&self, solution: &S, entity_index: usize) -> Option<i64>;
41
42    fn value_order_key(&self, solution: &S, entity_index: usize, value: usize) -> Option<i64>;
43
44    fn assignment_edge_allowed(
45        &self,
46        solution: &S,
47        left_entity: usize,
48        left_value: usize,
49        right_entity: usize,
50        right_value: usize,
51    ) -> bool;
52}