├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | 3 | 4 | #Added by cargo 5 | # 6 | #already existing elements were commented out 7 | 8 | #/target 9 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "eventemitter" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "eventemitter" 3 | version = "0.1.0" 4 | authors = ["heapwolf "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SYNOPSIS 2 | An event emtter for Rust. 3 | 4 | # USAGE 5 | 6 | ```rust 7 | mod events; 8 | 9 | fn main () { 10 | let mut e = events::EventEmitter::new(); 11 | 12 | e.on("click", |data: &mut dyn Any| { 13 | 14 | // 15 | // Listen for any data structure and re-cast it. 16 | // 17 | let d = &mut data.downcast_mut::().unwrap(); 18 | assert_eq!(d.x, 1); 19 | }); 20 | 21 | struct Args { 22 | pub x: usize, 23 | pub y: usize, 24 | } 25 | 26 | // 27 | // Emit any data structure 28 | // 29 | e.emit("click", &mut Args { x: 1, y: 2 }); 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::any::Any; 2 | use std::collections::HashMap; 3 | 4 | type Callback<'a> = Box<(dyn FnMut(&mut dyn Any) + 'static)>; 5 | 6 | pub struct EventEmitter<'a> { 7 | pub events: HashMap<&'a str, Vec>>, 8 | } 9 | 10 | impl<'a> EventEmitter<'a> { 11 | pub fn new() -> Self { 12 | EventEmitter { 13 | events: HashMap::new(), 14 | } 15 | } 16 | 17 | pub fn create_callback<'x, F>(f: F) -> Callback<'x> 18 | where 19 | F: FnMut(&mut dyn Any) + 'static, 20 | { 21 | Box::new(f) as Callback 22 | } 23 | 24 | pub fn on(&mut self, name: &'a str, cb: impl Fn(&mut dyn Any) + 'static) { 25 | if !self.events.contains_key(name) { 26 | self.events.insert(name, Vec::new()); 27 | } 28 | 29 | let list = &mut self.events.get_mut(name).unwrap(); 30 | list.push(EventEmitter::<'a>::create_callback(cb)); 31 | } 32 | 33 | pub fn off(&mut self, name: &'a str) { 34 | if self.events.contains_key(name) { 35 | self.events.remove(name); 36 | } 37 | } 38 | 39 | pub fn emit(&mut self, name: &'a str, data: &mut dyn Any) { 40 | if !self.events.contains_key(name) { 41 | return 42 | } 43 | 44 | let list = &mut self.events.get_mut(name).unwrap(); 45 | 46 | for cb in list.iter_mut() { 47 | cb(data); 48 | } 49 | } 50 | 51 | pub fn listeners(&mut self, name: &'a str) -> Option<&Vec>> { 52 | let listeners = self.events.get(name); 53 | 54 | if listeners.is_some() { 55 | return listeners; 56 | } 57 | 58 | None 59 | } 60 | } 61 | 62 | #[cfg(test)] 63 | mod tests { 64 | use super::*; 65 | 66 | #[test] 67 | fn emit_data () { 68 | let mut e = EventEmitter::new(); 69 | 70 | e.on("click", |data: &mut dyn Any| { 71 | let d = &mut data.downcast_mut::().unwrap(); 72 | d.x = 10; 73 | }); 74 | 75 | e.on("click", |data: &mut dyn Any| { 76 | let d = &mut data.downcast_mut::().unwrap(); 77 | d.y = 20; 78 | }); 79 | 80 | struct Args { 81 | pub x: usize, 82 | pub y: usize, 83 | } 84 | 85 | let args = &mut Args { x: 1, y: 2 }; 86 | 87 | assert_eq!(args.x, 1); 88 | assert_eq!(args.y, 2); 89 | 90 | e.emit("click", args); 91 | 92 | assert_eq!(args.x, 10); 93 | assert_eq!(args.y, 20); 94 | assert_eq!(e.listeners("click").unwrap().len(), 2); 95 | } 96 | 97 | #[test] 98 | fn emit_inline () { 99 | let mut e = EventEmitter::new(); 100 | 101 | e.on("click", |data: &mut dyn Any| { 102 | let d = &mut data.downcast_mut::().unwrap(); 103 | assert_eq!(d.x, 1); 104 | }); 105 | 106 | e.on("click", |data: &mut dyn Any| { 107 | let d = &mut data.downcast_mut::().unwrap(); 108 | assert_eq!(d.y, 2); 109 | }); 110 | 111 | struct Args { 112 | pub x: usize, 113 | pub y: usize, 114 | } 115 | 116 | e.emit("click", &mut Args { x: 1, y: 2 }); 117 | } 118 | 119 | #[test] 120 | fn off () { 121 | let mut e = EventEmitter::new(); 122 | 123 | e.on("click", |data: &mut dyn Any| { 124 | let d = &mut data.downcast_mut::().unwrap(); 125 | d.x = d.x + 1; 126 | }); 127 | 128 | struct Args { 129 | pub x: usize, 130 | } 131 | 132 | let args = &mut Args { x: 0 }; 133 | 134 | e.emit("click", args); 135 | assert_eq!(args.x, 1); 136 | e.emit("click", args); 137 | assert_eq!(args.x, 2); 138 | e.off("click"); 139 | e.emit("click", args); 140 | assert_eq!(args.x, 2); 141 | } 142 | } 143 | --------------------------------------------------------------------------------