#![doc = include_str!("../README.md")]
#![no_std]
#![cfg_attr(doc, feature(doc_auto_cfg))]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
#[derive(Clone, Copy, Debug)]
pub struct ClosureOnce<S, Args, Out> {
state: S,
computation: fn(S, Args) -> Out,
}
impl<S, A, O> ClosureOnce<S, A, O> {
pub fn new(s: S, operation: impl Into<fn(S, A) -> O>) -> Self {
Self {
state: s,
computation: operation.into(),
}
}
#[inline(always)]
pub fn as_fn_once(self) -> impl FnOnce(A) -> O {
as_fn_once(self)
}
}
#[derive(Clone, Copy)]
pub struct ClosureMut<S, Args, Out> {
state: S,
computation: fn(&mut S, Args) -> Out,
}
impl<S, A, O> ClosureMut<S, A, O> {
pub fn new(s: S, operation: impl Into<fn(&mut S, A) -> O>) -> Self {
Self {
state: s,
computation: operation.into(),
}
}
#[inline(always)]
pub fn as_fn_mut(self) -> impl FnMut(A) -> O {
as_fn_mut(self)
}
}
#[derive(Clone, Copy)]
pub struct Closure<S, Args, Out> {
state: S,
computation: fn(&S, Args) -> Out,
}
impl<S, A, O> Closure<S, A, O> {
pub fn new(s: S, operation: impl Into<fn(&S, A) -> O>) -> Self {
Self {
state: s,
computation: operation.into(),
}
}
#[inline(always)]
pub fn as_fn(self) -> impl Fn(A) -> O {
as_fn(self)
}
}
pub trait CoOnce<Args> {
type Output;
fn call_once(self, args: Args) -> Self::Output;
}
pub trait CoMut<Args>: CoOnce<Args> {
fn call_mut(&mut self, args: Args) -> Self::Output;
}
pub trait Co<Args>: CoMut<Args> {
fn call(&self, args: Args) -> Self::Output;
}
impl<A, O, F: FnOnce(A) -> O> CoOnce<A> for F {
type Output = O;
#[inline(always)]
fn call_once(self, args: A) -> Self::Output {
(self)(args)
}
}
impl<A, O, F: FnMut(A) -> O> CoMut<A> for F {
#[inline(always)]
fn call_mut(&mut self, args: A) -> Self::Output {
(self)(args)
}
}
impl<A, O, F: Fn(A) -> O> Co<A> for F {
#[inline(always)]
fn call(&self, args: A) -> Self::Output {
(self)(args)
}
}
impl<S, A, O> CoOnce<A> for ClosureOnce<S, A, O> {
type Output = O;
#[inline(always)]
fn call_once(self, args: A) -> Self::Output {
(self.computation)(self.state, args)
}
}
impl<S, A, O> CoOnce<A> for ClosureMut<S, A, O> {
type Output = O;
#[inline(always)]
fn call_once(mut self, args: A) -> Self::Output {
(self.computation)(&mut self.state, args)
}
}
impl<S, A, O> CoMut<A> for ClosureMut<S, A, O> {
#[inline(always)]
fn call_mut(&mut self, args: A) -> Self::Output {
(self.computation)(&mut self.state, args)
}
}
impl<S, A, O> CoOnce<A> for Closure<S, A, O> {
type Output = O;
#[inline(always)]
fn call_once(self, args: A) -> Self::Output {
(self.computation)(&self.state, args)
}
}
impl<S, A, O> CoMut<A> for Closure<S, A, O> {
#[inline(always)]
fn call_mut(&mut self, args: A) -> Self::Output {
(self.computation)(&self.state, args)
}
}
impl<S, A, O> Co<A> for Closure<S, A, O> {
#[inline(always)]
fn call(&self, args: A) -> Self::Output {
(self.computation)(&self.state, args)
}
}
#[inline(always)]
pub const fn closure_state() -> state_builder::ClosureState<()> {
state_builder::ClosureState(())
}
pub const fn single_closure_state<S>(s: S) -> state_builder::ClosureState<S> {
state_builder::ClosureState(s)
}
pub mod state_builder {
use super::{Closure, ClosureMut, ClosureOnce};
#[derive(Clone, Copy, Debug, Default)]
pub struct ClosureState<S>(pub S);
impl<S> ClosureState<S> {
#[inline]
pub const fn with_state(s: S) -> Self {
Self(s)
}
#[inline]
pub fn as_tuple(self) -> ClosureState<(S,)> {
ClosureState::with_state((self.0,))
}
#[inline]
pub fn finalise<A, O>(self, fin: fn(&S, A) -> O) -> Closure<S, A, O> {
Closure::new(self.0, fin)
}
#[inline]
pub fn finalise_mut<A, O>(self, fin: fn(&mut S, A) -> O) -> ClosureMut<S, A, O> {
ClosureMut::new(self.0, fin)
}
#[inline]
pub fn finalise_once<A, O>(self, fin: fn(S, A) -> O) -> ClosureOnce<S, A, O> {
ClosureOnce::new(self.0, fin)
}
}
impl ClosureState<()> {
#[inline(always)]
pub const fn and<TX>(self, other: TX) -> ClosureState<(TX,)> {
ClosureState::with_state((other,))
}
}
macro_rules! tuple_closure_state_flat{
($first_param_name:ident $($existing_params:ident)*) => {
impl <$($existing_params,)* $first_param_name> ClosureState<($($existing_params,)* $first_param_name,)> {
#[inline(always)]
#[allow(non_snake_case)]
pub fn and<TX>(self, n: TX) -> ClosureState<($($existing_params,)* $first_param_name, TX,)> {
let ($($existing_params,)* $first_param_name,) = self.0;
ClosureState(($($existing_params,)* $first_param_name, n))
}
}
tuple_closure_state_flat!{$($existing_params)*}
};
{} => {}
}
tuple_closure_state_flat! {T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10}
}
pub mod compose {
use super::{Co, CoMut, CoOnce};
#[derive(Clone, Copy)]
pub struct Chain<ComputationTuple>(pub ComputationTuple);
macro_rules! chain {
{$first_type_param:ident $last_type_param:ident $($type_param:ident($previous_output_param:ident))*} => {
impl<$first_type_param, $($type_param,)* > Chain<($first_type_param, $($type_param,)*)> {
#[inline(always)]
#[allow(non_snake_case)]
pub fn and_then<TX>(self, next: TX) -> Chain<($first_type_param, $($type_param,)* TX)> {
let ($first_type_param, $($type_param,)*) = self.0;
Chain(($first_type_param, $($type_param,)* next))
}
#[inline]
pub fn as_fn_once<Args>(self) -> impl FnOnce(Args) -> <Self as CoOnce<Args>>::Output where Self: CoOnce<Args> {
crate::as_fn_once(self)
}
#[inline]
pub fn as_fn_mut<Args>(self) -> impl FnMut(Args) -> <Self as CoOnce<Args>>::Output where Self: CoMut<Args> {
crate::as_fn_mut(self)
}
#[inline]
pub fn as_fn<Args>(self) -> impl Fn(Args) -> <Self as CoOnce<Args>>::Output where Self: Co<Args> {
crate::as_fn(self)
}
}
impl <
A,
$first_type_param: CoOnce<A>,
$($type_param : CoOnce<$previous_output_param::Output>,)*
> CoOnce<A> for Chain<($first_type_param, $($type_param,)*)> {
type Output = $last_type_param::Output;
#[inline]
#[allow(non_snake_case)]
fn call_once(self, args: A) -> Self::Output {
let Self(($first_type_param, $($type_param,)*)) = self;
let args = $first_type_param.call_once(args);
$(
let args = $type_param.call_once(args);
)*
args
}
}
impl <
A,
$first_type_param: CoMut<A>,
$($type_param : CoMut<$previous_output_param::Output>,)*
> CoMut<A> for Chain<($first_type_param, $($type_param,)*)> {
#[inline]
#[allow(non_snake_case)]
fn call_mut(&mut self, args: A) -> Self::Output {
let Self(($first_type_param, $($type_param,)*)) = self;
let args = $first_type_param.call_mut(args);
$(
let args = $type_param.call_mut(args);
)*
args
}
}
impl <
A,
$first_type_param: Co<A>,
$($type_param : Co<$previous_output_param::Output>,)*
> Co<A> for Chain<($first_type_param, $($type_param,)*)> {
#[inline]
#[allow(non_snake_case)]
fn call(&self, args: A) -> Self::Output {
let Self(($first_type_param, $($type_param,)*)) = self;
let args = $first_type_param.call(args);
$(
let args = $type_param.call(args);
)*
args
}
}
}
}
chain! {T0 T11 T1(T0) T2(T1) T3(T2) T4(T3) T5(T4) T6(T5) T7(T6) T8(T7) T9(T8) T10(T9) T11(T10)}
chain! {T0 T10 T1(T0) T2(T1) T3(T2) T4(T3) T5(T4) T6(T5) T7(T6) T8(T7) T9(T8) T10(T9)}
chain! {T0 T9 T1(T0) T2(T1) T3(T2) T4(T3) T5(T4) T6(T5) T7(T6) T8(T7) T9(T8)}
chain! {T0 T8 T1(T0) T2(T1) T3(T2) T4(T3) T5(T4) T6(T5) T7(T6) T8(T7)}
chain! {T0 T7 T1(T0) T2(T1) T3(T2) T4(T3) T5(T4) T6(T5) T7(T6)}
chain! {T0 T6 T1(T0) T2(T1) T3(T2) T4(T3) T5(T4) T6(T5)}
chain! {T0 T5 T1(T0) T2(T1) T3(T2) T4(T3) T5(T4)}
chain! {T0 T4 T1(T0) T2(T1) T3(T2) T4(T3)}
chain! {T0 T3 T1(T0) T2(T1) T3(T2)}
chain! {T0 T2 T1(T0) T2(T1)}
chain! {T0 T1 T1(T0)}
pub trait CoOnceExt<Arg>: CoOnce<Arg> {
#[inline(always)]
fn and_then<T>(self, other: T) -> Chain<(Self, T)>
where
Self: Sized,
{
Chain((self, other))
}
}
impl<Arg, T: CoOnce<Arg>> CoOnceExt<Arg> for T {}
}
pub use compose::Chain;
#[inline(always)]
pub fn as_fn_once<Arg, T: CoOnce<Arg>>(t: T) -> impl FnOnce(Arg) -> T::Output {
move |a| t.call_once(a)
}
#[inline(always)]
pub fn as_fn_mut<Arg, T: CoMut<Arg>>(mut t: T) -> impl FnMut(Arg) -> T::Output {
move |a| t.call_mut(a)
}
#[inline(always)]
pub fn as_fn<Arg, T: Co<Arg>>(t: T) -> impl Fn(Arg) -> T::Output {
move |a| t.call(a)
}
pub mod prelude {
pub use super::{
closure_state, single_closure_state, compose::CoOnceExt as _, Closure, ClosureMut, ClosureOnce, Co, CoMut, CoOnce,
};
}