I need to create a hashmap that stores references to other objects as the values, with the names of those objects as the keys (HashMap<String, Consumer>).
The overall system is like a mini-version of Apache Kafka for event handling. So Event objects get passed to Topics where they are then pushed to Consumer objects.
Right now I’m having a hard time setting up the subscribe & unsubscribe functions for adding or removing entries in the Topic’s hashmap for tracking who is subscribing to it. The compiler is complaining about me ‘moving’ Consumers to the Topic even though I’m just trying to store/remove a shared immutable reference to the Consumer. I tried using Rc but I still don’t have any luck with it. Let me know if you know of a solution.
use std::collections::HashMap;
//TODO: this will likely need to be re-vamped for more diverse event types
pub struct Event {
etype: String,
msg: String,
}
// Trait to make things easier across whatever will act as the 'Consumer' of Events from a Topic
pub trait Consume {
fn consume(event: Event){
}
}
#[derive(PartialEq)]
struct Consumer {
name : String,
}
impl Consume for Consumer {
fn consume(event: Event) {
println!("{}: {}", event.etype, event.msg);
}
}
pub struct Topic {
name: String,
subscribers: HashMap<String, Consumer>,
events: Vec<Event>,
}
impl Topic {
fn new(tname: String) -> Topic {
return Topic {
name: tname,
subscribers: HashMap::new(),
events: Vec::new(),
};
}
//TODO:
/// Don't know if Box, RefCell, Rc, or what will be needed here to make the compiler happy
fn subscribe(&mut self, consumer: &Consumer) {
if self.subscribers.contains_key(&consumer.name) == false {
let cons_ref = consumer;
// eprintln!("Does not contain consumer")
let map = &mut self.subscribers;
map.entry(consumer.name.clone()).or_insert(consumer);
}
}
fn unsubscribe(&mut self, consumer: Consumer) {
if self.subscribers.contains_key(&consumer.name) {
// eprintln!("Does not contain consumer")
self.subscribers.remove_entry(&consumer.name);
}
}
}
Here are the tests for the above code:
#[cfg(test)]
mod tests {
use super::*;
// == EVENTS ==
#[test]
fn test_create_event(){
let type_name = "Test";
let message = "Hello, World!";
let event = Event {
etype: type_name.to_string(),
msg: message.to_string()
};
assert_eq!(event.etype, type_name);
assert_eq!(event.msg, message);
}
// == TOPIC ==
#[test]
fn test_topic_create(){
let topic_name = "Test";
let topic = Topic::new(topic_name.to_string());
assert_eq!(topic.name, topic_name);
}
#[test]
fn test_topic_subscribe(){
let topic_name = "Topic";
let mut topic = Topic::new(topic_name.to_string());
let consumer_name = "Consumer";
let cons = Consumer{name: consumer_name.to_string()};
// Subscribe
topic.subscribe( cons);
let test_subscriber = topic.subscribers[consumer_name].name.clone();
assert_eq!(test_subscriber, consumer_name);
}
//TODO: Write this out
#[test]
fn test_topic_unsubscribe(){
let topic_name = "Topic";
let mut topic = Topic::new(topic_name.to_string());
let consumer_name = "Consumer";
let cons = Consumer{name: consumer_name.to_string()};
topic.subscribe( &cons);
// Unsubscribe
topic.unsubscribe(&cons);
}
// Add Event to Topic
// == CONSUMER ==
// Consume Message
}
Here is the output for Cargo Check:
Checking events v0.1.0 (/home/mike/Projects/Rust/Game/events)
warning: unused variable: `event`
--> src/lib.rs:15:16
|
15 | fn consume(event: Event){
| ^^^^^ help: if this is intentional, prefix it with an underscore: `_event`
|
= note: `#[warn(unused_variables)]` on by default
error[E0507]: cannot move out of `*consumer` which is behind a shared reference
--> src/lib.rs:50:36
|
50 | let cons_ref = Rc::new(*consumer);
| ^^^^^^^^^ move occurs because `*consumer` has type `Consumer`, which does not implement the `Copy` trait
|
help: consider cloning the value if the performance cost is acceptable
|
50 - let cons_ref = Rc::new(*consumer);
50 + let cons_ref = Rc::new(consumer.clone());
|
For more information about this error, try `rustc --explain E0507`.
warning: `events` (lib) generated 1 warning
error: could not compile `events` (lib) due to 1 previous error; 1 warning emitted
2