#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct NodeFlags(u8);
impl NodeFlags {
pub const F_EXACT: u8 = 1;
pub const F_RELAXED: u8 = 2;
pub const F_MARKED: u8 = 4;
pub const F_CUTSET: u8 = 8;
#[allow(dead_code)]
#[inline]
pub fn new(relaxed: bool) -> Self {
if relaxed {
Self::new_relaxed()
} else {
Self::new_exact()
}
}
#[inline]
pub fn new_exact() -> Self {
NodeFlags(NodeFlags::F_EXACT)
}
#[inline]
pub fn new_relaxed() -> Self {
NodeFlags(NodeFlags::F_RELAXED)
}
#[inline]
pub fn is_exact(self) -> bool {
self.test(NodeFlags::F_EXACT) && !self.test(NodeFlags::F_RELAXED)
}
#[inline]
pub fn is_relaxed(self) -> bool {
self.test(NodeFlags::F_RELAXED)
}
#[inline]
pub fn is_marked(self) -> bool {
self.test(NodeFlags::F_MARKED)
}
#[allow(dead_code)]
#[inline]
pub fn is_cutset(self) -> bool {
self.test(NodeFlags::F_CUTSET)
}
#[inline]
pub fn set_exact(&mut self, exact: bool) {
self.set(NodeFlags::F_EXACT, exact)
}
#[inline]
pub fn set_relaxed(&mut self, relaxed: bool) {
self.set(NodeFlags::F_RELAXED, relaxed)
}
#[inline]
pub fn set_marked(&mut self, marked: bool) {
self.set(NodeFlags::F_MARKED, marked)
}
#[inline]
pub fn set_cutset(&mut self, cutset: bool) {
self.set(NodeFlags::F_CUTSET, cutset)
}
#[inline]
pub fn test(self, mask: u8) -> bool {
self.0 & mask == mask
}
#[inline]
pub fn set(&mut self, flag: u8, value: bool) {
if value {
self.add(flag)
} else {
self.remove(flag)
}
}
#[inline]
pub fn add(&mut self, flags: u8) {
self.0 |= flags;
}
#[inline]
pub fn remove(&mut self, flags: u8) {
self.0 &= !flags;
}
}
impl Default for NodeFlags {
fn default() -> Self {
NodeFlags::new_exact()
}
}
#[cfg(test)]
#[allow(clippy::bool_assert_comparison)]
mod test_node_flags {
use super::NodeFlags;
#[test]
fn new_can_be_relaxed_or_not() {
let tested = NodeFlags::new_exact();
assert_eq!(NodeFlags(NodeFlags::F_EXACT), tested);
assert_eq!(true, tested.is_exact());
assert_eq!(false, tested.is_relaxed());
let tested = NodeFlags::new_relaxed();
assert_eq!(NodeFlags(NodeFlags::F_RELAXED), tested);
assert_eq!(false, tested.is_exact());
assert_eq!(true, tested.is_relaxed());
assert_eq!(NodeFlags::new(false), NodeFlags::new_exact());
assert_eq!(NodeFlags::new(true), NodeFlags::new_relaxed());
}
#[test]
fn at_creation_time_marked_flag_is_never_set() {
let tested = NodeFlags::new(false);
assert_eq!(false, tested.is_marked());
let tested = NodeFlags::new(true);
assert_eq!(false, tested.is_marked());
}
#[test]
fn is_relaxed_iff_created_or_marked_relaxed() {
let mut tested = NodeFlags::new_relaxed();
assert_eq!(true, tested.is_relaxed());
tested.set_relaxed(false);
assert_eq!(false, tested.is_relaxed());
tested.set_relaxed(true);
assert_eq!(true, tested.is_relaxed());
let mut tested = NodeFlags::new_exact();
assert_eq!(false, tested.is_relaxed());
tested.set_relaxed(true);
assert_eq!(true, tested.is_relaxed());
tested.set_relaxed(false);
assert_eq!(false, tested.is_relaxed());
}
#[test]
fn is_exact_iff_marked_so_and_not_relaxed() {
let mut tested = NodeFlags::new_exact();
assert_eq!(true, tested.is_exact());
tested.set_exact(false);
assert_eq!(false, tested.is_exact());
tested.set_exact(true);
assert_eq!(true, tested.is_exact());
tested.set_relaxed(true);
assert_eq!(false, tested.is_exact());
tested.set_exact(false);
assert_eq!(false, tested.is_exact());
tested.set_exact(true);
assert_eq!(false, tested.is_exact());
}
#[test]
fn is_marked_iff_marked_so() {
let mut tested = NodeFlags::new_exact();
assert_eq!(false, tested.is_marked());
tested.set_marked(true);
assert_eq!(true, tested.is_marked());
tested.set_marked(false);
assert_eq!(false, tested.is_marked());
tested.set_marked(true);
assert_eq!(true, tested.is_marked());
}
#[test]
fn test_yields_the_value_of_the_flag() {
let mut tested = NodeFlags::new_exact();
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
tested.set_relaxed(true);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
tested.set_marked(true);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
tested.set_exact(false);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
tested.set_relaxed(false);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
tested.set_marked(false);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
}
#[test]
fn test_checks_the_value_of_more_than_one_flag() {
let mut tested = NodeFlags::new_exact();
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
assert_eq!(false, tested.test(NodeFlags::F_EXACT | NodeFlags::F_MARKED));
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
tested.set_marked(true);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
assert_eq!(true, tested.test(NodeFlags::F_EXACT | NodeFlags::F_MARKED));
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
tested.set_relaxed(true);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
assert_eq!(true, tested.test(NodeFlags::F_EXACT | NodeFlags::F_MARKED));
assert_eq!(true, tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED));
assert_eq!(
true,
tested.test(NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
assert_eq!(
true,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
let mut tested = NodeFlags::new_exact();
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
assert_eq!(false, tested.test(NodeFlags::F_EXACT | NodeFlags::F_MARKED));
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
tested.set_marked(true);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
assert_eq!(true, tested.test(NodeFlags::F_EXACT | NodeFlags::F_MARKED));
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
tested.set_exact(false);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
assert_eq!(false, tested.test(NodeFlags::F_EXACT | NodeFlags::F_MARKED));
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
tested.set_relaxed(false);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
assert_eq!(false, tested.test(NodeFlags::F_EXACT | NodeFlags::F_MARKED));
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
tested.set_marked(false);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
assert_eq!(false, tested.test(NodeFlags::F_EXACT | NodeFlags::F_MARKED));
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
assert_eq!(
false,
tested.test(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED)
);
}
#[test]
fn add_turns_one_or_more_flags_on() {
let mut tested = NodeFlags(0);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
tested.add(NodeFlags::F_EXACT);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.add(NodeFlags::F_RELAXED);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.add(NodeFlags::F_MARKED);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.add(NodeFlags::F_EXACT | NodeFlags::F_MARKED);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.add(NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.add(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
}
#[test]
fn remove_turns_one_or_more_flags_off() {
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
tested.remove(NodeFlags::F_EXACT);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.remove(NodeFlags::F_RELAXED);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.remove(NodeFlags::F_MARKED);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.remove(NodeFlags::F_EXACT | NodeFlags::F_MARKED);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.remove(NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.remove(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
}
#[test]
fn set_turns_one_or_more_flags_on_or_off() {
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
tested.set(NodeFlags::F_EXACT, false);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.set(NodeFlags::F_RELAXED, false);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.set(NodeFlags::F_MARKED, false);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.set(NodeFlags::F_EXACT | NodeFlags::F_MARKED, false);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.set(NodeFlags::F_RELAXED | NodeFlags::F_MARKED, false);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED);
tested.set(
NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED,
false,
);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.set(NodeFlags::F_EXACT, true);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.set(NodeFlags::F_RELAXED, true);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(false, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.set(NodeFlags::F_MARKED, true);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.set(NodeFlags::F_EXACT | NodeFlags::F_MARKED, true);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(false, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.set(NodeFlags::F_RELAXED | NodeFlags::F_MARKED, true);
assert_eq!(false, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
let mut tested = NodeFlags(0);
tested.set(
NodeFlags::F_EXACT | NodeFlags::F_RELAXED | NodeFlags::F_MARKED,
true,
);
assert_eq!(true, tested.test(NodeFlags::F_EXACT));
assert_eq!(true, tested.test(NodeFlags::F_RELAXED));
assert_eq!(true, tested.test(NodeFlags::F_MARKED));
}
#[test]
fn by_default_only_the_exact_flag_is_on() {
assert_eq!(true, NodeFlags::default().test(NodeFlags::F_EXACT));
assert_eq!(false, NodeFlags::default().test(NodeFlags::F_RELAXED));
assert_eq!(false, NodeFlags::default().test(NodeFlags::F_MARKED));
}
}