Created
December 17, 2018 20:53
-
-
Save CrowdHailer/f9f158f258799c35842a26ce67f85c6d to your computer and use it in GitHub Desktop.
actors.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment