Skip to content

Instantly share code, notes, and snippets.

@MartinKavik
Last active March 15, 2020 17:29
Show Gist options
  • Save MartinKavik/36a96f28b9bad76d6cb7141946f5f716 to your computer and use it in GitHub Desktop.
Save MartinKavik/36a96f28b9bad76d6cb7141946f5f716 to your computer and use it in GitHub Desktop.
Return `Msg` or `()` in handlers. | Runtime panics | Stable Rust
use std::any::{Any, TypeId};
#[derive(Debug)]
enum Msg {
Increment,
}
fn main() {
let handlers: Vec<Handler<Msg>> = vec![
Handler::new(|| Msg::Increment),
Handler::new(|| println!("Look, no msg!")),
//Handler::new(|| 123),
];
for handler in handlers {
let msg = (handler.callback)();
println!("Msg: {:?}", msg);
}
}
struct Handler<Ms> {
callback: Box<dyn Fn() -> Option<Ms>>,
}
impl<Ms: 'static> Handler<Ms> {
fn new<T: 'static>(callback: impl FnOnce() -> T + Clone + 'static) -> Self {
let t_type = TypeId::of::<T>();
if t_type != TypeId::of::<Ms>() && t_type != TypeId::of::<()>() {
panic!("Handler can return only Msg or ()!");
}
let callback = move || {
let output = &mut Some(callback.clone()()) as &mut dyn Any;
output
.downcast_mut::<Option<Ms>>()
.and_then(Option::take)
};
Self {
callback: Box::new(callback),
}
}
}
@MartinKavik
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment