1use std::{
2 any::Any,
3 cell::{Ref, RefCell, RefMut},
4 ops::Index,
5 rc::Rc,
6};
7
8use derive_ex::derive_ex;
9use slabmap::SlabMap;
10
11use crate::{
12 core::{
13 BindKey, BindSink, BindSource, DirtyOrMaybeDirty, NotifyContext, SinkBindings, Slot,
14 SourceBinder, UpdateContext,
15 },
16 utils::{Changes, RefCountOps},
17 ActionContext, SignalContext,
18};
19
20const SLOT_ITEMS: Slot = Slot(usize::MAX);
21
22fn key_to_slot(key: usize) -> Slot {
23 assert!(key != usize::MAX);
24 Slot(key)
25}
26fn slot_to_key(slot: Slot) -> Option<usize> {
27 if slot == SLOT_ITEMS {
28 None
29 } else {
30 Some(slot.0)
31 }
32}
33
34pub struct SignalSlabMap<T>(Rc<dyn DynSignalSlabMap<T>>);
35
36impl<T: 'static> SignalSlabMap<T> {
37 pub fn from_scan(f: impl FnMut(&mut ItemsMut<T>, &mut SignalContext) + 'static) -> Self {
38 Self(Scan::new(f))
39 }
40
41 pub fn item<'a, 's: 'a>(&'a self, key: usize, sc: &mut SignalContext<'s>) -> Ref<'a, T> {
42 self.0.item(self.0.clone().to_any(), key, sc)
43 }
44 pub fn items<'a, 's: 'a>(&'a self, sc: &mut SignalContext<'s>) -> Items<'a, T> {
45 self.0.items(self.0.clone().to_any(), None, sc)
46 }
47 pub fn reader(&self) -> SignalSlabMapReader<T> {
48 SignalSlabMapReader::new(self.0.clone())
49 }
50}
51
52trait DynSignalSlabMap<T> {
53 fn to_any(self: Rc<Self>) -> Rc<dyn Any>;
54 fn item(&self, this: Rc<dyn Any>, key: usize, sc: &mut SignalContext) -> Ref<T>;
55 fn items(&self, this: Rc<dyn Any>, age: Option<usize>, sc: &mut SignalContext) -> Items<T>;
56 fn ref_counts(&self) -> RefMut<RefCountOps>;
57}
58
59pub struct SignalSlabMapReader<T> {
60 owner: Rc<dyn DynSignalSlabMap<T>>,
61 age: Option<usize>,
62}
63impl<T: 'static> SignalSlabMapReader<T> {
64 fn new(owner: Rc<dyn DynSignalSlabMap<T>>) -> Self {
65 Self { owner, age: None }
66 }
67 pub fn read<'a, 's: 'a>(&'a mut self, sc: &mut SignalContext<'s>) -> Items<'a, T> {
68 let age = self.age;
69
70 let mut ref_counts = self.owner.ref_counts();
71 ref_counts.increment();
72 ref_counts.decrement(age);
73
74 let items = self.owner.items(self.owner.clone().to_any(), age, sc);
75 self.age = Some(items.items.changes.end_age());
76 items
77 }
78}
79impl<T> Drop for SignalSlabMapReader<T> {
80 fn drop(&mut self) {
81 self.owner.ref_counts().decrement(self.age);
82 }
83}
84
85pub struct Items<'a, T> {
86 items: Ref<'a, ItemsMut<T>>,
87 age: Option<usize>,
88}
89
90impl<'a, T> Items<'a, T> {
91 pub fn is_empty(&self) -> bool {
92 self.len() == 0
93 }
94 pub fn len(&self) -> usize {
95 self.items.len
96 }
97 pub fn get(&self, key: usize) -> Option<&T> {
98 self.items.get(key)
99 }
100 pub fn iter(&self) -> Iter<T> {
101 Iter(self.items.items.iter())
102 }
103 pub fn changes(&self) -> impl Iterator<Item = SlabMapChange<T>> {
104 use iter_n::iter2::*;
105 if let Some(age) = self.age {
106 self.items
107 .changes
108 .items(age)
109 .map(|change| {
110 let key = change.key;
111 let value = &self.items.items[key].value;
112 match change.action {
113 ChangeAction::Insert => SlabMapChange::Insert {
114 key,
115 new_value: value,
116 },
117 ChangeAction::Remove => SlabMapChange::Remove {
118 key,
119 old_value: value,
120 },
121 }
122 })
123 .into_iter0()
124 } else {
125 self.iter()
126 .map(|(key, value)| SlabMapChange::Insert {
127 key,
128 new_value: value,
129 })
130 .into_iter1()
131 }
132 }
133}
134impl<'a, T> Index<usize> for Items<'a, T> {
135 type Output = T;
136 fn index(&self, index: usize) -> &Self::Output {
137 self.get(index).expect("index out of bounds")
138 }
139}
140
141impl<'a, T> IntoIterator for &'a Items<'a, T> {
142 type Item = (usize, &'a T);
143 type IntoIter = Iter<'a, T>;
144
145 fn into_iter(self) -> Self::IntoIter {
146 self.iter()
147 }
148}
149
150pub struct ItemsMut<T> {
151 items: SlabMap<Item<T>>,
152 len: usize,
153 changes: Changes<ChangeData>,
154}
155impl<T> ItemsMut<T> {
156 fn new() -> Self {
157 Self {
158 items: SlabMap::new(),
159 len: 0,
160 changes: Changes::new(),
161 }
162 }
163 fn edit_start(&mut self, ref_counts: &RefCell<RefCountOps>) -> usize {
164 ref_counts.borrow_mut().apply(&mut self.changes);
165 self.clean_changes();
166 self.changes.end_age()
167 }
168 fn edit_end(
169 &mut self,
170 age: usize,
171 sinks: &mut SinkBindingsSet,
172 mut f: impl FnMut(&mut SinkBindings),
173 ) {
174 let mut is_dirty = false;
175 for c in self.changes.items(age) {
176 is_dirty = true;
177 if let Some(sink) = sinks.get_mut(key_to_slot(c.key)) {
178 f(sink);
179 }
180 }
181 if is_dirty {
182 f(&mut sinks.any);
183 }
184 self.clean_changes();
185 }
186 fn edit_end_and_update(
187 &mut self,
188 age: usize,
189 sinks: &mut SinkBindingsSet,
190 uc: &mut UpdateContext,
191 ) {
192 self.edit_end(age, sinks, |sink| sink.update(true, uc))
193 }
194 fn edit_end_and_notify(
195 &mut self,
196 sinks: &mut SinkBindingsSet,
197 age: usize,
198 nc: &mut NotifyContext,
199 ) {
200 self.edit_end(age, sinks, |sink| sink.notify(DirtyOrMaybeDirty::Dirty, nc))
201 }
202
203 pub fn get(&self, key: usize) -> Option<&T> {
204 let item = self.items.get(key)?;
205 if item.is_exists {
206 Some(&item.value)
207 } else {
208 None
209 }
210 }
211 pub fn insert(&mut self, value: T) -> usize {
212 let key = self.items.insert(Item::new(value));
213 self.len += 1;
214 self.changes.push(ChangeData {
215 action: ChangeAction::Insert,
216 key,
217 });
218 key
219 }
220 pub fn remove(&mut self, key: usize) {
221 let item = &mut self.items[key];
222 assert!(item.is_exists);
223 item.is_exists = false;
224 self.len -= 1;
225 self.changes.push(ChangeData {
226 action: ChangeAction::Remove,
227 key,
228 });
229 }
230
231 fn clean_changes(&mut self) {
232 self.changes.clean(|d| match d.action {
233 ChangeAction::Insert => {}
234 ChangeAction::Remove => {
235 self.items.remove(d.key);
236 }
237 });
238 }
239}
240impl<T> Index<usize> for ItemsMut<T> {
241 type Output = T;
242 fn index(&self, index: usize) -> &Self::Output {
243 self.get(index).expect("index out of bounds")
244 }
245}
246
247pub struct Iter<'a, T>(slabmap::Iter<'a, Item<T>>);
248
249impl<'a, T> Iterator for Iter<'a, T> {
250 type Item = (usize, &'a T);
251
252 fn next(&mut self) -> Option<Self::Item> {
253 for (key, value) in self.0.by_ref() {
254 if value.is_exists {
255 return Some((key, &value.value));
256 }
257 }
258 None
259 }
260}
261
262struct Item<T> {
263 value: T,
264 is_exists: bool,
265}
266impl<T> Item<T> {
267 fn new(value: T) -> Self {
268 Self {
269 value,
270 is_exists: true,
271 }
272 }
273}
274
275#[derive(Clone, Copy, Debug)]
276pub enum SlabMapChange<'a, T> {
277 Insert { key: usize, new_value: &'a T },
278 Remove { key: usize, old_value: &'a T },
279}
280
281enum ChangeAction {
282 Insert,
283 Remove,
284}
285
286struct ChangeData {
287 action: ChangeAction,
288 key: usize,
289}
290
291#[derive_ex(Default, Clone(bound()))]
292#[default(Self::new())]
293pub struct StateSlabMap<T>(Rc<RawStateSlabMap<T>>);
294
295impl<T> StateSlabMap<T> {
296 pub fn new() -> Self {
297 Self(Rc::new(RawStateSlabMap {
298 items: RefCell::new(ItemsMut::new()),
299 sinks: RefCell::new(SinkBindingsSet::new()),
300 ref_counts: RefCell::new(RefCountOps::new()),
301 }))
302 }
303}
304
305impl<T: 'static> StateSlabMap<T> {
306 pub fn to_signal_slab_map(&self) -> SignalSlabMap<T> {
307 SignalSlabMap(self.0.clone())
308 }
309 pub fn insert(&self, value: T, ac: &mut ActionContext) -> usize {
310 let mut data = self.0.items.borrow_mut();
311 let age = data.edit_start(&self.0.ref_counts);
312 let key = data.insert(value);
313 data.edit_end_and_notify(&mut self.0.sinks.borrow_mut(), age, ac.nc());
314 key
315 }
316 pub fn remove(&self, key: usize, ac: &mut ActionContext) {
317 let mut data = self.0.items.borrow_mut();
318 let age = data.edit_start(&self.0.ref_counts);
319 data.remove(key);
320 data.edit_end_and_notify(&mut self.0.sinks.borrow_mut(), age, ac.nc());
321 }
322 pub fn item<'a, 's: 'a>(&'a self, key: usize, sc: &mut SignalContext<'s>) -> Ref<'a, T> {
323 self.0.bind(key_to_slot(key), sc);
324 self.0.item(key)
325 }
326 pub fn items<'a, 's: 'a>(&'a self, sc: &mut SignalContext<'s>) -> Items<'a, T> {
327 self.0.bind(SLOT_ITEMS, sc);
328 self.0.items(None)
329 }
330 pub fn reader(&self) -> SignalSlabMapReader<T> {
331 SignalSlabMapReader::new(self.0.clone())
332 }
333}
334
335struct RawStateSlabMap<T> {
336 items: RefCell<ItemsMut<T>>,
337 sinks: RefCell<SinkBindingsSet>,
338 ref_counts: RefCell<RefCountOps>,
339}
340impl<T: 'static> RawStateSlabMap<T> {
341 fn rc_this(this: Rc<dyn Any>) -> Rc<Self> {
342 Rc::downcast(this).unwrap()
343 }
344 fn bind(self: &Rc<Self>, slot: Slot, sc: &mut SignalContext) {
345 self.sinks.borrow_mut().bind(self.clone(), slot, sc);
346 }
347 fn item(&self, key: usize) -> Ref<T> {
348 Ref::map(self.items.borrow(), |r| r.get(key).expect("key not found"))
349 }
350 fn items(&self, age: Option<usize>) -> Items<T> {
351 let items = self.items.borrow();
352 Items { items, age }
353 }
354}
355
356impl<T: 'static> DynSignalSlabMap<T> for RawStateSlabMap<T> {
357 fn to_any(self: Rc<Self>) -> Rc<dyn Any> {
358 self
359 }
360
361 fn item(&self, this: Rc<dyn Any>, key: usize, sc: &mut SignalContext) -> Ref<T> {
362 Self::rc_this(this).bind(key_to_slot(key), sc);
363 self.item(key)
364 }
365
366 fn items(&self, this: Rc<dyn Any>, age: Option<usize>, sc: &mut SignalContext) -> Items<T> {
367 Self::rc_this(this).bind(SLOT_ITEMS, sc);
368 self.items(age)
369 }
370
371 fn ref_counts(&self) -> RefMut<RefCountOps> {
372 self.ref_counts.borrow_mut()
373 }
374}
375
376impl<T: 'static> BindSource for RawStateSlabMap<T> {
377 fn check(self: Rc<Self>, slot: Slot, key: BindKey, uc: &mut UpdateContext) -> bool {
378 self.sinks.borrow_mut().is_dirty(slot, key, uc)
379 }
380 fn unbind(self: Rc<Self>, slot: Slot, key: BindKey, uc: &mut UpdateContext) {
381 self.sinks.borrow_mut().unbind(slot, key, uc);
382 }
383 fn rebind(self: Rc<Self>, slot: Slot, key: BindKey, sc: &mut SignalContext) {
384 self.sinks.borrow_mut().rebind(self.clone(), slot, key, sc);
385 }
386}
387
388struct SinkBindingsSet {
389 items: Vec<SinkBindings>,
390 any: SinkBindings,
391}
392impl SinkBindingsSet {
393 fn new() -> Self {
394 Self {
395 items: Vec::new(),
396 any: SinkBindings::new(),
397 }
398 }
399 fn update_all(&mut self, is_dirty: bool, uc: &mut UpdateContext) {
400 for s in &mut self.items {
401 s.update(is_dirty, uc);
402 }
403 self.any.update(is_dirty, uc);
404 }
405 fn notify_all(&mut self, dirty: DirtyOrMaybeDirty, nc: &mut NotifyContext) {
406 for s in &mut self.items {
407 s.notify(dirty, nc);
408 }
409 self.any.notify(dirty, nc);
410 }
411
412 fn bind(&mut self, this: Rc<dyn BindSource>, slot: Slot, sc: &mut SignalContext) {
413 if let Some(key) = slot_to_key(slot) {
414 if self.items.len() < key {
415 self.items.resize_with(key + 1, SinkBindings::new);
416 }
417 }
418 if let Some(s) = self.get_mut(slot) {
419 s.bind(this, slot, sc);
420 }
421 }
422 fn unbind(&mut self, slot: Slot, key: BindKey, uc: &mut UpdateContext) {
423 if let Some(s) = self.get_mut(slot) {
424 s.unbind(key, uc);
425 }
426 }
427 fn rebind(
428 &mut self,
429 this: Rc<dyn BindSource>,
430 slot: Slot,
431 key: BindKey,
432 sc: &mut SignalContext,
433 ) {
434 if let Some(s) = self.get_mut(slot) {
435 s.rebind(this, slot, key, sc);
436 }
437 }
438
439 fn is_dirty(&self, slot: Slot, key: BindKey, uc: &mut UpdateContext) -> bool {
440 if let Some(s) = self.get(slot) {
441 s.is_dirty(key, uc)
442 } else {
443 true
444 }
445 }
446
447 fn get(&self, slot: Slot) -> Option<&SinkBindings> {
448 if let Some(key) = slot_to_key(slot) {
449 self.items.get(key)
450 } else {
451 Some(&self.any)
452 }
453 }
454 fn get_mut(&mut self, slot: Slot) -> Option<&mut SinkBindings> {
455 if let Some(key) = slot_to_key(slot) {
456 self.items.get_mut(key)
457 } else {
458 Some(&mut self.any)
459 }
460 }
461}
462
463struct Scan<T, F> {
464 data: RefCell<ScanData<T, F>>,
465 ref_counts: RefCell<RefCountOps>,
466 sinks: RefCell<SinkBindingsSet>,
467}
468impl<T, F> Scan<T, F>
469where
470 T: 'static,
471 F: FnMut(&mut ItemsMut<T>, &mut SignalContext) + 'static,
472{
473 fn new(f: F) -> Rc<Self> {
474 Rc::new_cyclic(|this| Self {
475 data: RefCell::new(ScanData {
476 sb: SourceBinder::new(this, Slot(0)),
477 items: ItemsMut::new(),
478 f,
479 }),
480 ref_counts: RefCell::new(RefCountOps::new()),
481 sinks: RefCell::new(SinkBindingsSet::new()),
482 })
483 }
484
485 fn update(self: &Rc<Self>, uc: &mut UpdateContext) {
486 if uc.borrow(&self.data).sb.is_clean() {
487 return;
488 }
489 let d = &mut *self.data.borrow_mut();
490 if d.sb.check(uc) {
491 let age = d.items.edit_start(&self.ref_counts);
492 d.sb.update(|sc| (d.f)(&mut d.items, sc), uc);
493 d.items
494 .edit_end_and_update(age, &mut self.sinks.borrow_mut(), uc);
495 }
496 self.sinks.borrow_mut().update_all(false, uc);
497 }
498 fn rc_this(this: Rc<dyn Any>) -> Rc<Self> {
499 Rc::downcast(this).unwrap()
500 }
501}
502
503impl<T, F> DynSignalSlabMap<T> for Scan<T, F>
504where
505 T: 'static,
506 F: FnMut(&mut ItemsMut<T>, &mut SignalContext) + 'static,
507{
508 fn to_any(self: Rc<Self>) -> Rc<dyn Any> {
509 self
510 }
511
512 fn item(&self, this: Rc<dyn Any>, key: usize, sc: &mut SignalContext) -> Ref<T> {
513 let this = Self::rc_this(this);
514 this.update(sc.uc());
515 self.sinks.borrow_mut().bind(this, key_to_slot(key), sc);
516 Ref::map(self.data.borrow(), |data| &data.items[key])
517 }
518
519 fn items(&self, this: Rc<dyn Any>, age: Option<usize>, sc: &mut SignalContext) -> Items<T> {
520 let this = Self::rc_this(this);
521 this.update(sc.uc());
522 self.sinks.borrow_mut().bind(this, SLOT_ITEMS, sc);
523 let data = Ref::map(self.data.borrow(), |data| &data.items);
524 Items { items: data, age }
525 }
526 fn ref_counts(&self) -> RefMut<RefCountOps> {
527 self.ref_counts.borrow_mut()
528 }
529}
530impl<T, F> BindSource for Scan<T, F>
531where
532 T: 'static,
533 F: FnMut(&mut ItemsMut<T>, &mut SignalContext) + 'static,
534{
535 fn check(self: Rc<Self>, slot: Slot, key: BindKey, uc: &mut UpdateContext) -> bool {
536 self.update(uc);
537 self.sinks.borrow().is_dirty(slot, key, uc)
538 }
539
540 fn unbind(self: Rc<Self>, slot: Slot, key: BindKey, uc: &mut UpdateContext) {
541 self.sinks.borrow_mut().unbind(slot, key, uc)
542 }
543
544 fn rebind(self: Rc<Self>, slot: Slot, key: BindKey, sc: &mut SignalContext) {
545 self.sinks.borrow_mut().rebind(self.clone(), slot, key, sc)
546 }
547}
548impl<T, F> BindSink for Scan<T, F>
549where
550 T: 'static,
551 F: FnMut(&mut ItemsMut<T>, &mut SignalContext) + 'static,
552{
553 fn notify(self: Rc<Self>, slot: Slot, dirty: DirtyOrMaybeDirty, nc: &mut NotifyContext) {
554 if self.data.borrow_mut().sb.on_notify(slot, dirty) {
555 self.sinks
556 .borrow_mut()
557 .notify_all(DirtyOrMaybeDirty::MaybeDirty, nc);
558 }
559 }
560}
561
562struct ScanData<T, F> {
563 sb: SourceBinder,
564 items: ItemsMut<T>,
565 f: F,
566}