pub trait PowerBool {
#[inline(always)]
fn raise(&mut self) -> bool {
self.set(true)
}
#[inline(always)]
fn lower(&mut self) -> bool {
self.set(false)
}
#[inline(always)]
fn set(&mut self, val: bool) -> bool;
#[inline(always)]
fn trip(&mut self, val: bool) -> bool;
#[inline(always)]
fn kick(&mut self) -> bool {
!self.set(false)
}
#[inline(always)]
fn punch(&mut self) -> bool {
!self.set(true)
}
}
impl PowerBool for bool {
#[inline(always)]
fn set(&mut self, val: bool) -> bool {
let ret = *self != val;
*self = val;
ret
}
#[inline(always)]
fn trip(&mut self, val: bool) -> bool {
let ret = val && !*self;
if ret {
*self = true;
}
ret
}
}
#[cfg(test)]
mod test_powerbool {
use super::PowerBool;
fn truth_table_row<F: Fn(&mut bool) -> bool>(before: bool, f: F, returns: bool, after: bool) {
let mut v = before;
assert_eq!(f(&mut v), returns);
assert_eq!(v, after);
}
#[test]
fn set() {
fn set_true(v: &mut bool) -> bool { v.set(true) }
fn set_false(v: &mut bool) -> bool { v.set(false) }
truth_table_row(true, set_true, false, true);
truth_table_row(true, set_false, true, false);
truth_table_row(false, set_true, true, true);
truth_table_row(false, set_false, false, false);
}
#[test]
fn raise() {
truth_table_row(true, bool::raise, false, true);
truth_table_row(false, bool::raise, true, true);
}
#[test]
fn lower() {
truth_table_row(true, bool::lower, true, false);
truth_table_row(false, bool::lower, false, false);
}
#[test]
fn trip() {
fn trip_true(v: &mut bool) -> bool { v.trip(true) }
fn trip_false(v: &mut bool) -> bool { v.trip(false) }
truth_table_row(true, trip_true, false, true);
truth_table_row(true, trip_false, false, true);
truth_table_row(false, trip_true, true, true);
truth_table_row(false, trip_false, false, false);
}
#[test]
fn kick() {
truth_table_row(false, bool::kick, true, false);
truth_table_row(true, bool::kick, false, false);
}
#[test]
fn punch() {
truth_table_row(false, bool::punch, false, true);
truth_table_row(true, bool::punch, true, true);
}
}
pub trait Change {
#[inline(always)]
fn change(&mut self, v: Self) -> bool;
}
impl<T: PartialEq> Change for T {
#[inline(always)]
fn change(&mut self, v: Self) -> bool {
if self != &v {
*self = v;
true
} else {
false
}
}
}
#[cfg(test)]
mod test_change {
use super::Change;
#[test]
fn works() {
let mut x = 1;
assert!(x.change(2));
}
#[test]
fn still_works() {
let mut x = 1;
assert!(!x.change(1));
}
}