ryley 0.1.1

Syntax unifies programmers
Documentation
//! Module `ord_dict`
//! 
//! This module (which can be found in `structs`) contains the type `OrdDict` which
//! is a sorted `dictionary` or `map`.
//! 
//! # Getting Started:
//! 
//! ## Create a new `OrdDict`:
//! ```
//! # use ryley::structs::prelude::OrdDict;
//! let mut d: OrdDict<i32,i32>=OrdDict::new();
//! ```
//! or
//! ```
//! # use ryley::structs::prelude::*;
//! let mut d: OrdDict<i32,i32>=ord_dict!{1:1, 2:4, 3:9};
//! ```
//! 
//! ## Utilitise `OrdDict`:
//! ```
//! # use ryley::structs::prelude::*;
//! # let mut d: OrdDict<i32,i32>=ord_dict!{1:1, 2:4, 3:9};
//! d.add((4,16)).add((5,16)).distinct().remove_slice(&[1,2,4]);
//! 
//! assert!(d.contains(&9));
//! ```
//! 
//! ## Remember that dictionaries are associated key-value pairs!
//! 
//! Also it is a sorted container, therefore its first key will always be its smallest
//! (and last key the largest). This makes insertions a bit slower in theory than `HashDict`'s.

use std::collections::btree_map::{IntoIter, Iter, IterMut};
use std::collections::BTreeMap;
use core::fmt::{Debug, Display, Formatter, Result};
use core::hash::Hash;
use core::ops::{Index, IndexMut};
use core::str::FromStr;

use super::algorithm::{DictDisplay, DictFromStr};
use super::hash_dict::algo::{contains_slice, count, count_fn, count_item_fn, count_key_fn, count_slice, difference, distinct, distinct_fn, ext, find, find_fn, find_slice, intersect, pop, pop_slice, remove, remove_slice, replace, replace_fn, replace_slice, sym_diff, union, Dict, DictMut, DictRef};
use super::UDSI::{Container, Indexed, IndContainer};

/// Type `OrdDict` is a thin wrapper for `BTreeMap`
/// 
/// `OrdDict` implements the Unified Data Structure Interface (or UDSI for short).
/// 
/// ## Beware
/// - `OrdDict` is an indexed container, therefore it contains 1 of each key and these
///   keys are also associated with a value
/// - `OrdDict` is also a sorted container, which means it has its keys organised in a
///   sorted manner
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OrdDict<Key, Value> {
    /// Internal storage of `OrdDict`
    /// 
    /// Type `OrdDict` is actually a thin wrapper for `BTreeMap`.
    /// 
    /// Every datastructure implementing `UDSI` has `cont` as its inner storage.
    pub cont: BTreeMap<Key, Value>
}

impl<T,U> Container<(T,U)> for OrdDict<T,U> {
    fn len(&self) -> usize {
        self.cont.len()
    }
}
impl<T,U> IndContainer<T,U> for OrdDict<T,U> {
    fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a T,&'a U)> where T: 'a, U: 'a {
        self.cont.iter()
    }
    fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = (&'a T,&'a mut U)> where T: 'a, U: 'a {
        self.cont.iter_mut()
    }
}
impl<T: Display, U: Display> DictDisplay<T,U> for OrdDict<T,U> {}
impl<T: Display, U: Display> Display for OrdDict<T,U> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        self.display(f, "OrdDict")
    }
}
impl<T: Ord,U> Extend<(T,U)> for OrdDict<T,U> {
    fn extend<I: IntoIterator<Item = (T,U)>>(&mut self, iter: I) {
        self.cont.append(&mut iter.into_iter().collect());
    }
}
impl<T: Ord,U> FromIterator<(T,U)> for OrdDict<T,U> {
    fn from_iter<I: IntoIterator<Item = (T,U)>>(iter: I) -> Self {
        let mut cont = Self::new();
        cont.extend(iter);
        cont
    }
}
impl<T,U> IntoIterator for OrdDict<T,U> {
    type Item = (T,U);
    type IntoIter = IntoIter<T,U>;
    fn into_iter(self) -> Self::IntoIter {
        self.cont.into_iter()
    }
}
impl<'a,T,U> IntoIterator for &'a OrdDict<T,U> {
    type Item = (&'a T,&'a U);
    type IntoIter = Iter<'a,T,U>;
    fn into_iter(self) -> Self::IntoIter {
        self.cont.iter()
    }
}
impl<'a,T,U> IntoIterator for &'a mut OrdDict<T,U> {
    type Item = (&'a T,&'a mut U);
    type IntoIter = IterMut<'a,T,U>;
    fn into_iter(self) -> Self::IntoIter {
        self.cont.iter_mut()
    }
}
impl<T,U,V: Into<BTreeMap<T,U>>> From<V> for OrdDict<T,U> {
    fn from(value: V) -> Self {
        use crate::ord_dict;
        ord_dict![cont: value.into()]
    }
}
impl<T: Ord + FromStr + Default, U: FromStr + Default> DictFromStr<T,U> for OrdDict<T,U> where <T as FromStr>::Err : Display, <U as FromStr>::Err : Display {}
impl<T: Ord + FromStr + Default, U: FromStr + Default> FromStr for OrdDict<T,U> where <T as FromStr>::Err : Display, <U as FromStr>::Err : Display {
    type Err = String;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        Self::from_string(s, "OrdDict", |cont, t, u| {cont.cont.insert(t,u);})
    }
}


/// Constructs a new `OrdDict`
/// 
/// `ord_dict!` allows for the effortless contruction of Dictionaries. This macro has
/// multiple forms:
/// 
/// - Create a new `OrdDict` from elements:
/// ```
/// # use ryley::structs::prelude::*;
/// let d = ord_dict!{1:2,2:4,3:6,4:8,5:10};
/// assert_eq!(d.len(), 5);
/// ```
///
/// - Create a new `OrdDict` from a `BTreeMap`:
/// 
/// ```
/// # use ryley::structs::prelude::*;
/// # use std::collections::BTreeMap;
/// let d = ord_dict!{cont: BTreeMap::from([(1,1),(2,2),(3,3),(4,4),(5,5)])};
/// assert_eq!(d.len(), 5);
/// ```
#[macro_export]
macro_rules! ord_dict {
    [cont: $x:expr] => {
        {
            use $crate::structs::ord_dict::OrdDict;
            OrdDict { cont: ($x)}
        }
    };
    [$($x:tt : $y:tt),*] => {
        {
            use std::collections::BTreeMap;
            use $crate::structs::ord_dict::OrdDict;
            let mut inner=BTreeMap::new();
            $(
                inner.insert($x,$y);
            )*
            OrdDict { cont: (inner) }
        }
    };
}

impl<X: Ord + Hash + Clone + core::fmt::Debug, T: Ord + Clone> Indexed<X,T> for OrdDict<X,T> {
    fn add(&mut self, elem: (X,T)) -> &mut Self {
        self.cont.insert(elem.0, elem.1);
        self
    }
    fn add_slice(&mut self, slice: Vec<(X,T)>) -> &mut Self {
        for val in slice { self.cont.insert(val.0, val.1); }
        self
    }
    fn contains(&self, elem: &T) -> bool {
        self.cont.iter().any(|x| x.1==elem)
    }
    fn contains_fn(&self, mut f: impl FnMut(&T) -> bool) -> bool {
        self.cont.iter().any(|(_,t)| f(t))
    }
    fn contains_slice(&self, slice: &[T]) -> bool {
        contains_slice(DictRef::OrdMap(&self.cont), slice)
    }
    fn contains_key(&self, key: &X) -> bool {
        self.cont.contains_key(key)
    }
    fn contains_key_fn(&self, mut f: impl FnMut(&X) -> bool) -> bool {
        self.cont.iter().any(|(x,_)| f(x))
    }
    fn contains_item(&self, item: (&X,&T)) -> bool {
        self.contains_key(item.0) && self.cont[item.0]==*item.1
    }
    fn contains_item_fn(&self, f: impl FnMut((&X,&T)) -> bool) -> bool {
        self.cont.iter().any(f)
    }
    fn count(&self, elem: &T) -> usize {
        count(DictRef::OrdMap(&self.cont), elem)
    }
    fn count_fn(&self, f: impl FnMut(&T) -> bool) -> usize {
        count_fn(DictRef::OrdMap(&self.cont), f)
    }
    fn count_slice(&self, slice: &[T]) -> usize {
        count_slice(DictRef::OrdMap(&self.cont), slice)
    }
    fn count_key(&self, key: &X) -> usize {
        usize::from(self.contains_key(key))
    }
    fn count_key_fn(&self, f: impl FnMut(&X) -> bool) -> usize {
        count_key_fn(DictRef::OrdMap(&self.cont), f)
    }
    fn count_item(&self, item: (&X,&T)) -> usize {
        usize::from(self.contains_item(item))
    }
    fn count_item_fn(&self, f: impl FnMut((&X,&T)) -> bool) -> usize {
        count_item_fn(DictRef::OrdMap(&self.cont), f)
    }
    fn find(&self, elem: &T, maxcount: Option<isize>) -> Vec<&X> {
        find(DictRef::OrdMap(&self.cont), elem, maxcount).into_iter().map(|x| unsafe {x.as_ref().unwrap()}).collect()
    }
    fn find_fn(&self, f: impl FnMut(&T) -> bool, maxcount: Option<isize>) -> Vec<&X> {
        find_fn(DictRef::OrdMap(&self.cont), f, maxcount).into_iter().map(|x| unsafe {x.as_ref().unwrap()}).collect()
    }
    fn find_slice(&self, slice: &[T], maxcount: Option<isize>) -> Vec<&X> {
        find_slice(DictRef::OrdMap(&self.cont), slice, maxcount).into_iter().map(|x| unsafe {x.as_ref().unwrap()}).collect()
    }
    fn pop(&mut self, index: &X) -> T {
        pop(DictMut::OrdMap(&mut self.cont), index)
    }
    fn pop_slice(&mut self, indices: &[X]) -> Vec<T> {
        pop_slice(DictMut::OrdMap(&mut self.cont), indices)
    }
    fn remove(&mut self, index: &X) -> &mut Self {
        remove(DictMut::OrdMap(&mut self.cont), index);
        self
    }
    fn remove_slice(&mut self, indices: &[X]) -> &mut Self {
        remove_slice(DictMut::OrdMap(&mut self.cont), indices);
        self
    }
    fn replace(&mut self, what: &T, to_what: Option<&T>, max_count: Option<isize>) -> &mut Self {
        replace(DictMut::OrdMap(&mut self.cont), what, to_what, max_count);
        self
    }
    fn replace_fn(&mut self, f: impl FnMut(&T)->bool, to_what: Option<&T>, max_count: Option<isize>) -> &mut Self {
        replace_fn(DictMut::OrdMap(&mut self.cont), f, to_what, max_count);
        self
    }
    fn replace_slice<const N: usize>(&mut self, slice: &[T;N], to_what: Option<&[T;N]>, max_count: Option<isize>) -> &mut Self {
        replace_slice(DictMut::OrdMap(&mut self.cont), slice, to_what, max_count);
        self
    }
    fn distinct(&mut self) -> &mut Self {
        distinct(DictMut::OrdMap(&mut self.cont));
        self
    }
    fn distinct_fn<U: Ord>(&mut self, f: impl FnMut(&T) -> U) -> &mut Self {
        distinct_fn(DictMut::OrdMap(&mut self.cont), f);
        self
    }
    fn clear(&mut self) -> &mut Self {
        self.cont.clear();
        self
    }
    fn union(&mut self, other: Self) -> &mut Self {
        union(DictMut::OrdMap(&mut self.cont), Dict::OrdMap(other.cont));
        self
    }
    fn intersect(&mut self, other: &Self) -> &mut Self {
        intersect(DictMut::OrdMap(&mut self.cont), DictRef::OrdMap(&other.cont));
        self
    }
    fn difference(&mut self, other: &Self) -> &mut Self {
        difference(DictMut::OrdMap(&mut self.cont), DictRef::OrdMap(&other.cont));
        self
    }
    fn sym_diff(&mut self, other: Self) -> &mut Self {
        sym_diff(DictMut::OrdMap(&mut self.cont), Dict::OrdMap(other.cont));
        self
    }
    fn maxi(&self) -> (&T, &X) {
        let res=ext(DictRef::OrdMap(&self.cont), true);
        unsafe {(res.0.as_ref().unwrap(),res.1.as_ref().unwrap())}
    }
    fn mini(&self) -> (&T, &X) {
        let res=ext(DictRef::OrdMap(&self.cont), false);
        unsafe {(res.0.as_ref().unwrap(),res.1.as_ref().unwrap())}
    }
    fn keys<'a>(&'a self) -> impl Iterator<Item = &'a X> where X: 'a {
        self.cont.keys()
    }
    fn values<'a>(&'a self) -> impl Iterator<Item = &'a T> where T: 'a {
        self.cont.values()
    }
    fn into_keys(self) -> impl IntoIterator<Item = X> {
        self.cont.into_keys()
    }
    fn into_values(self) -> impl IntoIterator<Item = T> {
        self.cont.into_values()
    }
}


impl<T,U> OrdDict<T,U> {
    /// Constructs a new, empty `OrdDict<X,T>`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use ryley::structs::prelude::OrdDict;
    /// let mut dict: OrdDict<i32,i32> = OrdDict::new();
    /// ```
    #[must_use]
    pub const fn new() -> Self {
        Self { cont: (BTreeMap::new()) }
    }
}

impl<T: Ord,U> Index<&T> for OrdDict<T,U> {
    type Output = U;
    fn index(&self, index: &T) -> &Self::Output {
        &self.cont[index]
    }
}
impl<T: Ord,U> IndexMut<&T> for OrdDict<T,U> {
    fn index_mut(&mut self, index: &T) -> &mut Self::Output {
        self.cont.get_mut(index).unwrap()
    }
}