macro_rules! set_op_methods {
{$settype:ident} => {
pub fn intersection<'a>(&'a self, other: &'a $settype<T, S>) -> Intersection<'a, T, S> {
let (small, large) = sort_by_size(self, other);
Intersection {
iter: small.iter(),
other: large
}
}
pub fn difference<'a>(&'a self, other: &'a $settype<T, S>) -> Difference<'a, T, S> {
Difference {
iter: self.iter(),
other
}
}
pub fn union<'a>(&'a self, other: &'a $settype<T, S>) -> Union<'a, T, S> {
let (small, large) = sort_by_size(self, other);
Union {
iter: large.iter().chain(small.difference(large))
}
}
pub fn symmetric_difference<'a>(&'a self, other: &'a $settype<T, S>) -> SymmetricDifference<'a, T, S> {
SymmetricDifference {
iter: self.difference(other).chain(other.difference(self))
}
}
}
}
pub(crate) use set_op_methods;
macro_rules! set_op_types {
{$settype:ident where {$($wheres:tt)+} } => {
pub struct Intersection<'a, T, S> {
iter: Iter<'a, T>,
other: &'a $settype<T, S>,
}
impl<'a, T, S: BuildHasher> Iterator for Intersection<'a, T, S>
where $($wheres)+
{
type Item = T::Strong;
fn next(&mut self) -> Option<Self::Item> {
for item in &mut self.iter {
if self.other.contains_strong(&item) {
return Some(item);
}
}
return None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1)
}
}
pub struct Difference<'a, T, S> {
iter: Iter<'a, T>,
other: &'a $settype<T, S>,
}
impl<'a, T, S: BuildHasher> Iterator for Difference<'a, T, S>
where $($wheres)+
{
type Item = T::Strong;
fn next(&mut self) -> Option<Self::Item> {
for item in &mut self.iter {
if ! self.other.contains_strong(&item) {
return Some(item);
}
}
return None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1)
}
}
pub struct Union<'a, T, S> {
iter: iter::Chain<Iter<'a, T>, Difference<'a, T, S>>,
}
impl<'a, T, S:BuildHasher> Iterator for Union<'a, T, S>
where $($wheres)+
{
type Item = T::Strong;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
pub struct SymmetricDifference<'a, T, S> {
iter: iter::Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
}
impl<'a, T, S:BuildHasher> Iterator for SymmetricDifference<'a, T, S>
where $($wheres)+
{
type Item = T::Strong;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
}
}
pub(crate) use set_op_types;
macro_rules! single_set_op {
{ $settype:ident where {$($wheres:tt)+}
op: $op:ident,
method: $method:ident,
set_method: $set_method:ident $(,)?
} => {
impl<T, S: BuildHasher + Default> ops::$op<&$settype<T, S>> for &$settype<T, S>
where $($wheres)+
{
type Output = $settype<T, S>;
fn $method(self, other: &$settype<T,S>) -> Self::Output {
self.$set_method(other).collect()
}
}
}
}
pub(crate) use single_set_op;
macro_rules! set_operators {
{$settype:ident where {$($wheres:tt)+} } => {
single_set_op!{
$settype where {$($wheres)+}
op: BitAnd,
method: bitand,
set_method: intersection
}
single_set_op!{
$settype where {$($wheres)+}
op: BitOr,
method: bitor,
set_method: union
}
single_set_op!{
$settype where {$($wheres)+}
op: BitXor,
method: bitxor,
set_method: symmetric_difference
}
single_set_op!{
$settype where {$($wheres)+}
op: Sub,
method: sub,
set_method: difference
}
}
}
pub(crate) use set_operators;
macro_rules! set_relationships {
{$settype:ident} => {
pub fn is_superset(&self, other: &$settype<T, S>) -> bool {
other.is_subset(self)
}
pub fn is_disjoint(&self, other: &$settype<T, S>) -> bool {
let (small, large) = sort_by_size(self, other);
! small.iter().any(|t| large.contains_strong(&t))
}
}
}
pub(crate) use set_relationships;