feo3boy_opcodes/compiler/instr/flow/
path.rs1use std::array;
2use std::borrow::{Borrow, BorrowMut};
3use std::iter;
4use std::ops::{Deref, DerefMut};
5use std::{mem, slice};
6
7use crate::count_repetition;
8
9#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
12pub enum ElementSelector {
13 Branch(bool),
15 Block(usize),
17}
18
19impl ElementSelector {
20 #[inline]
22 pub fn as_path(&self) -> &ElementPath {
23 ElementPath::from_slice(slice::from_ref(self))
24 }
25
26 #[inline]
28 pub fn as_mut_path(&mut self) -> &mut ElementPath {
29 ElementPath::from_mut_slice(slice::from_mut(self))
30 }
31
32 pub fn unwrap_branch(self) -> bool {
34 match self {
35 ElementSelector::Branch(cond) => cond,
36 ElementSelector::Block(_) => panic!("Not a Branch Selector"),
37 }
38 }
39
40 pub fn unwrap_block(self) -> usize {
42 match self {
43 ElementSelector::Block(idx) => idx,
44 ElementSelector::Branch(_) => panic!("Not a Block Selector"),
45 }
46 }
47
48 pub fn unwrap_branch_mut(&mut self) -> &mut bool {
50 match self {
51 ElementSelector::Branch(cond) => cond,
52 ElementSelector::Block(_) => panic!("Not a Branch Selector"),
53 }
54 }
55
56 pub fn unwrap_block_mut(&mut self) -> &mut usize {
58 match self {
59 ElementSelector::Block(idx) => idx,
60 ElementSelector::Branch(_) => panic!("Not a Block Selector"),
61 }
62 }
63}
64
65impl From<bool> for ElementSelector {
66 #[inline]
67 fn from(cond: bool) -> Self {
68 Self::Branch(cond)
69 }
70}
71
72impl From<usize> for ElementSelector {
73 #[inline]
74 fn from(index: usize) -> Self {
75 Self::Block(index)
76 }
77}
78
79impl Borrow<ElementPath> for ElementSelector {
80 #[inline]
81 fn borrow(&self) -> &ElementPath {
82 self.as_path()
83 }
84}
85
86impl BorrowMut<ElementPath> for ElementSelector {
87 #[inline]
88 fn borrow_mut(&mut self) -> &mut ElementPath {
89 self.as_mut_path()
90 }
91}
92
93impl ElementIndex for ElementSelector {
94 type PathSelectors = iter::Once<Self>;
95
96 #[inline]
97 fn path_selectors(self) -> Self::PathSelectors {
98 iter::once(self)
99 }
100}
101
102#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
104#[repr(transparent)]
105pub struct ElementPathBuf {
106 path: Vec<ElementSelector>,
108}
109
110impl ElementPathBuf {
111 #[inline]
113 pub fn new() -> Self {
114 Default::default()
115 }
116
117 pub fn from_path(path: &ElementPath) -> Self {
119 Self {
120 path: path.as_slice().to_vec(),
121 }
122 }
123
124 #[inline]
126 pub fn as_path(&self) -> &ElementPath {
127 ElementPath::from_slice(&self.path)
128 }
129
130 #[inline]
132 pub fn as_mut_path(&mut self) -> &mut ElementPath {
133 ElementPath::from_mut_slice(&mut self.path)
134 }
135
136 #[inline]
138 pub fn push<S>(&mut self, selector: S)
139 where
140 S: Into<ElementSelector>,
141 {
142 self.path.push(selector.into());
143 }
144
145 #[inline]
147 pub fn append<P>(&mut self, path: P)
148 where
149 P: ElementIndex,
150 {
151 self.path.extend(path.path_selectors())
152 }
153
154 #[inline]
158 pub fn pop(&mut self) -> Option<ElementSelector> {
159 self.path.pop()
160 }
161}
162
163impl Deref for ElementPathBuf {
164 type Target = ElementPath;
165
166 #[inline]
167 fn deref(&self) -> &Self::Target {
168 self.as_path()
169 }
170}
171
172impl DerefMut for ElementPathBuf {
173 #[inline]
174 fn deref_mut(&mut self) -> &mut Self::Target {
175 self.as_mut_path()
176 }
177}
178
179impl Borrow<ElementPath> for ElementPathBuf {
180 #[inline]
181 fn borrow(&self) -> &ElementPath {
182 self.as_path()
183 }
184}
185
186impl BorrowMut<ElementPath> for ElementPathBuf {
187 #[inline]
188 fn borrow_mut(&mut self) -> &mut ElementPath {
189 self.as_mut_path()
190 }
191}
192
193impl AsRef<ElementPath> for ElementPathBuf {
194 #[inline]
195 fn as_ref(&self) -> &ElementPath {
196 self.as_path()
197 }
198}
199
200impl AsMut<ElementPath> for ElementPathBuf {
201 #[inline]
202 fn as_mut(&mut self) -> &mut ElementPath {
203 self.as_mut_path()
204 }
205}
206
207impl AsRef<[ElementSelector]> for ElementPathBuf {
208 #[inline]
209 fn as_ref(&self) -> &[ElementSelector] {
210 self.as_slice()
211 }
212}
213
214impl AsMut<[ElementSelector]> for ElementPathBuf {
215 #[inline]
216 fn as_mut(&mut self) -> &mut [ElementSelector] {
217 self.as_mut_slice()
218 }
219}
220
221impl IntoIterator for ElementPathBuf {
222 type IntoIter = std::vec::IntoIter<ElementSelector>;
223 type Item = ElementSelector;
224
225 #[inline]
226 fn into_iter(self) -> Self::IntoIter {
227 self.path.into_iter()
228 }
229}
230
231impl<'p> IntoIterator for &'p ElementPathBuf {
232 type IntoIter = slice::Iter<'p, ElementSelector>;
233 type Item = &'p ElementSelector;
234
235 #[inline]
236 fn into_iter(self) -> Self::IntoIter {
237 self.iter()
238 }
239}
240
241impl<'p> IntoIterator for &'p mut ElementPathBuf {
242 type IntoIter = slice::IterMut<'p, ElementSelector>;
243 type Item = &'p mut ElementSelector;
244
245 #[inline]
246 fn into_iter(self) -> Self::IntoIter {
247 self.iter_mut()
248 }
249}
250
251impl PartialEq<ElementPath> for ElementPathBuf {
252 #[inline]
253 fn eq(&self, other: &ElementPath) -> bool {
254 self.as_path() == other
255 }
256}
257
258impl PartialEq<&ElementPath> for ElementPathBuf {
259 #[inline]
260 fn eq(&self, other: &&ElementPath) -> bool {
261 self.as_path() == *other
262 }
263}
264
265impl PartialEq<&mut ElementPath> for ElementPathBuf {
266 #[inline]
267 fn eq(&self, other: &&mut ElementPath) -> bool {
268 self.as_path() == *other
269 }
270}
271
272impl<'p> ElementIndex for ElementPathBuf {
273 type PathSelectors = std::vec::IntoIter<ElementSelector>;
274
275 #[inline]
276 fn path_selectors(self) -> Self::PathSelectors {
277 self.into_iter()
278 }
279}
280
281impl<'p> ElementIndex for &'p ElementPathBuf {
282 type PathSelectors = iter::Copied<slice::Iter<'p, ElementSelector>>;
283
284 #[inline]
285 fn path_selectors(self) -> Self::PathSelectors {
286 self.iter().copied()
287 }
288}
289
290impl<'p> ElementIndex for &'p mut ElementPathBuf {
291 type PathSelectors = iter::Copied<slice::Iter<'p, ElementSelector>>;
292
293 #[inline]
294 fn path_selectors(self) -> Self::PathSelectors {
295 self.iter().copied()
296 }
297}
298
299#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
301#[repr(transparent)]
302pub struct ElementPath {
303 path: [ElementSelector],
304}
305
306impl ElementPath {
307 pub const EMPTY: &ElementPath = ElementPath::from_slice(&[]);
309
310 #[inline]
312 pub const fn from_slice<'p>(slice: &'p [ElementSelector]) -> &'p Self {
313 unsafe { mem::transmute(slice) }
316 }
317
318 #[inline]
320 pub fn from_mut_slice<'p>(slice: &'p mut [ElementSelector]) -> &'p mut Self {
321 unsafe { mem::transmute(slice) }
324 }
325
326 #[inline]
328 pub const fn len(&self) -> usize {
329 self.path.len()
330 }
331
332 #[inline]
334 pub fn to_buf(&self) -> ElementPathBuf {
335 ElementPathBuf::from_path(self)
336 }
337
338 #[inline]
340 pub const fn as_slice(&self) -> &[ElementSelector] {
341 &self.path
342 }
343
344 #[inline]
346 pub fn as_mut_slice(&mut self) -> &mut [ElementSelector] {
347 &mut self.path
348 }
349
350 #[inline]
352 pub fn iter(&self) -> slice::Iter<ElementSelector> {
353 self.as_slice().iter()
354 }
355
356 #[inline]
358 pub fn iter_mut(&mut self) -> slice::IterMut<ElementSelector> {
359 self.as_mut_slice().iter_mut()
360 }
361
362 pub const fn parent(&self) -> Option<&ElementPath> {
365 match self.path.split_last() {
366 Some((_, head)) => Some(ElementPath::from_slice(head)),
367 None => None,
368 }
369 }
370
371 #[inline]
373 pub const fn last(&self) -> Option<ElementSelector> {
374 match self.path.last() {
375 Some(last) => Some(*last),
376 None => None,
377 }
378 }
379
380 #[inline]
382 pub fn last_mut(&mut self) -> Option<&mut ElementSelector> {
383 self.path.last_mut()
384 }
385}
386
387impl AsRef<[ElementSelector]> for ElementPath {
388 #[inline]
389 fn as_ref(&self) -> &[ElementSelector] {
390 self.as_slice()
391 }
392}
393
394impl AsMut<[ElementSelector]> for ElementPath {
395 #[inline]
396 fn as_mut(&mut self) -> &mut [ElementSelector] {
397 self.as_mut_slice()
398 }
399}
400
401impl ToOwned for ElementPath {
402 type Owned = ElementPathBuf;
403
404 #[inline]
405 fn to_owned(&self) -> Self::Owned {
406 self.to_buf()
407 }
408}
409
410impl<'p> IntoIterator for &'p ElementPath {
411 type IntoIter = slice::Iter<'p, ElementSelector>;
412 type Item = &'p ElementSelector;
413
414 #[inline]
415 fn into_iter(self) -> Self::IntoIter {
416 self.iter()
417 }
418}
419
420impl<'p> IntoIterator for &'p mut ElementPath {
421 type IntoIter = slice::IterMut<'p, ElementSelector>;
422 type Item = &'p mut ElementSelector;
423
424 #[inline]
425 fn into_iter(self) -> Self::IntoIter {
426 self.iter_mut()
427 }
428}
429
430impl<'p> ElementIndex for &'p ElementPath {
431 type PathSelectors = iter::Copied<slice::Iter<'p, ElementSelector>>;
432
433 #[inline]
434 fn path_selectors(self) -> Self::PathSelectors {
435 self.iter().copied()
436 }
437}
438
439impl<'p> ElementIndex for &'p mut ElementPath {
440 type PathSelectors = iter::Copied<slice::Iter<'p, ElementSelector>>;
441
442 #[inline]
443 fn path_selectors(self) -> Self::PathSelectors {
444 self.iter().copied()
445 }
446}
447
448impl PartialEq<ElementPathBuf> for ElementPath {
449 #[inline]
450 fn eq(&self, other: &ElementPathBuf) -> bool {
451 self == other.as_path()
452 }
453}
454
455impl PartialEq<ElementPathBuf> for &ElementPath {
456 #[inline]
457 fn eq(&self, other: &ElementPathBuf) -> bool {
458 *self == other.as_path()
459 }
460}
461
462impl PartialEq<ElementPathBuf> for &mut ElementPath {
463 #[inline]
464 fn eq(&self, other: &ElementPathBuf) -> bool {
465 *self == other.as_path()
466 }
467}
468
469pub trait ElementIndex {
471 type PathSelectors: Iterator<Item = ElementSelector>
472 + DoubleEndedIterator
473 + ExactSizeIterator
474 + iter::FusedIterator;
475
476 fn path_selectors(self) -> Self::PathSelectors;
477}
478
479impl ElementIndex for bool {
480 type PathSelectors = iter::Once<ElementSelector>;
481
482 #[inline]
483 fn path_selectors(self) -> Self::PathSelectors {
484 ElementSelector::from(self).path_selectors()
485 }
486}
487
488impl ElementIndex for usize {
489 type PathSelectors = iter::Once<ElementSelector>;
490
491 #[inline]
492 fn path_selectors(self) -> Self::PathSelectors {
493 ElementSelector::from(self).path_selectors()
494 }
495}
496
497macro_rules! tuple_element_index {
498 ($($t:ident),* $(,)?) => {
499 impl<$($t),*> ElementIndex for ($($t,)*)
500 where $($t: Into<ElementSelector>,)*
501 {
502 type PathSelectors = array::IntoIter<ElementSelector, {count_repetition!($($t,)*)}>;
503
504 fn path_selectors(self) -> Self::PathSelectors {
505 #[allow(non_snake_case)]
506 let ($($t,)*) = self;
507 [$($t.into(),)*].into_iter()
508 }
509 }
510 };
511}
512
513tuple_element_index!();
514tuple_element_index!(A);
515tuple_element_index!(A, B);
516tuple_element_index!(A, B, C);
517tuple_element_index!(A, B, C, D);
518tuple_element_index!(A, B, C, D, E);
519tuple_element_index!(A, B, C, D, E, F);
520tuple_element_index!(A, B, C, D, E, F, G);
521tuple_element_index!(A, B, C, D, E, F, G, H);
522tuple_element_index!(A, B, C, D, E, F, G, H, I);
523tuple_element_index!(A, B, C, D, E, F, G, H, I, J);