1pub trait PowerBool {
5 #[inline(always)]
7 fn raise(&mut self) -> bool {
8 self.set(true)
9 }
10
11 #[inline(always)]
13 fn lower(&mut self) -> bool {
14 self.set(false)
15 }
16
17 #[inline(always)]
24 fn set(&mut self, val: bool) -> bool;
25
26 #[inline(always)]
42 fn trip(&mut self, val: bool) -> bool;
43
44 #[inline(always)]
47 fn kick(&mut self) -> bool {
48 !self.set(false)
49 }
50
51 #[inline(always)]
54 fn punch(&mut self) -> bool {
55 !self.set(true)
56 }
57}
58
59impl PowerBool for bool {
60 #[inline(always)]
61 fn set(&mut self, val: bool) -> bool {
62 let ret = *self != val;
63 *self = val;
64 ret
65 }
66
67 #[inline(always)]
68 fn trip(&mut self, val: bool) -> bool {
69 let ret = val && !*self;
70 if ret {
71 *self = true;
72 }
73 ret
74 }
75}
76
77#[cfg(test)]
78mod test_powerbool {
79 use super::PowerBool;
92
93 fn truth_table_row<F: Fn(&mut bool) -> bool>(before: bool, f: F, returns: bool, after: bool) {
94 let mut v = before;
95 assert_eq!(f(&mut v), returns);
96 assert_eq!(v, after);
97 }
98
99 #[test]
100 fn set() {
101 fn set_true(v: &mut bool) -> bool { v.set(true) }
102 fn set_false(v: &mut bool) -> bool { v.set(false) }
103 truth_table_row(true, set_true, false, true);
104 truth_table_row(true, set_false, true, false);
105 truth_table_row(false, set_true, true, true);
106 truth_table_row(false, set_false, false, false);
107 }
108
109 #[test]
110 fn raise() {
111 truth_table_row(true, bool::raise, false, true);
112 truth_table_row(false, bool::raise, true, true);
113 }
114
115 #[test]
116 fn lower() {
117 truth_table_row(true, bool::lower, true, false);
118 truth_table_row(false, bool::lower, false, false);
119 }
120
121 #[test]
122 fn trip() {
123 fn trip_true(v: &mut bool) -> bool { v.trip(true) }
124 fn trip_false(v: &mut bool) -> bool { v.trip(false) }
125 truth_table_row(true, trip_true, false, true);
126 truth_table_row(true, trip_false, false, true);
127 truth_table_row(false, trip_true, true, true);
128 truth_table_row(false, trip_false, false, false);
129 }
130
131 #[test]
132 fn kick() {
133 truth_table_row(false, bool::kick, true, false);
134 truth_table_row(true, bool::kick, false, false);
135 }
136
137 #[test]
138 fn punch() {
139 truth_table_row(false, bool::punch, false, true);
140 truth_table_row(true, bool::punch, true, true);
141 }
142}
143
144pub trait Change {
145 #[inline(always)]
147 fn change(&mut self, v: Self) -> bool;
148}
149impl<T: PartialEq> Change for T {
150 #[inline(always)]
151 fn change(&mut self, v: Self) -> bool {
152 if self != &v {
153 *self = v;
154 true
155 } else {
156 false
157 }
158 }
159}
160
161#[cfg(test)]
162mod test_change {
163 use super::Change;
164
165 #[test]
166 fn works() {
167 let mut x = 1;
168 assert!(x.change(2));
169 }
170
171 #[test]
172 fn still_works() {
173 let mut x = 1;
174 assert!(!x.change(1));
175 }
176}