holly 0.5.3

A simplistic actor model library using futures.
Documentation
use futures::{future, prelude::*};
use holly::{Error, prelude::*};
use tokio_threadpool::ThreadPool;

// The root actor.
struct Root;

// Messages the root actor accepts.
enum RootMsg {
    Start,
    FromChild(Hello)
}

impl From<Hello> for RootMsg {
    fn from(h: Hello) -> Self {
        RootMsg::FromChild(h)
    }
}

// The child actor, created by `Root`.
struct Child {
    // The child knows its parent address, but can only send back `Hello` messages.
    parent: Addr<RootMsg, Hello>
}

// Message, the child actor receives.
struct ChildMsg;

// Message from child to parent.
#[derive(Debug)]
struct Hello;

impl Actor<RootMsg, Error> for Root {
    type Result = Box<dyn Future<Item = State<Self, RootMsg>, Error = Error> + Send>;

    fn process(self, ctx: &mut Context<RootMsg>, msg: Option<RootMsg>) -> Self::Result {
        match msg {
            Some(RootMsg::Start) => {
                let child = Child { parent: ctx.address().cast() };
                let future = future::result(ctx.scheduler().spawn(child))
                    .and_then(|addr| addr.send(ChildMsg))
                    .map(move |_| State::Ready(self));
                Box::new(future)
            }
            Some(RootMsg::FromChild(m)) => {
                println!("Received message from child: {:?}", m);
                Box::new(future::ok(State::Done))
            }
            None => {
                Box::new(future::ok(State::Done))
            }
        }
    }
}

impl Actor<ChildMsg, Error> for Child {
    type Result = Box<dyn Future<Item = State<Self, ChildMsg>, Error = Error> + Send>;

    fn process(self, _ctx: &mut Context<ChildMsg>, _msg: Option<ChildMsg>) -> Self::Result {
        Box::new(self.parent.send(Hello).map(|_| State::Done))
    }
}

#[test]
fn parent_child() -> Result<(), Error> {
    let pool = ThreadPool::new();
    let exec = Scheduler::new(pool.sender().clone());
    let mut root = exec.spawn(Root)?;
    root.send_now(RootMsg::Start)?;
    pool.shutdown_on_idle().wait().unwrap();
    Ok(())
}