use core::{cell::{Cell, RefCell}, ops::BitXorAssign, str::Utf8Error};
use alloc::{boxed::Box, format, rc::Rc, str, string::String, sync::Arc};
pub trait AnyExt1<R>: Sized {
fn let_ref<'a>(&'a self, f: impl FnOnce(&'a Self) -> R) -> R {
f(self)
}
fn let_mut<'a>(&'a mut self, f: impl FnOnce(&'a mut Self) -> R) -> R {
f(self)
}
fn let_owned(self, f: impl FnOnce(Self) -> R) -> R {
f(self)
}
fn also_ref(self, f: impl FnOnce(&Self) -> R) -> Self {
f(&self);
self
}
fn also_mut(mut self, f: impl FnOnce(&mut Self) -> R) -> Self {
f(&mut self);
self
}
fn y(self, f: impl Copy + Fn(&dyn Fn(Self) -> R, Self) -> R) -> R {
fn y<T, R>(f: impl Copy + Fn(&dyn Fn(T) -> R, T) -> R) -> impl Fn(T) -> R {
move |a| f(&y(f), a)
}
y(f)(self)
}
fn then_if(self, f1: impl FnOnce(&Self) -> bool, f2: impl FnOnce(Self) -> R) -> Option<R> {
if f1(&self) { f2(self).as_some() } else { None }
}
fn then_unless(self, f1: impl FnOnce(&Self) -> bool, f2: impl FnOnce(Self) -> R) -> Option<R> {
if !f1(&self) { f2(self).as_some() } else { None }
}
}
impl<T, R> AnyExt1<R> for T {}
pub trait AnyExt: Sized {
fn drop(self) {}
fn as_some(self) -> Option<Self> {
self.into()
}
fn as_ok<B>(self) -> Result<Self, B> {
Ok(self)
}
fn as_err<A>(self) -> Result<A, Self> {
Err(self)
}
fn as_box(self) -> Box<Self> {
Box::new(self)
}
fn as_cell(self) -> Cell<Self> {
Cell::new(self)
}
fn as_ref_cell(self) -> RefCell<Self> {
RefCell::new(self)
}
fn as_rc(self) -> Rc<Self> {
Rc::new(self)
}
fn as_arc(self) -> Arc<Self> {
Arc::new(self)
}
fn type_name(&self) -> &str {
core::any::type_name::<Self>()
}
fn type_size(&self) -> usize {
core::mem::size_of::<Self>()
}
fn take_if(self, f: impl FnOnce(&Self) -> bool) -> Option<Self> {
if f(&self) { self.as_some() } else { None }
}
fn take_unless(self, f: impl FnOnce(&Self) -> bool) -> Option<Self> {
if !f(&self) { self.as_some() } else { None }
}
}
impl<T> AnyExt for T {}
pub trait BoolExt<R> {
fn if_true(self, value: R) -> Option<R>;
fn if_false(self, value: R) -> Option<R>;
fn then_false(self, f: impl FnOnce() -> R) -> Option<R>;
}
impl<R> BoolExt<R> for bool {
fn if_true(self, value: R) -> Option<R> {
if self { value.as_some() } else { None }
}
fn if_false(self, value: R) -> Option<R> {
if !self { value.as_some() } else { None }
}
fn then_false(self, f: impl FnOnce() -> R) -> Option<R> {
if !self { f().as_some() } else { None }
}
}
pub trait ArrExt {
fn swap_xor(self, i: usize, j: usize) -> Self;
}
impl<T> ArrExt for &mut [T] where T: BitXorAssign<T> + Copy {
fn swap_xor(self, i: usize, j: usize) -> Self {
self.also_mut(|s| if i != j {
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
})
}
}
pub trait Utf8Ext<'a> {
fn to_str(self) -> Result<&'a str, Utf8Error>;
}
impl<'a> Utf8Ext<'a> for &'a [u8] {
fn to_str(self) -> Result<&'a str, Utf8Error> {
str::from_utf8(self)
}
}
pub trait U128Ext {
fn fmt_size_from(self, unit: char) -> String;
}
impl U128Ext for u128 {
fn fmt_size_from(self, unit: char) -> String {
let units = ['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'];
let mut size = self as f64;
let mut counter = 0;
while size >= 1024.0 {
size /= 1024.0;
counter += 1;
}
for (i, &c) in units.iter().enumerate() {
if c == unit {
counter += i;
break;
}
}
format!("{:.1} {}", size, units.get(counter).unwrap_or_else(|| panic!("memory unit out of bounds")))
}
}
pub trait OptionExt<T> {
fn or_else_some(self, f: impl FnOnce() -> T) -> Self;
}
impl<T> OptionExt<T> for Option<T> {
fn or_else_some(self, f: impl FnOnce() -> T) -> Self {
match self {
Some(_) => self,
None => f().as_some()
}
}
}
pub trait FnOnceExt<P1, P2, R> {
fn partial2(self, p2: P2) -> Box<dyn FnOnce(P1) -> R>;
}
impl<P1, P2: 'static, R, F> FnOnceExt<P1, P2, R> for F where F: FnOnce(P1, P2) -> R + 'static {
fn partial2(self, p2: P2) -> Box<dyn FnOnce(P1) -> R> {
(move |p1| self(p1, p2)).as_box()
}
}