Skip to main content

solverforge_solver/builder/context/
model.rs

1use std::fmt;
2use std::marker::PhantomData;
3
4use super::{ConflictRepair, ListVariableSlot, ScalarGroupBinding, ScalarVariableSlot};
5
6pub enum VariableSlot<S, V, DM, IDM> {
7    Scalar(ScalarVariableSlot<S>),
8    List(ListVariableSlot<S, V, DM, IDM>),
9}
10
11impl<S, V, DM: Clone, IDM: Clone> Clone for VariableSlot<S, V, DM, IDM> {
12    fn clone(&self) -> Self {
13        match self {
14            Self::Scalar(variable) => Self::Scalar(*variable),
15            Self::List(variable) => Self::List(variable.clone()),
16        }
17    }
18}
19
20impl<S, V, DM: fmt::Debug, IDM: fmt::Debug> fmt::Debug for VariableSlot<S, V, DM, IDM> {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        match self {
23            Self::Scalar(variable) => variable.fmt(f),
24            Self::List(variable) => variable.fmt(f),
25        }
26    }
27}
28
29pub struct RuntimeModel<S, V, DM, IDM> {
30    variables: Vec<VariableSlot<S, V, DM, IDM>>,
31    scalar_groups: Vec<ScalarGroupBinding<S>>,
32    conflict_repairs: Vec<ConflictRepair<S>>,
33    _phantom: PhantomData<(fn() -> S, fn() -> V)>,
34}
35
36impl<S, V, DM: Clone, IDM: Clone> Clone for RuntimeModel<S, V, DM, IDM> {
37    fn clone(&self) -> Self {
38        Self {
39            variables: self.variables.clone(),
40            scalar_groups: self.scalar_groups.clone(),
41            conflict_repairs: self.conflict_repairs.clone(),
42            _phantom: PhantomData,
43        }
44    }
45}
46
47impl<S, V, DM, IDM> RuntimeModel<S, V, DM, IDM> {
48    pub fn new(variables: Vec<VariableSlot<S, V, DM, IDM>>) -> Self {
49        Self {
50            variables,
51            scalar_groups: Vec::new(),
52            conflict_repairs: Vec::new(),
53            _phantom: PhantomData,
54        }
55    }
56
57    pub fn with_scalar_groups(mut self, groups: Vec<ScalarGroupBinding<S>>) -> Self {
58        self.scalar_groups = groups;
59        self
60    }
61
62    pub fn with_conflict_repairs(mut self, repairs: Vec<ConflictRepair<S>>) -> Self {
63        self.conflict_repairs = repairs;
64        self
65    }
66
67    pub fn variables(&self) -> &[VariableSlot<S, V, DM, IDM>] {
68        &self.variables
69    }
70
71    pub fn scalar_groups(&self) -> &[ScalarGroupBinding<S>] {
72        &self.scalar_groups
73    }
74
75    pub fn conflict_repairs(&self) -> &[ConflictRepair<S>] {
76        &self.conflict_repairs
77    }
78
79    pub fn is_empty(&self) -> bool {
80        self.variables.is_empty()
81    }
82
83    pub fn has_list_variables(&self) -> bool {
84        self.variables
85            .iter()
86            .any(|variable| matches!(variable, VariableSlot::List(_)))
87    }
88
89    pub fn scalar_variables(&self) -> impl Iterator<Item = &ScalarVariableSlot<S>> {
90        self.variables.iter().filter_map(|variable| match variable {
91            VariableSlot::Scalar(ctx) => Some(ctx),
92            VariableSlot::List(_) => None,
93        })
94    }
95
96    pub fn list_variables(&self) -> impl Iterator<Item = &ListVariableSlot<S, V, DM, IDM>> {
97        self.variables.iter().filter_map(|variable| match variable {
98            VariableSlot::List(ctx) => Some(ctx),
99            VariableSlot::Scalar(_) => None,
100        })
101    }
102}
103
104impl<S, V, DM: fmt::Debug, IDM: fmt::Debug> fmt::Debug for RuntimeModel<S, V, DM, IDM> {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        f.debug_struct("RuntimeModel")
107            .field("variables", &self.variables)
108            .field("scalar_groups", &self.scalar_groups)
109            .field("conflict_repairs", &self.conflict_repairs)
110            .finish()
111    }
112}