use crate::errors::Result;
use std::marker::PhantomData;
pub trait NoArgFunctor<'a> {
type Output;
fn tuple_invoke(self) -> Self::Output;
}
pub trait Functor<'a, Args> {
type Output;
fn tuple_invoke(self, args: Args) -> Self::Output;
}
pub trait BiFunctor<'a, FirstArg, Args> {
type Output;
fn tuple_invoke(self, first_arg: FirstArg, args: Args) -> Self::Output;
}
pub struct NoArgClosure<'a, FnType, Out>
where
FnType: 'a + FnOnce() -> Out,
{
phantom: PhantomData<&'a fn() -> Out>,
fn_impl: FnType,
}
impl<'a, FnType, Out> NoArgClosure<'a, FnType, Out>
where
FnType: 'a + FnOnce() -> Out,
{
pub fn new(fn_impl: FnType) -> Self {
Self {
fn_impl,
phantom: PhantomData,
}
}
}
impl<'a, FnType, Out> NoArgFunctor<'a> for NoArgClosure<'a, FnType, Out>
where
FnType: 'a + FnOnce() -> Out,
{
type Output = Out;
fn tuple_invoke(self) -> Self::Output {
(self.fn_impl)()
}
}
pub struct Closure<'a, FnType, Out, Args>
where
FnType: 'a + FnOnce(Args) -> Out,
{
phantom: PhantomData<&'a fn(Args) -> Out>,
fn_impl: FnType,
}
impl<'a, FnType, Out, Args> Closure<'a, FnType, Out, Args>
where
FnType: 'a + FnOnce(Args) -> Out,
{
pub fn new(fn_impl: FnType) -> Self {
Closure {
phantom: PhantomData,
fn_impl,
}
}
}
impl<'a, FnType, Out, Args> Functor<'a, Args> for Closure<'a, FnType, Out, Args>
where
FnType: 'a + FnOnce(Args) -> Out,
{
type Output = Out;
fn tuple_invoke(self, args: Args) -> Self::Output {
let fn_impl = self.fn_impl;
fn_impl(args)
}
}
pub struct BiClosure<'a, FnType, Out, FirstArg, Args>
where
FnType: 'a + FnOnce(FirstArg, Args) -> Out,
{
phantom: PhantomData<&'a fn(FirstArg, Args) -> Out>,
fn_impl: FnType,
}
impl<'a, FnType, Out, FirstArg, Args> BiClosure<'a, FnType, Out, FirstArg, Args>
where
FnType: 'a + FnOnce(FirstArg, Args) -> Out,
{
pub fn new(fn_impl: FnType) -> Self {
BiClosure {
phantom: PhantomData,
fn_impl,
}
}
}
impl<'a, FnType, Out, FirstArg, Args> BiFunctor<'a, FirstArg, Args>
for BiClosure<'a, FnType, Out, FirstArg, Args>
where
FnType: 'a + FnOnce(FirstArg, Args) -> Out,
{
type Output = Out;
fn tuple_invoke(self, first_arg: FirstArg, args: Args) -> Self::Output {
let fn_impl = self.fn_impl;
fn_impl(first_arg, args)
}
}
pub struct NoErrNoArgFunctor<'a, FunctorType, Out>
where
FunctorType: NoArgFunctor<'a, Output = Out>,
{
functor: FunctorType,
phantom: PhantomData<&'a fn() -> Out>,
}
impl<'a, FunctorType, Out> NoErrNoArgFunctor<'a, FunctorType, Out>
where
FunctorType: NoArgFunctor<'a, Output = Out>,
{
pub fn new(functor: FunctorType) -> Self {
Self {
functor,
phantom: PhantomData,
}
}
}
impl<'a, FunctorType, Out> NoArgFunctor<'a> for NoErrNoArgFunctor<'a, FunctorType, Out>
where
FunctorType: NoArgFunctor<'a, Output = Out>,
{
type Output = Result<Out>;
fn tuple_invoke(self) -> Self::Output {
Ok(self.functor.tuple_invoke())
}
}
pub struct NoErrFunctor<'a, FunctorType, Out, ArgTuple>
where
FunctorType: Functor<'a, ArgTuple, Output = Out>,
{
functor: FunctorType,
phantom: PhantomData<&'a fn(ArgTuple) -> Out>,
}
impl<'a, FunctorType, Out, ArgTuple> NoErrFunctor<'a, FunctorType, Out, ArgTuple>
where
FunctorType: Functor<'a, ArgTuple, Output = Out>,
{
pub fn new(functor: FunctorType) -> Self {
NoErrFunctor {
functor,
phantom: PhantomData,
}
}
}
impl<'a, FunctorType, Out, ArgTuple> Functor<'a, ArgTuple>
for NoErrFunctor<'a, FunctorType, Out, ArgTuple>
where
FunctorType: Functor<'a, ArgTuple, Output = Out>,
{
type Output = Result<Out>;
fn tuple_invoke(self, args: ArgTuple) -> Self::Output {
Ok(self.functor.tuple_invoke(args))
}
}
pub struct NoErrBiFunctor<'a, FunctorType, Out, FirstArg, ArgTuple>
where
FunctorType: BiFunctor<'a, FirstArg, ArgTuple, Output = Out>,
{
functor: FunctorType,
phantom: PhantomData<&'a fn(FirstArg, ArgTuple) -> Out>,
}
impl<'a, FunctorType, Out, FirstArg, ArgTuple>
NoErrBiFunctor<'a, FunctorType, Out, FirstArg, ArgTuple>
where
FunctorType: BiFunctor<'a, FirstArg, ArgTuple, Output = Out>,
{
pub fn new(functor: FunctorType) -> Self {
NoErrBiFunctor {
functor,
phantom: PhantomData,
}
}
}
impl<'a, FunctorType, Out, FirstArg, ArgTuple> BiFunctor<'a, FirstArg, ArgTuple>
for NoErrBiFunctor<'a, FunctorType, Out, FirstArg, ArgTuple>
where
FunctorType: BiFunctor<'a, FirstArg, ArgTuple, Output = Out>,
{
type Output = Result<Out>;
fn tuple_invoke(self, first_arg: FirstArg, args: ArgTuple) -> Self::Output {
Ok(self.functor.tuple_invoke(first_arg, args))
}
}