use std::collections::HashSet;
use std::ops::{BitOr, BitAnd, BitXor, Sub, BitOrAssign, BitAndAssign, BitXorAssign, SubAssign};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HashSetExt<T: Eq + std::hash::Hash>(pub HashSet<T>);
impl<T: Eq + std::hash::Hash> From<Vec<T>> for HashSetExt<T> {
fn from(vec: Vec<T>) -> Self {
HashSetExt(vec.into_iter().collect())
}
}
impl<T: Eq + std::hash::Hash> From<HashSet<T>> for HashSetExt<T> {
fn from(set: HashSet<T>) -> Self {
HashSetExt(set)
}
}
impl<'a, 'b, T: Eq + std::hash::Hash + Clone> BitOr<&'b HashSetExt<T>> for &'a HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitor(self, other: &'b HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.union(&other.0).cloned().collect())
}
}
impl<'a, T: Eq + std::hash::Hash + Clone> BitOr<HashSetExt<T>> for &'a HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitor(self, other: HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.union(&other.0).cloned().collect())
}
}
impl<'b, T: Eq + std::hash::Hash + Clone> BitOr<&'b HashSetExt<T>> for HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitor(self, other: &'b HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.union(&other.0).cloned().collect())
}
}
impl<'a, 'b, T: Eq + std::hash::Hash + Clone> BitAnd<&'b HashSetExt<T>> for &'a HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitand(self, other: &'b HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.intersection(&other.0).cloned().collect())
}
}
impl<'a, T: Eq + std::hash::Hash + Clone> BitAnd<HashSetExt<T>> for &'a HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitand(self, other: HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.intersection(&other.0).cloned().collect())
}
}
impl<'b, T: Eq + std::hash::Hash + Clone> BitAnd<&'b HashSetExt<T>> for HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitand(self, other: &'b HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.intersection(&other.0).cloned().collect())
}
}
impl<'a, 'b, T: Eq + std::hash::Hash + Clone> Sub<&'b HashSetExt<T>> for &'a HashSetExt<T> {
type Output = HashSetExt<T>;
fn sub(self, other: &'b HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.difference(&other.0).cloned().collect())
}
}
impl<'a, T: Eq + std::hash::Hash + Clone> Sub<HashSetExt<T>> for &'a HashSetExt<T> {
type Output = HashSetExt<T>;
fn sub(self, other: HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.difference(&other.0).cloned().collect())
}
}
impl<'b, T: Eq + std::hash::Hash + Clone> Sub<&'b HashSetExt<T>> for HashSetExt<T> {
type Output = HashSetExt<T>;
fn sub(self, other: &'b HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.difference(&other.0).cloned().collect())
}
}
impl<'a, 'b, T: Eq + std::hash::Hash + Clone> BitXor<&'b HashSetExt<T>> for &'a HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitxor(self, other: &'b HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.symmetric_difference(&other.0).cloned().collect())
}
}
impl<'a, T: Eq + std::hash::Hash + Clone> BitXor<HashSetExt<T>> for &'a HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitxor(self, other: HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.symmetric_difference(&other.0).cloned().collect())
}
}
impl<'b, T: Eq + std::hash::Hash + Clone> BitXor<&'b HashSetExt<T>> for HashSetExt<T> {
type Output = HashSetExt<T>;
fn bitxor(self, other: &'b HashSetExt<T>) -> Self::Output {
HashSetExt(self.0.symmetric_difference(&other.0).cloned().collect())
}
}
impl<T: Eq + std::hash::Hash + Clone> BitOrAssign for HashSetExt<T> {
fn bitor_assign(&mut self, other: Self) {
self.0.extend(other.0);
}
}
impl<T: Eq + std::hash::Hash + Clone> BitAndAssign for HashSetExt<T> {
fn bitand_assign(&mut self, other: Self) {
self.0 = self.0.intersection(&other.0).cloned().collect();
}
}
impl<T: Eq + std::hash::Hash + Clone> SubAssign for HashSetExt<T> {
fn sub_assign(&mut self, other: Self) {
self.0 = self.0.difference(&other.0).cloned().collect();
}
}
impl<T: Eq + std::hash::Hash + Clone> BitXorAssign for HashSetExt<T> {
fn bitxor_assign(&mut self, other: Self) {
self.0 = self.0.symmetric_difference(&other.0).cloned().collect();
}
}