wheel-timer2 0.1.2

A timer based on a multi-time wheel structure
Documentation
use std::any::Any;
use std::marker::PhantomData;

use crate::behave::Behave;

pub type BoxedCallback = Box<dyn Callback<Box<dyn Any + Send>> + Send>;

pub trait Callback<Ctx> {
    fn call(&self, context: &mut Ctx) -> Behave;

    fn boxed(self) -> BoxedCallback
    where
        Self: Sized,
    {
        unimplemented!()
    }
}

impl<F, B> Callback<()> for F
where
    F: Fn() -> B + Send + 'static,
    B: Into<Behave>,
{
    fn call(&self, _: &mut ()) -> Behave {
        self().into()
    }

    fn boxed(self) -> BoxedCallback {
        struct A<CB>(CB);

        impl<CB> Callback<Box<dyn Any + Send>> for A<CB>
        where
            CB: Callback<()> + Send + 'static,
        {
            fn call(&self, _: &mut Box<dyn Any + Send>) -> Behave {
                self.0.call(&mut ())
            }
        }

        Box::new(A(self))
    }
}

impl<F, B, C> Callback<(C,)> for F
where
    F: Fn(&mut C) -> B + Send + 'static,
    B: Into<Behave>,
    C: Send + 'static,
{
    fn call(&self, (ref mut ctx,): &mut (C,)) -> Behave {
        self(ctx).into()
    }

    fn boxed(self) -> BoxedCallback {
        struct A<C, CB>(CB, PhantomData<C>);

        impl<C, CB> Callback<Box<dyn Any + Send>> for A<C, CB>
        where
            CB: Callback<(C,)> + Send + 'static,
            C: Send + 'static,
        {
            fn call(&self, a: &mut Box<dyn Any + Send>) -> Behave {
                self.0
                    .call(unsafe { &mut *(a.downcast_mut::<C>().unwrap() as *mut C as *mut (C,)) })
            }
        }

        Box::new(A::<C, _>(self, PhantomData::default()))
    }
}