1use std::ops::{Add, Not, Sub};
2
3#[derive(Default, Debug, PartialEq)]
5pub enum Effect {
6 #[default]
7 None,
8 Apply,
9 Clear,
10}
11
12impl Effect {
13 pub fn is_set(&self) -> bool {
14 !matches!(self, Effect::None)
15 }
16
17 pub fn is_unset(&self) -> bool {
18 !self.is_set()
19 }
20}
21
22impl Add for Effect {
23 type Output = Effect;
24
25 fn add(self, rhs: Self) -> Self::Output {
26 match (self, rhs) {
27 (Effect::None, Effect::None) => Effect::None,
28 (Effect::None, Effect::Apply) => Effect::Apply,
29 (Effect::None, Effect::Clear) => Effect::None,
30 (Effect::Apply, Effect::None) => Effect::Apply,
31 (Effect::Apply, Effect::Apply) => Effect::Apply,
32 (Effect::Apply, Effect::Clear) => Effect::Clear,
33 (Effect::Clear, Effect::None) => Effect::Clear,
34 (Effect::Clear, Effect::Apply) => Effect::Apply,
35 (Effect::Clear, Effect::Clear) => Effect::Clear,
36 }
37 }
38}
39
40impl Sub for Effect {
41 type Output = Effect;
42
43 fn sub(self, rhs: Self) -> Self::Output {
44 match (self, rhs) {
45 (Effect::None, _) => Effect::None,
46 (Effect::Apply, Effect::Apply) => Effect::None,
47 (Effect::Clear, Effect::Clear) => Effect::None,
48 (Effect::Apply, _) => Effect::Apply,
49 (Effect::Clear, Effect::None) => Effect::None,
50 (Effect::Clear, _) => Effect::Clear,
51 }
52 }
53}
54
55impl Not for Effect {
56 type Output = Effect;
57
58 fn not(self) -> Self::Output {
59 match self {
60 Effect::None => Effect::None,
61 Effect::Apply => Effect::Clear,
62 Effect::Clear => Effect::None,
63 }
64 }
65}
66
67impl From<(bool, bool)> for Effect {
68 fn from(value: (bool, bool)) -> Self {
69 match value {
70 (false, false) => Effect::None,
71 (true, false) => Effect::Apply,
72 (false, true) => Effect::Clear,
73 _ => unreachable!("Invalid Effect"),
74 }
75 }
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Default)]
81pub enum DuoEffect {
82 #[default]
83 None,
85 A,
87 B,
89 AB,
91 BA,
93 AE,
94 BE,
95 E,
97}
98
99impl DuoEffect {
100 pub fn is_set(&self) -> bool {
102 !matches!(self, DuoEffect::None)
103 }
104
105 pub fn is_unset(&self) -> bool {
107 !self.is_set()
108 }
109}
110
111impl Add for DuoEffect {
112 type Output = DuoEffect;
113
114 fn add(self, rhs: Self) -> Self::Output {
118 match (self, rhs) {
119 (DuoEffect::None, DuoEffect::E | DuoEffect::AE | DuoEffect::BE) => DuoEffect::None,
121 (DuoEffect::None, rhs) => rhs,
123 (lhs, DuoEffect::None) => lhs,
125 (DuoEffect::E, rhs) => rhs,
126 (DuoEffect::A | DuoEffect::BA | DuoEffect::AE, DuoEffect::E) => DuoEffect::AE,
128 (DuoEffect::B | DuoEffect::AB | DuoEffect::BE, DuoEffect::E) => DuoEffect::BE,
130 (DuoEffect::A | DuoEffect::BA, DuoEffect::A) => DuoEffect::A,
132 (DuoEffect::B | DuoEffect::AB, DuoEffect::B) => DuoEffect::B,
134 (DuoEffect::A | DuoEffect::BA, DuoEffect::B) => DuoEffect::AB,
136 (DuoEffect::B | DuoEffect::AB, DuoEffect::A) => DuoEffect::BA,
138 (DuoEffect::A | DuoEffect::BA, DuoEffect::AE) => DuoEffect::AE,
140 (DuoEffect::B | DuoEffect::AB, DuoEffect::BE) => DuoEffect::BE,
142
143 (DuoEffect::AE, DuoEffect::B) => DuoEffect::AB,
144 (DuoEffect::BE, DuoEffect::A) => DuoEffect::BA,
145 (lhs, DuoEffect::AE) => lhs,
147 (lhs, DuoEffect::BE) => lhs,
149 (_, rhs) => rhs,
151 }
152 }
153}
154
155impl Sub for DuoEffect {
156 type Output = DuoEffect;
157
158 fn sub(self, rhs: Self) -> Self::Output {
161 match (self, rhs) {
162 (DuoEffect::E, DuoEffect::None) => DuoEffect::None,
163 (DuoEffect::None | DuoEffect::E, _) => self,
165 (lhs, DuoEffect::None | DuoEffect::E) => lhs,
167 (DuoEffect::A, DuoEffect::A | DuoEffect::BA) => DuoEffect::None,
169 (DuoEffect::B, DuoEffect::A | DuoEffect::BA) => DuoEffect::AB,
171 (DuoEffect::A, DuoEffect::B | DuoEffect::AB) => DuoEffect::BA,
172 (DuoEffect::B, DuoEffect::B | DuoEffect::AB) => DuoEffect::None,
173 (DuoEffect::AE, DuoEffect::A | DuoEffect::BA) => DuoEffect::AE,
174 (DuoEffect::BE, DuoEffect::B | DuoEffect::AB) => DuoEffect::BE,
175 (DuoEffect::AE, _) => DuoEffect::None,
176 (DuoEffect::BE, _) => DuoEffect::None,
177 (lhs, _) => lhs,
178 }
179 }
180}
181
182impl Not for DuoEffect {
183 type Output = DuoEffect;
184
185 fn not(self) -> Self::Output {
186 match self {
187 DuoEffect::None => DuoEffect::None,
188 DuoEffect::A | DuoEffect::BA => DuoEffect::AE,
189 DuoEffect::B | DuoEffect::AB => DuoEffect::BE,
190 DuoEffect::E | DuoEffect::AE | DuoEffect::BE => DuoEffect::None,
191 }
192 }
193}
194
195impl From<(bool, bool, bool)> for DuoEffect {
196 fn from(value: (bool, bool, bool)) -> Self {
197 match value {
198 (false, false, false) => DuoEffect::None,
199 (true, false, false) => DuoEffect::A,
200 (false, true, false) => DuoEffect::B,
201 (true, true, false) => DuoEffect::AB,
202 (false, false, true) => DuoEffect::BA,
203 (false, true, true) => DuoEffect::AE,
204 (true, false, true) => DuoEffect::BE,
205 (true, true, true) => DuoEffect::E,
206 }
207 }
208}