ferroui_base/utilities/
handler_list.rs1use std::cell::{Cell, RefCell};
2use std::rc::Rc;
3
4pub struct HandlerList<F: ?Sized> {
8 handlers: RefCell<Rc<Vec<(u64, Rc<F>)>>>,
9 next_id: HandlerIds,
10}
11
12enum HandlerIds {
14 Own(Cell<u64>),
15 Shared(Rc<Cell<u64>>),
18}
19
20impl HandlerIds {
21 fn next(&self) -> u64 {
22 let cell = match self {
23 Self::Own(cell) => cell,
24 Self::Shared(cell) => cell,
25 };
26 let id = cell.get();
27 cell.set(id + 1);
28 id
29 }
30}
31
32impl<F: ?Sized> Default for HandlerList<F> {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl<F: ?Sized> HandlerList<F> {
39 pub fn new() -> Self {
40 Self { handlers: RefCell::new(Rc::new(Vec::new())), next_id: HandlerIds::Own(Cell::new(1)) }
41 }
42
43 pub fn with_shared_ids(ids: Rc<Cell<u64>>) -> Self {
46 Self { handlers: RefCell::new(Rc::new(Vec::new())), next_id: HandlerIds::Shared(ids) }
47 }
48
49 #[inline]
50 pub fn is_empty(&self) -> bool {
51 self.handlers.borrow().is_empty()
52 }
53
54 pub fn len(&self) -> usize {
55 self.handlers.borrow().len()
56 }
57
58 pub fn add(&self, handler: Rc<F>) -> u64 {
60 let id = self.next_id.next();
61 let mut handlers = self.handlers.borrow_mut();
62 Rc::make_mut_or_clone(&mut handlers).push((id, handler));
63 id
64 }
65
66 pub fn remove(&self, token: u64) -> bool {
68 let mut handlers = self.handlers.borrow_mut();
69 match handlers.iter().position(|(id, _)| *id == token) {
70 Some(index) => {
71 Rc::make_mut_or_clone(&mut handlers).remove(index);
72 true
73 }
74 None => false,
75 }
76 }
77
78 #[inline]
80 pub fn snapshot(&self) -> Rc<Vec<(u64, Rc<F>)>> {
81 self.handlers.borrow().clone()
82 }
83}
84
85trait MakeMutOrClone<T> {
86 fn make_mut_or_clone(this: &mut Self) -> &mut T;
87}
88
89impl<F: ?Sized> MakeMutOrClone<Vec<(u64, Rc<F>)>> for Rc<Vec<(u64, Rc<F>)>> {
90 fn make_mut_or_clone(this: &mut Self) -> &mut Vec<(u64, Rc<F>)> {
91 if Rc::get_mut(this).is_none() {
92 let copy: Vec<(u64, Rc<F>)> = this.iter().map(|(id, f)| (*id, f.clone())).collect();
93 *this = Rc::new(copy);
94 }
95 Rc::get_mut(this).expect("uniquely owned after copy")
96 }
97}