ryley 0.1.1

Syntax unifies programmers
Documentation
//! Algorithm is home to some `QoL` algorithms, which are mainly used inside `ryley`.
//! 
//! Q. Why are some algorithms not public then?
//! 
//! A. They need docs.

use std::collections::BTreeMap;
use core::{fmt::{Display, Formatter, Alignment}, str::FromStr};

#[allow(non_snake_case)]
pub(super) fn KMP<T: PartialEq>(context: &[T], pattern: &[T], maxcount: Option<isize>) -> Vec<usize> {
    let mut count=maxcount.unwrap_or(-1);
    if count==0 { return vec![]; }
    let mut res=vec![];
    let pi=kmp_init(pattern);
    let mut i=0;
    let mut j=0;
    while i<context.len() && count!=0 {
        if pattern[j]==context[i] {
            i+=1;
            j+=1;
            if j==pattern.len() {
                res.push(i-pattern.len());
                count-=1;
                j=pi[j-1];
            }
        }
        else if j==0 { i+=1; }
        else { j=pi[j-1]; }
    }
    res
}
fn kmp_init<T: PartialEq>(pattern: &[T]) -> Vec<usize> {
    let mut pi=vec![];
    if pattern.is_empty() { return pi }
    pi.resize(pattern.len(), 0);
    let mut i=0;
    let mut j=1;
    while j<pattern.len() {
        if pattern[i]==pattern[j] {
            i+=1;
            pi[j]=i;
            j+=1;
        }
        else if i==0 {
            pi[j]=0;
            j+=1;
        }
        else { i=pi[i-1]; }
            
    }
    pi
}
pub(super) fn safe_index(index: isize, len: usize) -> usize {
    let mut ind_i = index;
    if ind_i<0 { ind_i+=pointer_cast(len); }
    debug_assert!(ind_i >= 0, "Index is out of bounds! Tried to index Container of size {len} with index {index}!");
    let ind = ind_i.unsigned_abs();
    #[cfg(debug_assertions)]
    debug_assert!(ind < len, "Index is out of bounds! Tried to index Container of size {len} with index {index}!");
    ind
}
pub(super) fn make_multiset<T: Ord>(cont: impl IntoIterator<Item = T>) -> BTreeMap<T,i128> {
    let mut h: BTreeMap<T,i128>=BTreeMap::new();
    for i in cont {
        if let Some(k)=h.get_mut(&i) { *k+=1; }
        else { h.insert(i,1); }
    }
    h
}

/// Returns an unsafe reference to the original value. This reference
/// might not be valid after a certain time.
/// 
/// # Warning
/// Only use this for references that are CERTAINLY not going to change!
/// For example don't use it with a `Vec` without a sufficient `capacity`.
/// 
/// # Examples
/// ```
/// # use ryley::structs::algorithm::unsafe_ref;
/// let origin=vec![1,2,3];
/// let safe_ref=&origin;
/// let unsafe_ref=unsafe_ref(safe_ref);
/// // Drop makes safe_ref unusable and
/// // makes unsafe_ref point to invalid data
/// drop(origin);
/// ```
pub const fn unsafe_ref<'a, T>(r: &T) -> &'a T {
    unsafe { &*(core::ptr::from_ref::<T>(r)) }
}

/// Returns an unsafe mutable reference to the original value. This
/// reference might not be valid after a certain time.
/// 
/// # Warning
/// Only use this for references that are CERTAINLY not going to change!
/// For example don't use it with a `Vec` without a sufficient `capacity`.
/// 
/// # Examples
/// ```
/// # use ryley::structs::algorithm::unsafe_ref_mut;
/// let mut origin=vec![1,2,3];
/// let safe_ref_mut=&mut origin;
/// let unsafe_ref_mut=unsafe_ref_mut(safe_ref_mut);
/// // Drop makes safe_ref_mut unusable and
/// // makes unsafe_ref_mut point to invalid data
/// drop(origin);
/// ```
pub fn unsafe_ref_mut<'a, T>(r: &mut T) -> &'a mut T {
    unsafe { &mut *(core::ptr::from_mut::<T>(r)) }
}

pub(super) trait CustomDisplay<T> where for<'a> &'a Self : IntoIterator<Item = &'a T>, T : Display {
    fn display(&self, f: &mut Formatter<'_>, name: &str, open: char, close: char) -> core::fmt::Result {
        if f.alternate() { write!(f, "{name}{open}")?; }
        else { write!(f, "{open}")?; }
        for (i,item) in self.into_iter().enumerate() {
            if i!=0 { write!(f, ", ")?; }
            match f.width() {
                Some(mut width) =>  {
                    let c=f.fill();
                    let buf=
                    f.precision().map_or_else(
                        ||
                            if f.sign_minus() {format!("{item:-}")}
                            else if f.sign_plus() {format!("{item:+}")}
                            else {format!("{item:}")},
                        |prec|
                            if f.sign_minus() {format!("{item:-.prec$}")}
                            else if f.sign_plus() {format!("{item:+.prec$}")}
                            else {format!("{item:.prec$}")}
                    );
                    width=if buf.len()>width {0} else {width-buf.len()};
                    let mut do_later=width;
                    let mut do_now=0;
                    if let Some(a) = f.align() {
                        match a {
                            Alignment::Left => {},
                            Alignment::Right => {do_now=width;do_later=0;},
                            Alignment::Center => {do_now=width/2;do_later=width-width/2;},
                        }
                    }
                    else {
                        do_now=width;do_later=0;
                    }
                    for _ in 0..do_now {
                        write!(f,"{c}")?;
                    }
                    write!(f,"{buf}")?;
                    for _ in 0..do_later {
                        write!(f,"{c}")?;
                    }
                },
                None => {
                    match f.precision() {
                        Some(p) => write!(f, "{item:.p$}")?,
                        None => write!(f, "{item}")?,
                    };
                },
            }
        }
        write!(f, "{close}")
    }
}

pub(super) trait CustomFromStr<T> where Self : Default, T: FromStr, <T as FromStr>::Err : Display {
    fn from_string(s: &str, name: &str, f: impl Fn(&mut Self, usize, T)) -> Result<Self,String> {
        let mut out=Self::default();
        let mut current=String::new();
        let mut level=0;
        let mut i=0;
        for chr in s.chars() {
            if "[{".contains(chr) {
                level+=1;
            }
            else if "]}".contains(chr) {
                level-=1;
                if level<0 { return Err(format!("{name} expression was malformed! Parenthesis don't match!")) }
            }
            if !(level==1 && "[{,".contains(chr) || level==0 && "]}".contains(chr)) {
                current.push(chr);
            }
            if level==1 && chr==',' || level==0 && "]}".contains(chr) {
                if !current.is_empty() {
                    match current.trim().parse::<T>() {
                        Ok(val) => {f(&mut out, i, val); i+=1;},
                        Err(err) => return Err(err.to_string())
                    }
                }
                current=String::new();
            }
        }
        if level!=0 { return Err(format!("{name} expression was malformed! Parenthesis don't match!")) }
        Ok(out)
    }
}

pub(super) trait DictDisplay<T,U> where for<'a> &'a Self : IntoIterator<Item = (&'a T,&'a U)>, T: Display, U: Display {
    fn display(&self, f: &mut Formatter<'_>, name: &str) -> core::fmt::Result {
        if f.alternate() { write!(f, "{name}{{")?; }
        else { write!(f, "{{")?; }
        for (i,(t,u)) in self.into_iter().enumerate() {
            if i!=0 { write!(f, ", ")?; }
            match f.width() {
                Some(mut width) =>  {
                    let c=f.fill();
                    let buf=
                    f.precision().map_or_else(
                        ||
                            if f.sign_minus() {format!("{u:-}")}
                            else if f.sign_plus() {format!("{u:+}")}
                            else {format!("{u:}")},
                        |prec|
                            if f.sign_minus() {format!("{u:-.prec$}")}
                            else if f.sign_plus() {format!("{u:+.prec$}")}
                            else {format!("{u:.prec$}")}
                    );
                    width=if buf.len()>width {0} else {width-buf.len()};
                    let mut do_later=width;
                    let mut do_now=0;
                    if let Some(a) = f.align() {
                        match a {
                            Alignment::Left => {},
                            Alignment::Right => {do_now=width;do_later=0;},
                            Alignment::Center => {do_now=width/2;do_later=width-width/2;},
                        }
                    }
                    else {
                        do_now=width;do_later=0;
                    }
                    write!(f,"{t}: ")?;
                    for _ in 0..do_now {
                        write!(f,"{c}")?;
                    }
                    write!(f,"{buf}")?;
                    for _ in 0..do_later {
                        write!(f,"{c}")?;
                    }
                },
                None => {
                    match f.precision() {
                        Some(p) => write!(f, "{t}: {u:.p$}")?,
                        None => write!(f, "{t}: {u}")?,
                    };
                },
            }
        }
        write!(f, "}}")
    }
}

pub(super) trait DictFromStr<T,U> where Self : Default, T: FromStr, U: FromStr, <T as FromStr>::Err : Display, <U as FromStr>::Err : Display {
    fn from_string(s: &str, name: &str, f: impl Fn(&mut Self, T, U)) -> Result<Self,String> {
        let mut out=Self::default();
        let mut current=String::new();
        let mut level=0;
        for chr in s.chars() {
            if "[{".contains(chr) {
                level+=1;
            }
            else if "]}".contains(chr) {
                level-=1;
                if level<0 { return Err(format!("{name} expression was malformed! Parenthesis don't match!")) }
            }
            if !(level==1 && "[{,".contains(chr) || level==0 && "]}".contains(chr)) {
                current.push(chr);
            }
            if level==1 && chr==',' || level==0 && chr==']' {
                if !current.is_empty() {
                    let mut sp=current.split(':');
                    let t=sp.next().unwrap();
                    let u=sp.next().unwrap();
                    let item=
                    (
                        match t.trim().parse::<T>() {
                            Ok(val) => val,
                            Err(err) => return Err(err.to_string())
                        },
                        match u.trim().parse::<U>() {
                            Ok(val) => val,
                            Err(err) => return Err(err.to_string())
                        }
                    );
                    f(&mut out, item.0,item.1);
                }
                current=String::new();
            }
        }
        if level!=0 { return Err(format!("{name} expression was malformed! Parenthesis don't match!")) }
        Ok(out)
    }
}

pub(super) fn pointer_cast(n: usize) -> isize {
    let res=isize::try_from(n);
    match res {
        Ok(val) => val,
        Err(err) => panic!("{err}"),
    }
}