1use std::{any::TypeId, cell::RefCell, rc::Rc};
5
6use cranpose_core::{PackedU64, collections::map::HashMap};
7
8use super::{
9 AnyModifierElement, DynModifierElement, InvalidationKind, MAX_DELEGATE_DEPTH,
10 ModifierChainIter, ModifierChainNodeRef, ModifierNode, ModifierNodeContext, NodeCapabilities,
11 NodePath, chain_node_ref::ChainPosition,
12};
13
14#[derive(Debug)]
18struct ModifierNodeEntry {
19 key: Option<PackedU64>,
20 element: DynModifierElement,
21 node: Rc<RefCell<dyn ModifierNode>>,
22 capabilities: NodeCapabilities,
23 aggregate: NodeCapabilities,
26}
27
28impl ModifierNodeEntry {
29 fn new(
30 key: Option<PackedU64>,
31 element: DynModifierElement,
32 node: Rc<RefCell<dyn ModifierNode>>,
33 capabilities: NodeCapabilities,
34 ) -> Self {
35 let entry = Self {
36 key,
37 element,
38 node,
39 capabilities,
40 aggregate: NodeCapabilities::empty(),
41 };
42 entry
43 .node
44 .borrow()
45 .node_state()
46 .set_capabilities(entry.capabilities);
47 entry
48 }
49}
50
51fn visit_node_tree_mut(
52 node: &mut dyn ModifierNode,
53 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
54) {
55 visitor(node);
56 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
57}
58
59fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
60 let mut current = 0usize;
61 let mut result: Option<&dyn ModifierNode> = None;
62 node.for_each_delegate(&mut |child| {
63 if result.is_none() && current == target {
64 result = Some(child);
65 }
66 current += 1;
67 });
68 result
69}
70
71fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
72 let mut current = 0usize;
73 let mut result: Option<&mut dyn ModifierNode> = None;
74 node.for_each_delegate_mut(&mut |child| {
75 if result.is_none() && current == target {
76 result = Some(child);
77 }
78 current += 1;
79 });
80 result
81}
82
83fn with_node_context<F, R>(
84 node: &mut dyn ModifierNode,
85 context: &mut dyn ModifierNodeContext,
86 f: F,
87) -> R
88where
89 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
90{
91 context.push_active_capabilities(node.node_state().capabilities());
92 let result = f(node, context);
93 context.pop_active_capabilities();
94 result
95}
96
97fn request_update_auto_invalidations(
98 element: &dyn AnyModifierElement,
99 context: &mut dyn ModifierNodeContext,
100 capabilities: NodeCapabilities,
101) {
102 if let Some(kind) = element.update_invalidation_kind() {
103 let capabilities = NodeCapabilities::for_invalidation(kind);
104 context.push_active_capabilities(capabilities);
105 context.invalidate(kind);
106 context.pop_active_capabilities();
107 } else if element.auto_invalidates_on_update() {
108 request_auto_invalidations(context, capabilities);
109 }
110}
111
112fn request_auto_invalidations(
113 context: &mut dyn ModifierNodeContext,
114 capabilities: NodeCapabilities,
115) {
116 if capabilities.is_empty() {
117 return;
118 }
119
120 context.push_active_capabilities(capabilities);
121
122 if capabilities.contains(NodeCapabilities::LAYOUT) {
123 context.invalidate(InvalidationKind::Layout);
124 }
125 if capabilities.contains(NodeCapabilities::DRAW) {
126 context.invalidate(InvalidationKind::Draw);
127 }
128 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
129 context.invalidate(InvalidationKind::PointerInput);
130 }
131 if capabilities.contains(NodeCapabilities::SEMANTICS) {
132 context.invalidate(InvalidationKind::Semantics);
133 }
134 if capabilities.contains(NodeCapabilities::FOCUS) {
135 context.invalidate(InvalidationKind::Focus);
136 }
137
138 context.pop_active_capabilities();
139}
140
141fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
142 visit_node_tree_mut(node, &mut |n| {
143 if !n.node_state().is_attached() {
144 n.node_state().set_attached(true);
145 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
146 }
147 });
148}
149
150fn reset_node_tree(node: &mut dyn ModifierNode) {
151 visit_node_tree_mut(node, &mut |n| n.on_reset());
152}
153
154fn detach_node_tree(node: &mut dyn ModifierNode) {
155 visit_node_tree_mut(node, &mut |n| {
156 if n.node_state().is_attached() {
157 n.on_detach();
158 n.node_state().set_attached(false);
159 }
160 });
161}
162
163pub struct ModifierNodeChain {
170 entries: Vec<ModifierNodeEntry>,
171 pub(super) aggregated_capabilities: NodeCapabilities,
172 delegated_order: Vec<(NodePath, NodeCapabilities, NodeCapabilities)>,
178 attached: bool,
182}
183
184#[derive(Default)]
188struct ReconcileScratch {
189 old_used: Vec<bool>,
190 match_order: Vec<Option<usize>>,
191 final_slots: Vec<Option<ModifierNodeEntry>>,
192 elements: Vec<DynModifierElement>,
193}
194
195thread_local! {
196 static RECONCILE_SCRATCH: RefCell<ReconcileScratch> =
197 RefCell::default();
198}
199
200impl Default for ModifierNodeChain {
201 fn default() -> Self {
202 Self::new()
203 }
204}
205
206struct EntryIndex {
207 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
208 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
209 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
210}
211
212struct EntryMatchQuery<'a> {
213 element_type: TypeId,
214 node_type: TypeId,
215 key: Option<u64>,
216 hash_code: u64,
217 element: &'a DynModifierElement,
218}
219
220impl EntryIndex {
221 fn build(entries: &[ModifierNodeEntry]) -> Self {
222 let mut keyed = HashMap::default();
223 let mut hashed = HashMap::default();
224 let mut typed = HashMap::default();
225
226 for (i, entry) in entries.iter().enumerate() {
227 let (element_type, node_type) =
228 (entry.element.element_type(), entry.element.node_type());
229 if let Some(key_value) = entry.key {
230 keyed
231 .entry((element_type, node_type, key_value.get()))
232 .or_insert_with(Vec::new)
233 .push(i);
234 } else {
235 hashed
236 .entry((element_type, node_type, entry.element.hash_code()))
237 .or_insert_with(Vec::new)
238 .push(i);
239 typed
240 .entry((element_type, node_type))
241 .or_insert_with(Vec::new)
242 .push(i);
243 }
244 }
245
246 Self {
247 keyed,
248 hashed,
249 typed,
250 }
251 }
252
253 fn find_match(
254 &self,
255 entries: &[ModifierNodeEntry],
256 used: &[bool],
257 query: EntryMatchQuery<'_>,
258 ) -> Option<usize> {
259 if let Some(key_value) = query.key {
260 if let Some(candidates) =
261 self.keyed
262 .get(&(query.element_type, query.node_type, key_value))
263 {
264 for &i in candidates {
265 if !used[i] {
266 return Some(i);
267 }
268 }
269 }
270 } else {
271 if let Some(candidates) =
272 self.hashed
273 .get(&(query.element_type, query.node_type, query.hash_code))
274 {
275 for &i in candidates {
276 if !used[i]
277 && entries[i]
278 .element
279 .as_ref()
280 .equals_element(query.element.as_ref())
281 {
282 return Some(i);
283 }
284 }
285 }
286
287 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
288 for &i in candidates {
289 if !used[i] {
290 return Some(i);
291 }
292 }
293 }
294 }
295
296 None
297 }
298}
299
300#[derive(Clone, Copy, PartialEq, Eq)]
302enum InPlace {
303 LinksHold,
305 Relink,
308}
309
310fn update_entry_in_place(
315 entry: &mut ModifierNodeEntry,
316 element: &DynModifierElement,
317 context: &mut dyn ModifierNodeContext,
318) -> Option<InPlace> {
319 if entry.element.element_type() != element.element_type()
320 || entry.element.node_type() != element.node_type()
321 || entry.key.map(PackedU64::get) != element.key()
322 || !element.can_update_node(&*entry.node.borrow())
323 {
324 return None;
325 }
326 let same_element = entry.element.as_ref().equals_element(element.as_ref());
327 let capabilities = element.capabilities();
328 let mut outcome = if capabilities == entry.capabilities {
329 InPlace::LinksHold
330 } else {
331 InPlace::Relink
332 };
333 if !same_element || element.requires_update() {
334 element.update_node(&mut *entry.node.borrow_mut());
335 entry.element = Rc::clone(element);
336 request_update_auto_invalidations(element.as_ref(), context, capabilities);
337 entry
338 .node
339 .borrow()
340 .for_each_delegate(&mut |_| outcome = InPlace::Relink);
341 }
342 entry.capabilities = capabilities;
343 entry
344 .node
345 .borrow()
346 .node_state()
347 .set_capabilities(capabilities);
348 Some(outcome)
349}
350
351fn fresh_entry(
354 element: DynModifierElement,
355 context: &mut dyn ModifierNodeContext,
356 attach: bool,
357) -> ModifierNodeEntry {
358 let capabilities = element.capabilities();
359 let entry = ModifierNodeEntry::new(
360 element.key().map(PackedU64::new),
361 Rc::clone(&element),
362 element.create_node(),
363 capabilities,
364 );
365 if attach {
366 attach_node_tree(&mut *entry.node.borrow_mut(), context);
367 }
368 element.update_node(&mut *entry.node.borrow_mut());
369 request_auto_invalidations(context, capabilities);
370 entry
371}
372
373fn reconcile_element(
378 element: DynModifierElement,
379 new_pos: usize,
380 (old_entries, index): (&mut [ModifierNodeEntry], &EntryIndex),
381 (used, match_order): (&mut [bool], &mut [Option<usize>]),
382 context: &mut dyn ModifierNodeContext,
383 attach: bool,
384) -> Option<ModifierNodeEntry> {
385 let element_type = element.element_type();
386 let node_type = element.node_type();
387 let key = element.key();
388 let hash_code = if key.is_none() {
390 element.hash_code()
391 } else {
392 0
393 };
394 let capabilities = element.capabilities();
395 let Some(idx) = index.find_match(
396 old_entries,
397 used,
398 EntryMatchQuery {
399 element_type,
400 node_type,
401 key,
402 hash_code,
403 element: &element,
404 },
405 ) else {
406 return Some(fresh_entry(element, context, attach));
407 };
408 let entry = &mut old_entries[idx];
409 if !element.can_update_node(&*entry.node.borrow()) {
410 return Some(fresh_entry(element, context, attach));
411 }
412
413 used[idx] = true;
414 match_order[idx] = Some(new_pos);
415 let same_element = entry.element.as_ref().equals_element(element.as_ref());
416 if !same_element || element.requires_update() {
417 element.update_node(&mut *entry.node.borrow_mut());
418 entry.element = element;
419 request_update_auto_invalidations(entry.element.as_ref(), context, capabilities);
420 }
421 if idx != new_pos {
422 request_auto_invalidations(context, capabilities);
423 }
424 entry.key = key.map(PackedU64::new);
425 entry.capabilities = capabilities;
426 entry
427 .node
428 .borrow()
429 .node_state()
430 .set_capabilities(capabilities);
431 None
432}
433
434impl ModifierNodeChain {
435 pub fn new() -> Self {
437 let mut chain = Self::detached();
438 chain.attached = true;
439 chain
440 }
441
442 pub fn detached() -> Self {
445 Self {
446 entries: Vec::new(),
447 aggregated_capabilities: NodeCapabilities::empty(),
448 delegated_order: Vec::new(),
449 attached: false,
450 }
451 }
452
453 pub fn detach_nodes(&mut self) {
455 if !self.attached {
456 return;
457 }
458 self.attached = false;
459 for entry in &self.entries {
460 detach_node_tree(&mut *entry.node.borrow_mut());
461 }
462 }
463
464 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
466 if self.attached {
467 return;
468 }
469 self.attached = true;
470 for entry in &self.entries {
471 attach_node_tree(&mut *entry.node.borrow_mut(), context);
472 }
473 }
474
475 pub fn update_from_slice(
481 &mut self,
482 elements: &[DynModifierElement],
483 context: &mut dyn ModifierNodeContext,
484 ) {
485 self.update_from_ref_iter(elements.iter(), context);
486 }
487
488 pub fn update_entries_in_place<'a, I>(
494 &mut self,
495 elements: I,
496 element_count: usize,
497 changed: u64,
498 context: &mut dyn ModifierNodeContext,
499 ) -> bool
500 where
501 I: Iterator<Item = &'a DynModifierElement>,
502 {
503 if element_count != self.entries.len() {
504 return false;
505 }
506 let mut relink = false;
507 let updated = self
508 .entries
509 .iter_mut()
510 .zip(elements)
511 .enumerate()
512 .filter(|&(index, _)| {
513 u32::try_from(index)
514 .ok()
515 .and_then(|bit| changed.checked_shr(bit))
516 .is_some_and(|rest| rest & 1 == 1)
517 })
518 .map(|(_, pair)| pair)
519 .all(
520 |(entry, element)| match update_entry_in_place(entry, element, context) {
521 Some(outcome) => {
522 relink |= outcome == InPlace::Relink;
523 true
524 }
525 None => false,
526 },
527 );
528 if relink {
529 self.sync_chain_links();
530 }
531 updated
532 }
533
534 pub fn update_from_ref_iter<'a, I>(
537 &mut self,
538 elements: I,
539 context: &mut dyn ModifierNodeContext,
540 ) where
541 I: Iterator<Item = &'a DynModifierElement>,
542 {
543 let mut scratch = RECONCILE_SCRATCH
546 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
547 .unwrap_or_default();
548 self.reconcile(elements, context, &mut scratch);
549 scratch.elements.clear();
550 scratch.final_slots.clear();
551 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
552 }
553
554 fn reconcile<'a, I>(
555 &mut self,
556 elements: I,
557 context: &mut dyn ModifierNodeContext,
558 scratch: &mut ReconcileScratch,
559 ) where
560 I: Iterator<Item = &'a DynModifierElement>,
561 {
562 let old_len = self.entries.len();
563 let mut fast_path_failed_at: Option<usize> = None;
564 let mut elements_count = 0;
565 let mut relink = false;
568
569 scratch.elements.clear();
570
571 for (idx, element) in elements.enumerate() {
572 elements_count = idx + 1;
573 if fast_path_failed_at.is_none() && idx < old_len {
574 if let Some(outcome) =
575 update_entry_in_place(&mut self.entries[idx], element, context)
576 {
577 relink |= outcome == InPlace::Relink;
578 continue;
579 }
580 fast_path_failed_at = Some(idx);
581 }
582 scratch.elements.push(Rc::clone(element));
583 }
584
585 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
586 if elements_count < self.entries.len() {
587 for entry in self.entries.drain(elements_count..) {
588 request_auto_invalidations(context, entry.capabilities);
589 detach_node_tree(&mut *entry.node.borrow_mut());
590 }
591 relink = true;
592 }
593 if relink {
594 self.sync_chain_links();
595 }
596 return;
597 }
598
599 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
600 }
601
602 fn rebuild_tail(
606 &mut self,
607 fail_idx: usize,
608 context: &mut dyn ModifierNodeContext,
609 scratch: &mut ReconcileScratch,
610 ) {
611 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
612 let processed_entries_len = self.entries.len();
613 let old_len = old_entries.len();
614
615 scratch.old_used.clear();
616 scratch.old_used.resize(old_len, false);
617
618 scratch.match_order.clear();
619 scratch.match_order.resize(old_len, None);
620
621 let index = EntryIndex::build(&old_entries);
622
623 let new_elements_count = scratch.elements.len();
624 scratch.final_slots.clear();
625 scratch.final_slots.reserve(new_elements_count);
626
627 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
628 let fresh = reconcile_element(
629 element,
630 new_pos,
631 (&mut old_entries, &index),
632 (&mut scratch.old_used, &mut scratch.match_order),
633 context,
634 self.attached,
635 );
636 scratch.final_slots.push(fresh);
637 }
638
639 for (i, entry) in old_entries.into_iter().enumerate() {
640 match scratch.match_order[i] {
641 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
642 _ => {
643 request_auto_invalidations(context, entry.capabilities);
644 detach_node_tree(&mut *entry.node.borrow_mut());
645 }
646 }
647 }
648
649 self.entries.reserve_exact(scratch.final_slots.len());
653 for slot in scratch.final_slots.drain(..) {
654 if let Some(entry) = slot {
655 self.entries.push(entry);
656 } else {
657 log::error!("modifier reconciliation produced an empty final slot");
658 }
659 }
660
661 debug_assert_eq!(
662 self.entries.len(),
663 processed_entries_len + new_elements_count
664 );
665 self.sync_chain_links();
666 }
667
668 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
672 where
673 I: IntoIterator<Item = DynModifierElement>,
674 {
675 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
676 self.update_from_slice(&collected, context);
677 }
678
679 pub fn reset(&mut self) {
682 for entry in &mut self.entries {
683 reset_node_tree(&mut *entry.node.borrow_mut());
684 }
685 }
686
687 pub fn detach_all(&mut self) {
689 for entry in std::mem::take(&mut self.entries) {
690 detach_node_tree(&mut *entry.node.borrow_mut());
691 {
692 let node_borrow = entry.node.borrow();
693 let state = node_borrow.node_state();
694 state.set_capabilities(NodeCapabilities::empty());
695 }
696 }
697 self.sync_chain_links();
698 }
699
700 pub fn len(&self) -> usize {
702 self.entries.len()
703 }
704
705 pub fn is_empty(&self) -> bool {
707 self.entries.is_empty()
708 }
709
710 pub fn capabilities(&self) -> NodeCapabilities {
712 self.aggregated_capabilities
713 }
714
715 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
717 self.aggregated_capabilities.contains(capability)
718 }
719
720 pub fn head(&self) -> ModifierChainNodeRef<'_> {
722 self.node_ref(ChainPosition::Head)
723 }
724
725 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
727 self.node_ref(ChainPosition::Tail)
728 }
729
730 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
732 ModifierChainIter::forward(self)
733 }
734
735 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
737 ModifierChainIter::backward(self)
738 }
739
740 pub fn for_each_forward<F>(&self, mut f: F)
742 where
743 F: FnMut(ModifierChainNodeRef<'_>),
744 {
745 for node in self.head_to_tail() {
746 f(node);
747 }
748 }
749
750 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
752 where
753 F: FnMut(ModifierChainNodeRef<'_>),
754 {
755 if mask.is_empty() {
756 self.for_each_forward(f);
757 return;
758 }
759
760 if !self.head().aggregate_child_capabilities().intersects(mask) {
761 return;
762 }
763
764 for node in self.head_to_tail() {
765 if node.kind_set().intersects(mask) {
766 f(node);
767 }
768 }
769 }
770
771 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
773 where
774 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
775 {
776 self.for_each_forward_matching(mask, |node_ref| {
777 node_ref.with_node(|node| f(node_ref.clone(), node));
778 });
779 }
780
781 pub fn for_each_backward<F>(&self, mut f: F)
783 where
784 F: FnMut(ModifierChainNodeRef<'_>),
785 {
786 for node in self.tail_to_head() {
787 f(node);
788 }
789 }
790
791 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
793 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
794 node as *const dyn ModifierNode as *const ()
795 }
796
797 let target = node_data_ptr(node);
798 (0..self.order_len())
801 .find(|&index| {
802 self.with_path(self.order_at(index).0, |node| node_data_ptr(node) == target)
803 .unwrap_or(false)
804 })
805 .map(|index| self.node_ref(ChainPosition::Node(index)))
806 }
807
808 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
811 self.entries.get(index).and_then(|entry| {
812 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
813 boxed_node.as_any().downcast_ref::<N>()
814 })
815 .ok()
816 })
817 }
818
819 pub fn node_mut<N: ModifierNode + 'static>(
822 &self,
823 index: usize,
824 ) -> Option<std::cell::RefMut<'_, N>> {
825 self.entries.get(index).and_then(|entry| {
826 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
827 boxed_node.as_any_mut().downcast_mut::<N>()
828 })
829 .ok()
830 })
831 }
832
833 pub fn get_node_rc(&self, index: usize) -> Option<&Rc<RefCell<dyn ModifierNode>>> {
836 self.entries.get(index).map(|entry| &entry.node)
837 }
838
839 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
841 self.aggregated_capabilities
842 .contains(NodeCapabilities::for_invalidation(kind))
843 }
844
845 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
847 where
848 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
849 {
850 for index in 0..self.order_len() {
851 let (path, cached_caps, _agg) = self.order_at(index);
852 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
853 let mut current: &mut dyn ModifierNode = &mut *node_borrow;
854 for &delegate_index in path.delegates() {
855 match nth_delegate_mut(current, delegate_index as usize) {
856 Some(delegate) => current = delegate,
857 None => return,
858 }
859 }
860 f(current, cached_caps);
861 }
862 }
863
864 pub(super) fn node_ref(&self, position: ChainPosition) -> ModifierChainNodeRef<'_> {
865 ModifierChainNodeRef {
866 chain: self,
867 position,
868 }
869 }
870
871 pub(super) fn with_path<R>(
873 &self,
874 path: NodePath,
875 f: impl FnOnce(&dyn ModifierNode) -> R,
876 ) -> Option<R> {
877 let node_borrow = self.entries[path.entry()].node.borrow();
878 let mut current: &dyn ModifierNode = &*node_borrow;
879 for &delegate_index in path.delegates() {
880 current = nth_delegate(current, delegate_index as usize)?;
881 }
882 Some(f(current))
883 }
884
885 pub(super) fn order_len(&self) -> usize {
887 if self.delegated_order.is_empty() {
888 self.entries.len()
889 } else {
890 self.delegated_order.len()
891 }
892 }
893
894 pub(super) fn order_at(&self, index: usize) -> (NodePath, NodeCapabilities, NodeCapabilities) {
897 if self.delegated_order.is_empty() {
898 let entry = &self.entries[index];
899 (NodePath::root(index), entry.capabilities, entry.aggregate)
900 } else {
901 self.delegated_order[index]
902 }
903 }
904
905 fn sync_chain_links(&mut self) {
908 self.rebuild_delegated_order();
909 let mut aggregate = NodeCapabilities::empty();
910 if self.delegated_order.is_empty() {
911 for entry in self.entries.iter_mut().rev() {
912 aggregate |= entry.capabilities;
913 entry.aggregate = aggregate;
914 }
915 } else {
916 for (_, caps, aggregate_child) in self.delegated_order.iter_mut().rev() {
917 aggregate |= *caps;
918 *aggregate_child = aggregate;
919 }
920 }
921 self.aggregated_capabilities = aggregate;
922 }
923
924 fn rebuild_delegated_order(&mut self) {
925 let delegates = self.entries.iter().any(|entry| {
926 let mut delegates = false;
927 entry
928 .node
929 .borrow()
930 .for_each_delegate(&mut |_| delegates = true);
931 delegates
932 });
933 if !delegates {
934 self.delegated_order = Vec::new();
935 return;
936 }
937 self.delegated_order.clear();
938 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
939 for (index, entry) in self.entries.iter().enumerate() {
940 let node_borrow = entry.node.borrow();
941 Self::enumerate_link_order(
942 &*node_borrow,
943 index,
944 &mut path_buf,
945 0,
946 &mut self.delegated_order,
947 );
948 }
949 }
950
951 fn enumerate_link_order(
952 node: &dyn ModifierNode,
953 entry: usize,
954 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
955 path_len: usize,
956 out: &mut Vec<(NodePath, NodeCapabilities, NodeCapabilities)>,
957 ) {
958 let caps = node.node_state().capabilities();
959 out.push((
960 NodePath::from_slice(entry, &path_buf[..path_len]),
961 caps,
962 NodeCapabilities::empty(),
963 ));
964 let mut delegate_index = 0usize;
965 node.for_each_delegate(&mut |child| {
966 if path_len < MAX_DELEGATE_DEPTH {
967 path_buf[path_len] = delegate_index;
968 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
969 }
970 delegate_index += 1;
971 });
972 }
973}