Skip to content

Instantly share code, notes, and snippets.

@CrowdHailer
Created December 17, 2018 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CrowdHailer/f9f158f258799c35842a26ce67f85c6d to your computer and use it in GitHub Desktop.
Save CrowdHailer/f9f158f258799c35842a26ce67f85c6d to your computer and use it in GitHub Desktop.
actors.rs
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