solverforge_solver/planning/
scalar.rs1use std::marker::PhantomData;
2
3#[derive(Debug)]
4pub struct ScalarTarget<S> {
5 descriptor_index: usize,
6 variable_name: &'static str,
7 _phantom: PhantomData<fn() -> S>,
8}
9
10impl<S> Clone for ScalarTarget<S> {
11 fn clone(&self) -> Self {
12 *self
13 }
14}
15
16impl<S> Copy for ScalarTarget<S> {}
17
18impl<S> PartialEq for ScalarTarget<S> {
19 fn eq(&self, other: &Self) -> bool {
20 self.descriptor_index == other.descriptor_index && self.variable_name == other.variable_name
21 }
22}
23
24impl<S> Eq for ScalarTarget<S> {}
25
26impl<S> std::hash::Hash for ScalarTarget<S> {
27 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
28 self.descriptor_index.hash(state);
29 self.variable_name.hash(state);
30 }
31}
32
33impl<S> ScalarTarget<S> {
34 #[doc(hidden)]
35 pub const fn from_descriptor_index(
36 descriptor_index: usize,
37 variable_name: &'static str,
38 ) -> Self {
39 Self {
40 descriptor_index,
41 variable_name,
42 _phantom: PhantomData,
43 }
44 }
45
46 #[inline]
47 pub fn set(self, entity_index: usize, to_value: Option<usize>) -> ScalarEdit<S> {
48 ScalarEdit {
49 descriptor_index: self.descriptor_index,
50 entity_index,
51 variable_name: self.variable_name,
52 to_value,
53 _phantom: PhantomData,
54 }
55 }
56
57 #[doc(hidden)]
58 #[inline]
59 pub fn descriptor_index(self) -> usize {
60 self.descriptor_index
61 }
62
63 #[doc(hidden)]
64 #[inline]
65 pub fn variable_name(self) -> &'static str {
66 self.variable_name
67 }
68}
69
70#[derive(Debug)]
71pub struct ScalarEdit<S> {
72 descriptor_index: usize,
73 entity_index: usize,
74 variable_name: &'static str,
75 to_value: Option<usize>,
76 _phantom: PhantomData<fn() -> S>,
77}
78
79impl<S> Clone for ScalarEdit<S> {
80 fn clone(&self) -> Self {
81 *self
82 }
83}
84
85impl<S> Copy for ScalarEdit<S> {}
86
87impl<S> PartialEq for ScalarEdit<S> {
88 fn eq(&self, other: &Self) -> bool {
89 self.descriptor_index == other.descriptor_index
90 && self.entity_index == other.entity_index
91 && self.variable_name == other.variable_name
92 && self.to_value == other.to_value
93 }
94}
95
96impl<S> Eq for ScalarEdit<S> {}
97
98impl<S> std::hash::Hash for ScalarEdit<S> {
99 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
100 self.descriptor_index.hash(state);
101 self.entity_index.hash(state);
102 self.variable_name.hash(state);
103 self.to_value.hash(state);
104 }
105}
106
107impl<S> ScalarEdit<S> {
108 #[doc(hidden)]
109 pub const fn from_descriptor_index(
110 descriptor_index: usize,
111 entity_index: usize,
112 variable_name: &'static str,
113 to_value: Option<usize>,
114 ) -> Self {
115 Self {
116 descriptor_index,
117 entity_index,
118 variable_name,
119 to_value,
120 _phantom: PhantomData,
121 }
122 }
123
124 #[doc(hidden)]
125 #[inline]
126 pub fn descriptor_index(&self) -> usize {
127 self.descriptor_index
128 }
129
130 #[doc(hidden)]
131 #[inline]
132 pub fn entity_index(&self) -> usize {
133 self.entity_index
134 }
135
136 #[doc(hidden)]
137 #[inline]
138 pub fn variable_name(&self) -> &'static str {
139 self.variable_name
140 }
141
142 #[doc(hidden)]
143 #[inline]
144 pub fn to_value(&self) -> Option<usize> {
145 self.to_value
146 }
147}
148
149#[derive(Debug)]
150pub struct ScalarCandidate<S> {
151 reason: &'static str,
152 edits: Vec<ScalarEdit<S>>,
153 construction_slot_key: Option<usize>,
154 construction_entity_order_key: Option<i64>,
155 construction_value_order_key: Option<i64>,
156}
157
158impl<S> Clone for ScalarCandidate<S> {
159 fn clone(&self) -> Self {
160 Self {
161 reason: self.reason,
162 edits: self.edits.clone(),
163 construction_slot_key: self.construction_slot_key,
164 construction_entity_order_key: self.construction_entity_order_key,
165 construction_value_order_key: self.construction_value_order_key,
166 }
167 }
168}
169
170impl<S> PartialEq for ScalarCandidate<S> {
171 fn eq(&self, other: &Self) -> bool {
172 self.reason == other.reason
173 && self.edits == other.edits
174 && self.construction_slot_key == other.construction_slot_key
175 && self.construction_entity_order_key == other.construction_entity_order_key
176 && self.construction_value_order_key == other.construction_value_order_key
177 }
178}
179
180impl<S> Eq for ScalarCandidate<S> {}
181
182impl<S> std::hash::Hash for ScalarCandidate<S> {
183 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
184 self.reason.hash(state);
185 self.edits.hash(state);
186 self.construction_slot_key.hash(state);
187 self.construction_entity_order_key.hash(state);
188 self.construction_value_order_key.hash(state);
189 }
190}
191
192impl<S> ScalarCandidate<S> {
193 pub fn new(reason: &'static str, edits: Vec<ScalarEdit<S>>) -> Self {
194 Self {
195 reason,
196 edits,
197 construction_slot_key: None,
198 construction_entity_order_key: None,
199 construction_value_order_key: None,
200 }
201 }
202
203 pub fn with_construction_slot_key(mut self, key: usize) -> Self {
204 self.construction_slot_key = Some(key);
205 self
206 }
207
208 pub fn with_construction_entity_order_key(mut self, key: i64) -> Self {
209 self.construction_entity_order_key = Some(key);
210 self
211 }
212
213 pub fn with_construction_value_order_key(mut self, key: i64) -> Self {
214 self.construction_value_order_key = Some(key);
215 self
216 }
217
218 #[doc(hidden)]
219 #[inline]
220 pub fn reason(&self) -> &'static str {
221 self.reason
222 }
223
224 #[doc(hidden)]
225 #[inline]
226 pub fn edits(&self) -> &[ScalarEdit<S>] {
227 &self.edits
228 }
229
230 #[doc(hidden)]
231 #[inline]
232 pub fn into_edits(self) -> Vec<ScalarEdit<S>> {
233 self.edits
234 }
235
236 #[doc(hidden)]
237 #[inline]
238 pub fn construction_slot_key(&self) -> Option<usize> {
239 self.construction_slot_key
240 }
241
242 #[doc(hidden)]
243 #[inline]
244 pub fn construction_entity_order_key(&self) -> Option<i64> {
245 self.construction_entity_order_key
246 }
247
248 #[doc(hidden)]
249 #[inline]
250 pub fn construction_value_order_key(&self) -> Option<i64> {
251 self.construction_value_order_key
252 }
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq)]
256pub struct ScalarGroupLimits {
257 pub value_candidate_limit: Option<usize>,
258 pub group_candidate_limit: Option<usize>,
259 pub max_moves_per_step: Option<usize>,
260}
261
262pub type ScalarCandidateProvider<S> = fn(&S, ScalarGroupLimits) -> Vec<ScalarCandidate<S>>;
263
264#[derive(Clone)]
265pub struct ScalarGroup<S> {
266 group_name: &'static str,
267 targets: Vec<ScalarTarget<S>>,
268 candidate_provider: ScalarCandidateProvider<S>,
269}
270
271impl<S> ScalarGroup<S> {
272 pub fn new(
273 group_name: &'static str,
274 targets: Vec<ScalarTarget<S>>,
275 candidate_provider: ScalarCandidateProvider<S>,
276 ) -> Self {
277 Self {
278 group_name,
279 targets,
280 candidate_provider,
281 }
282 }
283
284 #[doc(hidden)]
285 #[inline]
286 pub fn group_name(&self) -> &'static str {
287 self.group_name
288 }
289
290 #[doc(hidden)]
291 #[inline]
292 pub fn targets(&self) -> &[ScalarTarget<S>] {
293 &self.targets
294 }
295
296 #[doc(hidden)]
297 #[inline]
298 pub fn candidate_provider(&self) -> ScalarCandidateProvider<S> {
299 self.candidate_provider
300 }
301}
302
303impl<S> std::fmt::Debug for ScalarGroup<S> {
304 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
305 f.debug_struct("ScalarGroup")
306 .field("group_name", &self.group_name)
307 .field("target_count", &self.targets.len())
308 .finish_non_exhaustive()
309 }
310}