• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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