fidget_core/vm/
choice.rs

1/// A single choice made at a min/max node.
2///
3/// Explicitly stored in a `u8` so that this can be written by JIT functions,
4/// which have no notion of Rust enums.
5///
6/// Note that this is a bitfield such that
7/// ```rust
8/// # use fidget_core::vm::Choice;
9/// # assert!(
10/// Choice::Both as u8 == Choice::Left as u8 | Choice::Right as u8
11/// # );
12/// ```
13#[derive(Copy, Clone, Debug, Eq, PartialEq)]
14#[repr(u8)]
15pub enum Choice {
16    /// This choice has not yet been assigned
17    ///
18    /// A value of `Unknown` is invalid after evaluation
19    Unknown = 0,
20
21    /// The operation always picks the left-hand input
22    Left = 1,
23
24    /// The operation always picks the right-hand input
25    Right = 2,
26
27    /// The operation may pick either input
28    Both = 3,
29}
30
31impl std::ops::BitOrAssign<Choice> for Choice {
32    fn bitor_assign(&mut self, other: Self) {
33        *self = match (*self as u8) | (other as u8) {
34            0 => Self::Unknown,
35            1 => Self::Left,
36            2 => Self::Right,
37            3 => Self::Both,
38            _ => unreachable!(),
39        }
40    }
41}
42
43impl std::ops::Not for Choice {
44    type Output = Choice;
45    fn not(self) -> Self {
46        match self {
47            Self::Unknown => Self::Both,
48            Self::Left => Self::Right,
49            Self::Right => Self::Left,
50            Self::Both => Self::Unknown,
51        }
52    }
53}
54
55impl std::ops::BitAndAssign<Choice> for Choice {
56    fn bitand_assign(&mut self, other: Self) {
57        *self = match (*self as u8) | ((!other as u8) & 0b11) {
58            0 => Self::Unknown,
59            1 => Self::Left,
60            2 => Self::Right,
61            3 => Self::Both,
62            _ => unreachable!(),
63        }
64    }
65}