#![doc = include_str!("libdoc.md")]
use core::{
convert::{AsMut, AsRef},
ops::{Deref, DerefMut},
};
#[macro_export]
macro_rules! chained {
($val: expr, $($fn: expr),*) => {
Link::new($val)
$(.chain($fn))*
};
($val: expr => $($fn: expr)=>*) => {
Link::new($val)
$(.chain($fn))*
};
(=> $val: expr, $($fn: expr),+) => {
$val
$(.chain($fn))+
};
(=> $val: expr => $($fn: expr)=>+) => {
$val
$(.chain($fn))+
};
(>> $val: expr, $($fn: expr),*) => {
Link::new($val)
$(.chain($fn))*
.eval()
};
(>> $val: expr => $($fn: expr)=>*) => {
Link::new($val)
$(.chain($fn))*
.eval()
};
(>>> $val: expr, $($fn: expr),+) => {
$val
$(.chain($fn))*
.eval()
};
(>>> $val: expr => $($fn: expr)=>+) => {
$val
$(.chain($fn))*
.eval()
};
}
pub trait Chained {
type Item;
fn eval(self) -> Self::Item;
fn chain<F, T>(self, fun: F) -> Chain<Self, F, T>
where
Self: Sized,
F: FnOnce(Self::Item) -> T,
{
Chain { val: self, fun }
}
}
pub trait InterChained {
fn into_chained<T, F: FnOnce(Self) -> T>(self, fun: F) -> Chain<Link<Self>, F, T>
where
Self: Sized,
{
Link::new(self).chain(fun)
}
fn to_chained<T, F: FnOnce(Self) -> T>(&self, fun: F) -> Chain<Link<Self>, F, T>
where
Self: Clone,
{
Link::new(self.clone()).chain(fun)
}
fn chained<T, F: FnOnce(&Self) -> T>(&self, fun: F) -> Chain<Link<&Self>, F, T> {
Link::new(self).chain(fun)
}
fn chained_mut<T, F: FnOnce(&mut Self) -> T>(
&mut self,
fun: F,
) -> Chain<Link<&mut Self>, F, T> {
Link::new(self).chain(fun)
}
fn chained_deref<D, T, F: FnOnce(&Self::Target) -> T>(
&self,
fun: F,
) -> Chain<Link<&Self::Target>, F, T>
where
Self: Deref<Target = D>,
<Self as Deref>::Target: Sized,
{
Link::new(self.deref()).chain(fun)
}
fn chained_deref_mut<D, T, F: FnOnce(&mut Self::Target) -> T>(
&mut self,
fun: F,
) -> Chain<Link<&mut Self::Target>, F, T>
where
Self: DerefMut<Target = D>,
<Self as Deref>::Target: Sized,
{
Link::new(self.deref_mut()).chain(fun)
}
fn chained_as_ref<B: ?Sized, T, F: FnOnce(&B) -> T>(&self, fun: F) -> Chain<Link<&B>, F, T>
where
Self: AsRef<B>,
{
Link::new(self.as_ref()).chain(fun)
}
fn chained_as_mut<B: ?Sized, T, F: FnOnce(&mut B) -> T>(
&mut self,
fun: F,
) -> Chain<Link<&mut B>, F, T>
where
Self: AsMut<B>,
{
Link::new(self.as_mut()).chain(fun)
}
}
impl<T> InterChained for T {}
#[derive(Clone, Debug)]
pub struct Link<T>(T);
impl<T> Link<T> {
pub fn new(val: T) -> Self {
Link(val)
}
}
impl<T> From<T> for Link<T> {
fn from(value: T) -> Self {
Link::new(value)
}
}
impl<T> Chained for Link<T> {
type Item = T;
fn eval(self) -> Self::Item {
self.0
}
}
#[derive(Clone)]
pub struct Chain<C: Chained, F, T>
where
F: FnOnce(C::Item) -> T,
{
val: C,
fun: F,
}
impl<C, F, T, B> Chained for Chain<C, F, T>
where
C: Chained<Item = B>,
F: FnOnce(C::Item) -> T,
{
type Item = T;
fn eval(self) -> Self::Item {
(self.fun)(self.val.eval())
}
}