1 //! Provides utilities for managing callbacks. 2 3 use std::collections::HashMap; 4 use tokio::sync::mpsc::Sender; 5 6 use crate::{Message, RPCProxy}; 7 8 /// Utility for managing callbacks conveniently. 9 pub struct Callbacks<T: Send + ?Sized> { 10 callbacks: HashMap<u32, Box<T>>, 11 tx: Sender<Message>, 12 disconnected_message: fn(u32) -> Message, 13 } 14 15 impl<T: RPCProxy + Send + ?Sized> Callbacks<T> { 16 /// Creates new Callbacks. 17 /// 18 /// Parameters: 19 /// `tx`: Sender to use when notifying callback disconnect events. 20 /// `disconnected_message`: Constructor of the message to be sent on callback disconnection. new(tx: Sender<Message>, disconnected_message: fn(u32) -> Message) -> Self21 pub fn new(tx: Sender<Message>, disconnected_message: fn(u32) -> Message) -> Self { 22 Self { callbacks: HashMap::new(), tx, disconnected_message } 23 } 24 25 /// Stores a new callback and monitors for callback disconnect. 26 /// 27 /// When the callback disconnects, a message is sent. This message should be handled and then 28 /// the `remove_callback` function can be used. 29 /// 30 /// Returns the id of the callback. add_callback(&mut self, mut callback: Box<T>) -> u3231 pub fn add_callback(&mut self, mut callback: Box<T>) -> u32 { 32 let tx = self.tx.clone(); 33 let disconnected_message = self.disconnected_message; 34 let id = callback.register_disconnect(Box::new(move |cb_id| { 35 let tx = tx.clone(); 36 tokio::spawn(async move { 37 let _result = tx.send(disconnected_message(cb_id)).await; 38 }); 39 })); 40 41 self.callbacks.insert(id, callback); 42 id 43 } 44 45 /// Removes the callback given the id. 46 /// 47 /// When a callback is removed, disconnect monitoring is stopped and the proxy object is 48 /// removed. 49 /// 50 /// Returns true if callback is removed, false if there is no such id. remove_callback(&mut self, id: u32) -> bool51 pub fn remove_callback(&mut self, id: u32) -> bool { 52 match self.callbacks.get_mut(&id) { 53 Some(callback) => { 54 // Stop watching for disconnect. 55 callback.unregister(id); 56 // Remove the proxy object. 57 self.callbacks.remove(&id); 58 true 59 } 60 None => false, 61 } 62 } 63 64 /// Returns the callback object based on the given id. get_by_id(&self, id: u32) -> Option<&Box<T>>65 pub fn get_by_id(&self, id: u32) -> Option<&Box<T>> { 66 self.callbacks.get(&id) 67 } 68 69 /// Returns the mut callback object based on the given id. get_by_id_mut(&mut self, id: u32) -> Option<&mut Box<T>>70 pub fn get_by_id_mut(&mut self, id: u32) -> Option<&mut Box<T>> { 71 self.callbacks.get_mut(&id) 72 } 73 74 /// Applies the given function on all active callbacks. for_all_callbacks<F: Fn(&mut Box<T>)>(&mut self, f: F)75 pub fn for_all_callbacks<F: Fn(&mut Box<T>)>(&mut self, f: F) { 76 for (_, ref mut callback) in self.callbacks.iter_mut() { 77 f(callback); 78 } 79 } 80 } 81