noders 0.0.2

NodeJS-like event loop environment for Rust
Documentation
use std::marker::PhantomData;
use std::sync::Arc;
use std::sync::Weak;
use std::any::Any;
use mio_extras::channel::Sender;

use node::Core;


pub struct CallbackReq {
    pub x: Box<Any + Send>,
    pub canary: Arc<Canary>
}
pub enum CallbackEv {
    Req(CallbackReq)
}

pub struct Canary {
    pub callback_id: i32,
}


pub struct CallbackImpl {
    w:Box<Any>,
    f:Box<Any>,
    pub dispatch: fn(&mut CallbackImpl, Box<Any + Send>),
    pub canary: Weak<Canary>
}
fn dispatch<W,X,F>(cbi: &mut CallbackImpl, mut x: Box<Any + Send>) where
    F: 'static + Fn(&mut W,X),
    W: 'static,
    X: 'static
{
    let w: &mut W = cbi.w.downcast_mut().unwrap();
    let optx: &mut Option<X> = x.downcast_mut().unwrap();
    let x = optx.take().unwrap();
    let f: &Fn(&mut W,X) = cbi.f.downcast_ref::<F>().unwrap();
    f(w,x);
}
impl CallbackImpl {
    fn new<W,X,F>(w:W, f:F, c:&Arc<Canary>) -> CallbackImpl where
        F: 'static + Fn(&mut W,X),
        W: 'static,
        X: 'static
    {
        CallbackImpl {
            w:Box::new(w),
            f:Box::new(f),
            dispatch: dispatch::<W,X,F>,
            canary: Arc::downgrade(c)
        }
    }
}

pub struct Callback<X> where X: Send {
    canary: Arc<Canary>,
    sender: Sender<CallbackEv>,
    _x: PhantomData<X>
}

impl<X> Callback<X> where X: Send + 'static {
    pub fn new<W,F>(c:&Core, w:W, f:F) -> Callback<X> where
        F: 'static + Fn(&mut W,X),
        W: 'static,
    {
        let id = c.next_callback_id();
        let canary = Arc::new(Canary {
            callback_id: id,
        });
        c.register_callback(id, CallbackImpl::new(w, f, &canary));
        Callback { canary, _x: PhantomData, sender: c.callback_sender.clone() }
    }
    pub fn call(&self, x:X) {
        match self.sender.send(CallbackEv::Req(CallbackReq {
            x: Box::new(Some(x)),
            canary: self.canary.clone()
        })) {
            Ok(_) => (),
            Err(e) => { warn!("Error making callback {:?}", &e); }
        }
    } 
}