Skip to content

Instantly share code, notes, and snippets.

@aboglioli
Last active August 18, 2020 23:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aboglioli/693b17be13d5ed82805340d452cebae1 to your computer and use it in GitHub Desktop.
Save aboglioli/693b17be13d5ed82805340d452cebae1 to your computer and use it in GitHub Desktop.
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::fmt::Debug;
use std::rc::Rc;
#[derive(Debug)]
pub struct Error;
pub trait Event: Debug {
fn code(&self) -> &str;
fn payload(&self) -> Vec<u8>;
}
pub trait EventPublisher {
fn publish(&self, topic: &str, event: Box<dyn Event>) -> Result<(), Error>;
}
pub type Subscription = Box<dyn FnMut(&dyn Event) -> Result<(), Error>>;
pub trait EventSubscriber {
fn subscribe(&self, topic: &str, cb: Subscription) -> Result<(), Error>;
}
pub struct InMemEventBus {
subscriptions: RefCell<HashMap<String, Vec<Subscription>>>,
notified: Cell<u32>,
}
impl InMemEventBus {
pub fn new() -> InMemEventBus {
InMemEventBus {
subscriptions: RefCell::new(HashMap::new()),
notified: Cell::new(0),
}
}
pub fn notified(&self) -> u32 {
self.notified.get()
}
pub fn reset_counter(&self) {
self.notified.set(0);
}
}
impl Default for InMemEventBus {
fn default() -> Self {
Self::new()
}
}
impl EventPublisher for InMemEventBus {
fn publish(&self, topic: &str, event: Box<dyn Event>) -> Result<(), Error> {
let mut count = 0;
if let Some(subs) = self.subscriptions.borrow_mut().get_mut(topic) {
for sub in subs.iter_mut() {
sub(event.as_ref())?;
count += 1;
}
}
self.notified.set(self.notified.get() + count);
Ok(())
}
}
impl EventSubscriber for InMemEventBus {
fn subscribe(&self, topic: &str, cb: Subscription) -> Result<(), Error> {
if let Some(subs) = self.subscriptions.borrow_mut().get_mut(topic) {
subs.push(cb);
return Ok(());
}
self.subscriptions
.borrow_mut()
.insert(topic.to_owned(), vec![cb]);
Ok(())
}
}
#[derive(Debug)]
struct Ent1Created;
impl Event for Ent1Created {
fn code(&self) -> &str {
"ent1.created"
}
fn payload(&self) -> Vec<u8> {
b"ent1.created".to_vec()
}
}
#[derive(Debug)]
struct Ent1Updated;
impl Event for Ent1Updated {
fn code(&self) -> &str {
"ent1.updated"
}
fn payload(&self) -> Vec<u8> {
b"ent1.updated".to_vec()
}
}
#[derive(Debug)]
struct Ent2Created;
impl Event for Ent2Created {
fn code(&self) -> &str {
"ent2.created"
}
fn payload(&self) -> Vec<u8> {
b"ent2.created".to_vec()
}
}
fn main() -> Result<(), Error> {
let eb = InMemEventBus::new();
let calls = Rc::new(Cell::new(0));
let call = Rc::clone(&calls);
eb.subscribe(
"ent1.created",
Box::new(move |event| {
call.set(call.get() + 1);
assert_eq!(event.code(), "ent1.created");
Ok(())
}),
)?;
let call = Rc::clone(&calls);
eb.subscribe(
"ent1.created",
Box::new(move |event| {
println!("{}", event.code());
call.set(call.get() + 1);
Ok(())
}),
)?;
let call = Rc::clone(&calls);
eb.subscribe(
"ent1.updated",
Box::new(move |event| {
println!("{}", event.code());
call.set(call.get() + 1);
assert_eq!(event.code(), "ent1.updated");
Ok(())
}),
)?;
let call = Rc::clone(&calls);
eb.subscribe(
"ent2.created",
Box::new(move |event| {
println!("{}", event.code());
call.set(call.get() + 1);
assert_eq!(event.code(), "ent2.created");
Ok(())
}),
)?;
eb.publish("ent1.created", Box::new(Ent1Created)).unwrap();
assert_eq!(calls.get(), 2);
assert_eq!(eb.notified(), 2);
eb.reset_counter();
calls.set(0);
eb.publish("ent1.created", Box::new(Ent1Created)).unwrap();
eb.publish("ent1.updated", Box::new(Ent1Updated)).unwrap();
eb.publish("ent2.created", Box::new(Ent2Created)).unwrap();
assert_eq!(calls.get(), 4);
assert_eq!(eb.notified(), 4);
Ok(())
}
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::fmt::Debug;
use std::rc::Rc;
#[derive(Debug)]
pub struct Error;
pub trait Event: Debug {
fn code(&self) -> &str;
fn payload(&self) -> Vec<u8>;
}
pub struct InMemEventBus<'a> {
subscriptions:
RefCell<HashMap<String, Vec<Box<dyn FnMut(&dyn Event) + 'a>>>>,
notified: Cell<u32>,
}
impl<'a> InMemEventBus<'a> {
pub fn new() -> Self {
InMemEventBus {
subscriptions: RefCell::new(HashMap::new()),
notified: Cell::new(0),
}
}
pub fn notified(&self) -> u32 {
self.notified.get()
}
pub fn reset_counter(&self) {
self.notified.set(0);
}
}
pub trait EventPublisher {
fn publish(&self, topic: &str, event: &dyn Event) -> Result<(), Error>;
}
impl<'a> EventPublisher for InMemEventBus<'a> {
fn publish(&self, topic: &str, event: &dyn Event) -> Result<(), Error> {
let mut count = 0;
if let Some(subs) = self.subscriptions.borrow_mut().get_mut(topic) {
for sub in subs.iter_mut() {
sub(event);
count += 1;
}
}
self.notified.set(self.notified.get() + count);
Ok(())
}
}
pub trait EventSubscriber<'a> {
fn subscribe(
&self,
topic: &str,
cb: Box<dyn FnMut(&dyn Event) + 'a>,
) -> Result<(), Error>;
}
impl<'a> EventSubscriber<'a> for InMemEventBus<'a> {
fn subscribe(
&self,
topic: &str,
cb: Box<dyn FnMut(&dyn Event) + 'a>,
) -> Result<(), Error> {
if let Some(subs) = self.subscriptions.borrow_mut().get_mut(topic) {
subs.push(cb);
return Ok(());
}
self.subscriptions
.borrow_mut()
.insert(topic.to_owned(), vec![cb]);
Ok(())
}
}
#[derive(Debug)]
struct Ent1Created;
impl Event for Ent1Created {
fn code(&self) -> &str {
"ent1.created"
}
fn payload(&self) -> Vec<u8> {
b"ent1.created".to_vec()
}
}
#[derive(Debug)]
struct Ent1Updated;
impl Event for Ent1Updated {
fn code(&self) -> &str {
"ent1.updated"
}
fn payload(&self) -> Vec<u8> {
b"ent1.updated".to_vec()
}
}
#[derive(Debug)]
struct Ent2Created;
impl Event for Ent2Created {
fn code(&self) -> &str {
"ent2.created"
}
fn payload(&self) -> Vec<u8> {
b"ent2.created".to_vec()
}
}
fn main() -> Result<(), Error> {
let mut v = 0;
{
let eb = InMemEventBus::new();
let mut cb: Box<dyn FnMut(&dyn Event)> = Box::new(|event| {
v += 2;
});
eb.subscribe("ent1.created", cb)?;
eb.publish("ent1.created", &Ent1Created).unwrap();
}
println!("{}", v);
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment