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
}
pub const fn unsafe_ref<'a, T>(r: &T) -> &'a T {
unsafe { &*(core::ptr::from_ref::<T>(r)) }
}
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}"),
}
}