#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
use std::collections::HashSet;
use super::FlagSet;
let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
let flag_ap = FlagSet(a.clone(), true);
let flag_an = FlagSet(a.clone(), false);
let flag_bp = FlagSet(b.clone(), true);
let flag_bn = FlagSet(b.clone(), false);
assert_eq!(flag_bn, FlagSet::new(vec![2, 3, 4], false));
assert!(flag_an.contains(4));
assert_eq!(FlagSet::new(vec![1, 2, 3, 4], true), flag_ap.clone() + flag_bp.clone());
assert_eq!(FlagSet::new(vec![4], false), flag_ap.clone() + flag_bn.clone());
assert_eq!(FlagSet::new(vec![1], false), flag_an.clone() + flag_bp.clone());
assert_eq!(FlagSet::new(vec![2, 3], false), flag_an.clone() + flag_bn.clone());
assert_eq!(FlagSet::new(vec![2, 3], true), flag_ap.clone() & flag_bp.clone());
assert_eq!(FlagSet::new(vec![1], true), flag_ap.clone() & flag_bn.clone());
assert_eq!(FlagSet::new(vec![4], true), flag_an.clone() & flag_bp.clone());
assert_eq!(FlagSet::new(vec![1, 2, 3, 4], false), flag_an.clone() & flag_bn.clone());
assert_eq!(FlagSet::new(vec![1], true), flag_ap.clone() - flag_bp.clone());
assert_eq!(FlagSet::new(vec![2, 3], true), flag_ap.clone() - flag_bn.clone());
assert_eq!(FlagSet::new(vec![1, 2, 3, 4], false), flag_an.clone() - flag_bp.clone());
assert_eq!(FlagSet::new(vec![4], true), flag_an.clone() - flag_bn.clone());
assert_eq!(FlagSet(a.clone(), true), !flag_an.clone());
assert_eq!(FlagSet::new(vec![1, 4], true), flag_ap.clone() ^ flag_bp.clone());
}
}
use std::collections::HashSet;
use std::hash::Hash;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct FlagSet<T: Eq + Hash>(HashSet<T>, bool);
impl<T: Eq + Hash> Default for FlagSet<T> {
fn default() -> Self {
Self(HashSet::<T>::with_capacity(0), true)
}
}
impl<'a, T: Eq + Hash + Clone> FlagSet<T> {
pub fn new(vector: Vec<T>, flag: bool) -> Self {
Self(vector.into_iter().collect(), flag)
}
pub fn contains(&self, value: T) -> bool {
!(self.0.contains(&value) ^ self.1)
}
}
use std::ops::{Add, BitAnd, Not, Sub, BitXor};
impl<T: Eq + Hash + Clone> Add for FlagSet<T> {
type Output = Self;
fn add(self, other: Self) -> Self::Output {
match (self, other) {
(FlagSet(A, true), FlagSet(B, true)) => Self(&A | &B, true),
(FlagSet(A, true), FlagSet(B, false)) => Self(&B - &A, false),
(FlagSet(A, false), FlagSet(B, true)) => Self(&A - &B, false),
(FlagSet(A, false), FlagSet(B, false)) => Self(&A & &B, false),
}
}
}
impl<T: Eq + Hash + Clone> BitAnd for FlagSet<T> {
type Output = Self;
fn bitand(self, other: Self) -> Self::Output {
match (self, other) {
(FlagSet(A, true), FlagSet(B, true)) => Self(&A & &B, true),
(FlagSet(A, true), FlagSet(B, false)) => Self(&A - &B, true),
(FlagSet(A, false), FlagSet(B, true)) => Self(&B - &A, true),
(FlagSet(A, false), FlagSet(B, false)) => Self(&A | &B, false),
}
}
}
impl<T: Eq + Hash + Clone> Sub for FlagSet<T> {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
match (self, other) {
(FlagSet(A, true), FlagSet(B, true)) => Self(&A - &B, true),
(FlagSet(A, true), FlagSet(B, false)) => Self(&A & &B, true),
(FlagSet(A, false), FlagSet(B, true)) => Self(&A | &B, false),
(FlagSet(A, false), FlagSet(B, false)) => Self(&B - &A, true),
}
}
}
impl<T: Eq + Hash + Clone> BitXor for FlagSet<T> {
type Output = Self;
fn bitxor(self, other: Self) -> Self::Output {
(self.clone() + other.clone()) - (self & other)
}
}
impl<T: Eq + Hash + Clone> Not for FlagSet<T> {
type Output = Self;
fn not(mut self) -> Self::Output {
self.1 = !self.1;
self
}
}