Skip to content

Instantly share code, notes, and snippets.

@CrowdHailer
Created December 17, 2018 20:53
Show Gist options
  • Select an option

  • Save CrowdHailer/f9f158f258799c35842a26ce67f85c6d to your computer and use it in GitHub Desktop.

Select an option

Save CrowdHailer/f9f158f258799c35842a26ce67f85c6d to your computer and use it in GitHub Desktop.

Revisions

  1. CrowdHailer created this gist Dec 17, 2018.
    94 changes: 94 additions & 0 deletions lib.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@
    mod actor {
    extern crate typemap;

    #[derive(Debug)]
    pub struct Envelop<For: Actor> {
    // TODO make fields private
    pub address: For::Id,
    pub message: For::Message
    }

    // This is more a description of the protocol than the Actor
    pub trait Actor {
    type Id;
    type Message;

    // This could be extracted to a Worker<Message>
    // For static dispatch an mocking just have an enum of real vs mocked
    // type State;

    fn init() -> Self;
    fn handle(self, message: Self::Message) -> (Deliverables, Self);
    }

    pub type Deliverables = Vec<Box<dyn Deliverable>>;


    pub trait Deliverable {
    fn deliver(self, states: &mut typemap::TypeMap);
    }

    pub struct System {states: typemap::TypeMap}
    impl System {
    pub fn new() -> Self { Self{states: typemap::TypeMap::new()} }
    pub fn apply<T: Actor + typemap::Key>(self, envelop: Envelop<T>) -> T {
    let actor = self.states.remove::<T>();
    match actor {
    Some(actor) =>
    actor,
    None =>
    T::init()
    }.handle(envelop.message)
    }
    }
    }
    extern crate typemap;

    #[cfg(test)]
    mod tests {
    use crate::actor::{Actor, Envelop, Deliverables, System};

    #[derive(Debug)]
    struct NormalCounter(i32);
    #[derive(Debug)]
    enum CounterMessage {
    Increment()
    }
    impl Actor for NormalCounter {
    type Id = ();
    type Message = CounterMessage;
    fn init() -> Self { NormalCounter(0) }
    fn handle(self, _: CounterMessage) -> (Deliverables, Self) {
    let updated = NormalCounter(self.0 + 1);
    // let messages = value;
    (vec![], updated)
    }
    }

    impl typemap::Key for NormalCounter {
    type Value = NormalCounter;
    }

    impl Envelop<NormalCounter> {
    fn deliver(self, system: System) -> NormalCounter {
    system.apply::<NormalCounter>(self)
    }

    }

    // #[derive(Debug)]


    #[test]
    fn it_works() {
    // let counter = NormalCounter::init();
    // let counter = counter.handle(CounterMessage::Increment());
    // println!("{:?}", counter);
    let system = System::new();
    // println!("{:?}", system);
    let envelop: Envelop<NormalCounter> = Envelop{address: (), message: CounterMessage::Increment()};
    println!("{:?}", envelop);
    envelop.deliver(system);
    assert_eq!(2 + 2, 3);
    }
    }