ryley 0.1.1

Syntax unifies programmers
Documentation
//! Module `hash_set`
//! 
//! This module (which can be found in `structs`) contains the type `HashSet` which
//! is an unsorted `set`.
//! 
//! # Getting Started:
//! 
//! ## Create a new `HashSet`:
//! ```
//! # use ryley::structs::prelude::*;
//! let mut s: HashSet<i32>=HashSet::new();
//! ```
//! or
//! ```
//! # use ryley::structs::prelude::*;
//! let mut s: HashSet<i32>=hash_set![1,2,3,4,5];
//! ```
//! 
//! ## Utilitise `HashSet`:
//! ```
//! # use ryley::structs::prelude::*;
//! # let mut s: HashSet<i32>=hash_set![1,2,3,4,5];
//! s.add(12).add(7).add_slice(vec![9,8,6]);
//! 
//! assert!(s.contains_slice(&[3,6,9]));
//! ```
//! 
//! ## Remember that it contains 1 of each element!
//! 
//! Also it is an unsorted container, therefore its elements are organised randomly. If
//! sortedness or a stable order of elements is required you could use `OrdSet`instead.

use core::hash::{Hash,Hasher};
use core::fmt::{Display,Formatter,Result};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
use core::ops::{BitAnd,BitAndAssign,BitOr,BitOrAssign,BitXor,BitXorAssign};
use core::mem::swap;
use std::collections::hash_set::{Iter,IntoIter};
use core::cmp::Ordering;
use core::str::FromStr;

use super::algorithm::{CustomDisplay, CustomFromStr};
use super::UDSI::{Container, UniContainer, Unique};

/// Type `HashSet` is a thin wrapper for `std::collections::HashSet`
/// 
/// `HashSet` implements the Unified Data Structure Interface (or UDSI for short).
/// 
/// ## Beware
/// - `HashSet` is a unique container, therefore it contains 1 of each element
/// - `HashSet` is also an unsorted container, it contains elements in a random order
#[derive(Debug, Clone, Default)]
pub struct HashSet<T> {
    /// Internal storage of `HashSet`
    /// 
    /// Type `HashSet` is actually a thin wrapper for `std::collections::HashSet`.
    /// 
    /// Every datastructure implementing `UDSI` has `cont` as its inner storage.
    pub cont: std::collections::HashSet<T>
}
impl<T: PartialEq> PartialEq for HashSet<T> {
    fn eq(&self, other: &Self) -> bool {
        self.cont.iter().eq(other.cont.iter())
    }
}
impl<T: PartialEq> Eq for HashSet<T> {}
impl<T: PartialOrd> PartialOrd for HashSet<T> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.cont.iter().partial_cmp(other.cont.iter())
    }
}
impl<T: Ord> Ord for HashSet<T> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.cont.iter().cmp(other.cont.iter())
    }
}
impl<T: Hash> Hash for HashSet<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.cont.iter().collect::<Vec<_>>().hash(state);
    }
}

impl<T> Container<T> for HashSet<T> {
    fn len(&self) -> usize {
        self.cont.len()
    }
}
impl<T> UniContainer<T> for HashSet<T> {
    fn iter<'a>(&'a self) -> impl Iterator<Item = &'a T> where T: 'a {
        self.cont.iter()
    }
}
impl<T: Display> CustomDisplay<T> for HashSet<T> {}
impl<T: Display> Display for HashSet<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        self.display(f, "HashSet", '{', '}')
    }
}
impl<T: Eq + Hash> Extend<T> for HashSet<T> {
    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
        self.cont.extend(iter);
    }
}
impl<T: Eq + Hash> FromIterator<T> for HashSet<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let mut cont = Self::new();
        cont.extend(iter);
        cont
    }
}
impl<T> IntoIterator for HashSet<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;
    fn into_iter(self) -> Self::IntoIter {
        self.cont.into_iter()
    }
}
impl<'a,T> IntoIterator for &'a HashSet<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a,T>;
    fn into_iter(self) -> Self::IntoIter {
        self.cont.iter()
    }
}
impl<T,U: Into<std::collections::HashSet<T>>> From<U> for HashSet<T> {
    fn from(value: U) -> Self {
        use crate::hash_set;
        hash_set![cont: value.into()]
    }
}
impl<T: Eq + Hash + FromStr + Default> CustomFromStr<T> for HashSet<T> where <T as FromStr>::Err : Display {}
impl<T: Eq + Hash + FromStr + Default> FromStr for HashSet<T> where <T as FromStr>::Err : Display {
    type Err = String;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        Self::from_string(s, "HashSet", |cont, _, elem| {cont.cont.insert(elem);})
    }
}

/// Constructs a new `HashSet`
/// 
/// `hash_set!` allows for an effortless contruction of Sets. This macro has multiple forms:
/// 
/// - Create a new `HashSet` from elements:
/// ```
/// # use ryley::structs::prelude::*;
/// let s = hash_set!{1,2,3,4,5};
/// assert_eq!(s.len(), 5);
/// ```
/// 
/// - Create a new `HashSet` from an `std::collections::HashSet`:
/// 
/// ```
/// # use ryley::structs::prelude::*;
/// let s = hash_set!{cont: std::collections::HashSet::from_iter([1,2,3,4,5])};
/// assert_eq!(s.len(), 5);
/// ```
#[macro_export]
macro_rules! hash_set {
    [cont: $x:expr] => {
        {
            use $crate::structs::hash_set::HashSet;
            HashSet { cont: ($x)}
        }
    };
    [$($x:expr),*] => {
        {
            use $crate::structs::hash_set::HashSet;
            HashSet { cont: (std::collections::HashSet::from([$($x),*])) }
        }
    };
}


impl<T: Ord + Hash + Clone> Unique<T> for HashSet<T> {
    fn add(&mut self, elem: T) -> &mut Self {
        self.cont.insert(elem);
        self
    }
    fn add_slice(&mut self, elems: Vec<T>) -> &mut Self {
        self.cont.extend(elems);
        self
    }
    fn contains(&self, elem: &T) -> bool {
        self.cont.contains(elem)
    }
    fn contains_fn(&self, mut f: impl FnMut(&T) -> bool) -> bool {
        for elem in &self.cont { if f(elem) { return true } }
        false
    }
    fn contains_slice(&self, elems: &[T]) -> bool {
        for elem in elems { if !self.cont.contains(elem) { return false } }
        true
    }
    fn count(&self, elem: &T) -> usize {
        usize::from(self.contains(elem))
    }
    fn count_fn(&self, mut f: impl FnMut(&T) -> bool) -> usize {
        let mut count=0;
        for i in &self.cont { if f(i) {count+=1;} }
        count
    }
    fn count_slice(&self, elems: &[T]) -> usize {
        usize::from(self.contains_slice(elems))
    }
    fn replace(&mut self, what: &T, to_what: Option<&T>) -> &mut Self {
        if self.cont.remove(what) { if let Some(val) = to_what { self.cont.insert(val.clone()); } }
        self
    }
    fn replace_fn(&mut self, mut f: impl FnMut(&T)->bool, to_what: Option<&T>) -> &mut Self {
        let mut tmp=std::collections::HashSet::new();
        swap(&mut tmp,&mut self.cont);
        let mut insert_to_what=false;
        for elem in tmp {
            if f(&elem) { insert_to_what=true; }
            else { self.cont.insert(elem); }
        }
        if insert_to_what { if let Some(towhat)=to_what { self.cont.insert(towhat.clone()); } }
        self
    }
    fn replace_slice(&mut self, slice: &[T], to_what: Option<&[T]>) -> &mut Self {
        if self.contains_slice(slice) {
            for item in slice { self.cont.remove(item); }
            if let Some(towhat)=to_what {self.extend(towhat.into_iter().cloned())}
        }
        self
    }
    fn clear(&mut self) -> &mut Self {
        self.cont.clear();
        self
    }
    fn maxi(&self) -> &T {
        debug_assert!(!self.cont.is_empty(), "Tried to get min in empty HashSet!");
        self.cont.iter().max().unwrap()
    }
    fn mini(&self) -> &T {
        debug_assert!(!self.cont.is_empty(), "Tried to get min in empty HashSet!");
        self.cont.iter().min().unwrap()
    }
    fn union(&mut self, other: Self) -> &mut Self {
        self.cont.extend(other.cont);
        self
    }
    fn difference(&mut self, other: &Self) -> &mut Self {
        for i in other.iter() { self.cont.remove(i); }
        self
    }
    fn intersect(&mut self, other: &Self) -> &mut Self {
        let mut out=std::collections::HashSet::new();
        swap(&mut self.cont, &mut out);
        for i in out { if other.contains(&i) { self.cont.insert(i); } }
        self
    }
    fn sym_diff(&mut self, other: Self) -> &mut Self {
        let mut temp=std::collections::HashSet::new();
        for i in other { if !self.cont.remove(&i) { temp.insert(i); } }
        self.cont.extend(temp);
        self
    }
    fn is_subset(&self, other: &Self) -> bool {
        self.cont.is_subset(&other.cont)
    }
    fn is_superset(&self, other: &Self) -> bool {
        self.cont.is_superset(&other.cont)
    }
}


impl<T> HashSet<T> {
    /// Constructs a new, empty `HashSet<T>`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use ryley::structs::prelude::HashSet;
    /// let mut set: HashSet<i32> = HashSet::new();
    /// ```
    #[must_use]
    pub fn new() -> Self {
        Self {
            cont: std::collections::HashSet::new(),
        }
    }
}
impl<T: Clone + Add<Output = T>> HashSet<T> {
    /// Sums the elements of an `OrdSet`.
    ///
    /// Takes each element, adds them together, and returns the result.
    ///
    /// # Panics
    ///
    /// If the `OrdSet` is empty
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// # use ryley::structs::prelude::*;
    /// let s = ord_set![1, 2, 3];
    /// let sum: i32 = s.sum();
    /// assert_eq!(sum, 6);
    /// ```
    #[must_use = "Sum does not consume the Set"]
    pub fn sum(&self) -> T {
        debug_assert!(!self.cont.is_empty(), "Can't add elements together in empty OrdSet!");
        let mut iter=self.cont.iter();
        let mut out=iter.next().unwrap().clone();
        for elem in iter {
            out=out+elem.clone();
        }
        out
    }
}
impl<T: Eq + Hash + Clone> HashSet<HashSet<T>> {
    /// Flattens a slice of `T` into a single value, placing a
    /// given separator between each.
    ///
    /// # Examples
    ///
    /// ```
    /// # use ryley::structs::prelude::*;
    /// assert_eq!(ord_set![ord_set![1, 2], ord_set![3, 4]].join(Some(&vec![0])), ord_set![0, 1, 2, 3, 4]);
    /// assert_eq!(ord_set![ord_set![1, 2], ord_set![3, 4]].join(None), ord_set![1, 2, 3, 4]);
    /// ```
    #[must_use = "Join consumes the Set"]
    pub fn join(self, sep: Option<&Vec<T>>) -> HashSet<T> {
        let mut res=HashSet::new();
        for elem in self {
            res.cont.extend(elem.cont);
        }
        if let Some(val) = sep { res.cont.extend(val.clone()); }
        res
    }
}

macro_rules! scalar_op {
    ($for:tt, $trait:tt, $trait2:tt, $name:ident, $name2:ident) => {
        impl<T: Clone + Hash + Eq + $trait<Output = T>> $trait<T> for $for<T> {
            type Output = Self;
        
            fn $name(mut self, rhs: T) -> Self::Output {
                self.$name2(rhs);
                self
            }
        }
        impl<T: Clone + Hash + Eq + $trait<Output = T>> $trait2<T> for $for<T> {
            fn $name2(&mut self, rhs: T) {
                let mut tmp=$for::new();
                swap(&mut tmp,self);
                *self=tmp.into_iter().map(|x| x.$name(rhs.clone())).collect();
            }
        }
    };
    (shift $for:tt, $trait:tt, $trait2:tt, $name:ident, $name2:ident) => {
        impl<T: Clone + Hash + Eq + $trait<U, Output = T>, U: Clone> $trait<U> for $for<T> {
            type Output = Self;
        
            fn $name(mut self, rhs: U) -> Self::Output {
                self.$name2(rhs);
                self
            }
        }
        impl<T: Clone + Hash + Eq + $trait<U, Output = T>, U: Clone> $trait2<U> for $for<T> {
            fn $name2(&mut self, rhs: U) {
                let mut tmp=$for::new();
                swap(&mut tmp,self);
                *self=tmp.into_iter().map(|x| x.$name(rhs.clone())).collect();
            }
        }
    };
    ($for:tt, $trait:tt, $name:ident) => {
        impl<T: Hash + Eq + $trait<Output = T>> $trait for $for<T> {
            type Output = Self;
        
            fn $name(self) -> Self::Output {
                self.into_iter().map(|x| x.$name()).collect()
            }
        }
    };
}

//Operations with scalars
scalar_op!(HashSet,Not,not);
scalar_op!(HashSet,Neg,neg);
scalar_op!(HashSet,Add,AddAssign,add,add_assign);
scalar_op!(HashSet,Sub,SubAssign,sub,sub_assign);
scalar_op!(HashSet,Mul,MulAssign,mul,mul_assign);
scalar_op!(HashSet,Div,DivAssign,div,div_assign);
scalar_op!(HashSet,Rem,RemAssign,rem,rem_assign);
scalar_op!(shift HashSet,Shl,ShlAssign,shl,shl_assign);
scalar_op!(shift HashSet,Shr,ShrAssign,shr,shr_assign);
scalar_op!(HashSet,BitAnd,BitAndAssign,bitand,bitand_assign);
scalar_op!(HashSet,BitOr, BitOrAssign, bitor, bitor_assign );
scalar_op!(HashSet,BitXor,BitXorAssign,bitxor,bitxor_assign);