feo3boy_opcodes/compiler/instr/flow/
path.rs

1use 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/// Selects a child [`Element`][super::Element] within an `Element`. The selector must
10/// match the parent type.
11#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
12pub enum ElementSelector {
13    /// Selects between the true and false paths of a [`Branch`][super::Branch].
14    Branch(bool),
15    /// Indexes into the children of a [`Block`][super::Block].
16    Block(usize),
17}
18
19impl ElementSelector {
20    /// Get this [`ElementSelector`] as an [`ElementPath`] slice.
21    #[inline]
22    pub fn as_path(&self) -> &ElementPath {
23        ElementPath::from_slice(slice::from_ref(self))
24    }
25
26    /// Get this [`ElementSelector`] as a mut [`ElementPath`] slice.
27    #[inline]
28    pub fn as_mut_path(&mut self) -> &mut ElementPath {
29        ElementPath::from_mut_slice(slice::from_mut(self))
30    }
31
32    /// Gets the branch boolean or panics.
33    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    /// Gets the block index or panics.
41    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    /// Mutably gets the branch boolean or panics.
49    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    /// Mutably gets the block index or panics.
57    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/// A path to a particular child [`Element`][super::Element].
103#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
104#[repr(transparent)]
105pub struct ElementPathBuf {
106    /// The sequence of selectors that lead to the element.
107    path: Vec<ElementSelector>,
108}
109
110impl ElementPathBuf {
111    /// Create a new empty element path buf.
112    #[inline]
113    pub fn new() -> Self {
114        Default::default()
115    }
116
117    /// Create a new selector by copying the given path.
118    pub fn from_path(path: &ElementPath) -> Self {
119        Self {
120            path: path.as_slice().to_vec(),
121        }
122    }
123
124    /// Get this [`ElementPathBuf`] as an [`ElementPath`] slice.
125    #[inline]
126    pub fn as_path(&self) -> &ElementPath {
127        ElementPath::from_slice(&self.path)
128    }
129
130    /// Get this [`ElementPathBuf`] as a mut [`ElementPath`] slice.
131    #[inline]
132    pub fn as_mut_path(&mut self) -> &mut ElementPath {
133        ElementPath::from_mut_slice(&mut self.path)
134    }
135
136    /// Push the given selector onto the end of this path.
137    #[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    /// Append another [`ElementIndex`] to the end of this path.
146    #[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    /// Pop the last element off of this path selector, transforming it into its parent.
155    /// Returns the [`ElementSelector`] that was popped, or `None` if the path was already
156    /// the root.
157    #[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/// A path to a particular child [`Element`][super::Element].
300#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
301#[repr(transparent)]
302pub struct ElementPath {
303    path: [ElementSelector],
304}
305
306impl ElementPath {
307    /// An empty element path.
308    pub const EMPTY: &ElementPath = ElementPath::from_slice(&[]);
309
310    /// Create an [`ElementPath`] ref from a slice of [`ElementSelector`].
311    #[inline]
312    pub const fn from_slice<'p>(slice: &'p [ElementSelector]) -> &'p Self {
313        // Safety: ElementPath is repr(transparent) to [ElementSelector], so transmuting
314        // from &[ElementSelector] to &ElementPath is safe.
315        unsafe { mem::transmute(slice) }
316    }
317
318    /// Create a mut [`ElementPath`] ref from a mut slice of [`ElementSelector`].
319    #[inline]
320    pub fn from_mut_slice<'p>(slice: &'p mut [ElementSelector]) -> &'p mut Self {
321        // Safety: ElementPath is repr(transparent) to [ElementSelector], so transmuting
322        // from &mut [ElementSelector] to &mut ElementPath is safe.
323        unsafe { mem::transmute(slice) }
324    }
325
326    /// Gets the number of [selectors][ElementSelector] in this [`ElementPath`].
327    #[inline]
328    pub const fn len(&self) -> usize {
329        self.path.len()
330    }
331
332    /// Creates an [`ElementPathBuf`] from this [`ElementPath`].
333    #[inline]
334    pub fn to_buf(&self) -> ElementPathBuf {
335        ElementPathBuf::from_path(self)
336    }
337
338    /// Get this [`ElementPath`] as a slice.
339    #[inline]
340    pub const fn as_slice(&self) -> &[ElementSelector] {
341        &self.path
342    }
343
344    /// Get this [`ElementPath`] as a mutable slice.
345    #[inline]
346    pub fn as_mut_slice(&mut self) -> &mut [ElementSelector] {
347        &mut self.path
348    }
349
350    /// Get an iterator over the selectors in this path.
351    #[inline]
352    pub fn iter(&self) -> slice::Iter<ElementSelector> {
353        self.as_slice().iter()
354    }
355
356    /// Get an iterator over mutable selectors in this path.
357    #[inline]
358    pub fn iter_mut(&mut self) -> slice::IterMut<ElementSelector> {
359        self.as_mut_slice().iter_mut()
360    }
361
362    /// Get the parent of this [`ElementPath`] if any. Returns `None` for the root (empty)
363    /// path.
364    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    /// Gets the last selector from the [`ElementPath`].
372    #[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    /// Mutably gets the last selector from the [`ElementPath`].
381    #[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
469/// Trait for types which can be used to index into an [`Element`][super::Element].
470pub 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);