Skip to main content

solverforge_solver/builder/context/
model.rs

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