1 unstable release
Uses old Rust 2015
0.1.0 | Sep 19, 2018 |
---|
#1743 in Data structures
11KB
153 lines
handler_map
like AnyMap
, but with functions instead of values
This crate began with an idle thought: "Crates like AnyMap
let you store one value of each type.
What would it take to instead store a function that took that type, like a message handler?" What
came out was this.
The basic idea is that you start with a message type, and a function that receives it by-value:
struct MyMessage;
fn handle_msg(_: MyMessage) {
println!("Got your message!");
}
Then, take one of these HandlerMap
s, and hand it the handler:
let mut map = HandlerMap::new();
map.insert(handle_msg);
This registers that type in the handler so you can call it later:
map.call(MyMessage);
// console prints "Got your message!"
lib.rs
:
Crate which contains a "handler map", a structure that maps message types with "handlers" that can be called with them.
The focal point of this crate is the HandlerMap
type, which stores information about
functions which receive various types. This can be used to encode event handlers, message
handlers, or other situations where you want to dynamically select a function to call based on
the data it receives.
To register a handler, pass it to insert
:
use handler_map::HandlerMap;
/// Message which prints to the console when received.
struct MyMessage;
fn handle(_: MyMessage) {
println!("got your message!");
}
let mut map = HandlerMap::new();
map.insert(handle);
This adds the handler to the map so that it can be call
ed later on:
map.call(MyMessage);
The map can also take closures, as long as they implement Fn
and don't capture any references
to their environment:
use handler_map::HandlerMap;
use std::rc::Rc;
use std::cell::Cell;
/// Message which increments an accumulator when received.
struct MyMessage;
let mut map = HandlerMap::new();
let acc = Rc::new(Cell::new(0));
{
let acc = acc.clone();
map.insert(move |_: MyMessage| {
acc.set(acc.get() + 1);
});
}
// call the handler a few times to increment the counter
map.call(MyMessage);
map.call(MyMessage);
map.call(MyMessage);
assert_eq!(acc.get(), 3);
call
can take a message of any type, even if that type hasn't been registered. It returns a
bool
representing whether a handler was called. If a handler for that type has been
registered in the map, it returns true
; otherwise, it returns false
. If you want to check
that a handler has been registered without calling it, use is_registered
or
val_is_registered
.
If you want to remove an event from the handler, call remove
:
use handler_map::HandlerMap;
struct MyMessage;
fn handle_msg(_: MyMessage) {}
let mut map = HandlerMap::new();
map.insert(handle_msg);
assert!(map.is_registered::<MyMessage>());
map.remove::<MyMessage>();
assert!(!map.is_registered::<MyMessage>());