1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::any::Any;
use std::borrow::Borrow;
pub struct ManagedState<Id: Eq + Clone + Send + Sync> {
state: Vec<Tracked<Id>>,
}
struct Tracked<Id: Eq + Clone + Send + Sync> {
id: Id,
state: Box<dyn Any + Send + Sync>,
}
pub struct ManagedStateTracker<'a, Id: Eq + Clone + Send + Sync> {
tracker: &'a mut ManagedState<Id>,
index: usize,
}
impl<Id: Eq + Clone + Send + Sync> ManagedState<Id> {
pub fn tracker(&mut self) -> ManagedStateTracker<Id> {
ManagedStateTracker {
tracker: self,
index: 0,
}
}
}
impl<Id: Eq + Clone + Send + Sync> Default for ManagedState<Id> {
fn default() -> Self {
Self { state: Vec::new() }
}
}
impl<Id: Eq + Clone + Send + Sync> Tracked<Id> {
unsafe fn unchecked_mut_ref<'a, T: Any + Send + Sync>(&mut self) -> &'a mut T {
let state = self
.state
.downcast_mut::<T>()
.expect("widgets with the same id must always be of the same type");
(state as *mut T).as_mut().unwrap()
}
}
impl<'a, Id: Eq + Clone + Send + Sync> ManagedStateTracker<'a, Id> {
pub fn get<'i, T, Q>(&mut self, id: &Q) -> &'i mut T
where
T: Default + Any + Send + Sync,
Q: ?Sized + Eq + ToOwned<Owned = Id>,
Id: Borrow<Q>,
{
self.get_or_default_with(id, T::default)
}
pub fn get_or_default<'i, T, Q>(&mut self, id: &Q, default: T) -> &'i mut T
where
T: Any + Send + Sync,
Q: ?Sized + Eq + ToOwned<Owned = Id>,
Id: Borrow<Q>,
{
self.get_or_default_with(id, move || default)
}
pub fn get_or_default_with<'i, T, Q, F>(&mut self, id: &Q, default: F) -> &'i mut T
where
T: Any + Send + Sync,
Q: ?Sized + Eq + ToOwned<Owned = Id>,
F: FnOnce() -> T,
Id: Borrow<Q>,
{
let search_start = self.index;
while self.index < self.tracker.state.len() {
if self.tracker.state[self.index].id.borrow().eq(id) {
self.tracker.state.drain(search_start..self.index).count();
unsafe {
let i = search_start;
self.index = search_start + 1;
return self.tracker.state[i].unchecked_mut_ref();
}
} else {
self.index += 1;
}
}
self.tracker.state.insert(
search_start,
Tracked {
id: id.to_owned(),
state: Box::new(default()) as Box<dyn Any + Send + Sync>,
},
);
self.index = search_start + 1;
unsafe { self.tracker.state[search_start].unchecked_mut_ref() }
}
}
impl<'a, Id: Eq + Clone + Send + Sync> Drop for ManagedStateTracker<'a, Id> {
fn drop(&mut self) {
while self.index < self.tracker.state.len() {
self.tracker.state.pop();
}
}
}