Skip to content

Instantly share code, notes, and snippets.

@apowers313
Last active December 21, 2021 19:34
Show Gist options
  • Save apowers313/3cdcc808bd038069839f573e482ce333 to your computer and use it in GitHub Desktop.
Save apowers313/3cdcc808bd038069839f573e482ce333 to your computer and use it in GitHub Desktop.
Rust method as function pointer
use std::collections::HashMap;
macro_rules! handler {
($kernel:expr, $method:ident) => {
Box::new(|x| $kernel.$method(x))
};
}
fn main() {
let k = Kernel::new();
k.recv("test".to_string(), "this is a test of the emergency broadcast system".to_string());
}
struct Msg{
msg_type: String,
msg: String
}
struct Kernel<'env> {
handlers: HandlerCollection<'env>
}
impl Kernel<'_> {
fn new() -> Self {
let s = Self {
handlers: HandlerCollection::new()
};
s.handlers.add_handler(String::from("test"), handler!(s, test_handler));
s
}
fn recv(&self, msg_type: String, msg: String) {
self.handlers.call(msg_type, msg)
}
pub fn test_handler(&self, msg: String) -> Result<(), &'static str> {
println!("test msg: {}", msg);
Ok(())
}
}
type HandlerFn<'env> = Box<dyn 'env + Fn(String) -> Result<(), &'static str>>;
struct HandlerCollection<'env> {
collection: HashMap<String, HandlerFn<'env>>,
}
impl HandlerCollection<'_> {
fn new() -> Self {
let mut s = Self {
collection: HashMap::new(),
};
s
}
fn add_handler(&mut self, name: String, handler: HandlerFn) {
// cannot infer an appropriate lifetime due to conflicting requirements
self.collection.insert(name, handler);
}
fn call(&self, msg_type: String, msg: String) {
let handler = match self.collection.get(&msg_type) {
Some(x) => x,
None => {
println!("no message handler found for message type: '{}'", msg_type);
return;
}
};
match handler(msg) {
Ok(()) => return,
Err(e) => println!("error while handling {}: {}", msg_type, e),
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment