1use std::{
9 any::{Any, TypeId, type_name},
10 cell::{Cell, RefCell},
11 fmt,
12 hash::{Hash, Hasher},
13 ops::{BitOr, BitOrAssign},
14 rc::Rc,
15};
16
17use cranpose_core::{collections::map::HashMap, hash::default};
18pub use cranpose_ui_graphics::{DrawScope, Size};
19pub use cranpose_ui_layout::{Constraints, Measurable};
20
21use crate::nodes::input::types::PointerEvent;
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
26pub enum InvalidationKind {
27 Layout,
28 Draw,
29 PointerInput,
30 Semantics,
31 Focus,
32}
33
34pub trait ModifierNodeContext {
36 fn invalidate(&mut self, _kind: InvalidationKind) {}
38
39 fn request_update(&mut self) {}
42
43 fn node_id(&self) -> Option<cranpose_core::NodeId> {
46 None
47 }
48
49 fn push_active_capabilities(&mut self, _capabilities: NodeCapabilities) {}
51
52 fn pop_active_capabilities(&mut self) {}
54}
55
56#[derive(Default, Debug, Clone)]
65pub struct BasicModifierNodeContext {
66 invalidations: Vec<ModifierInvalidation>,
67 update_requested: bool,
68 active_capabilities: Vec<NodeCapabilities>,
69 node_id: Option<cranpose_core::NodeId>,
70}
71
72impl BasicModifierNodeContext {
73 pub fn new() -> Self {
75 Self::default()
76 }
77
78 pub fn invalidations(&self) -> &[ModifierInvalidation] {
82 &self.invalidations
83 }
84
85 pub fn clear_invalidations(&mut self) {
87 self.invalidations.clear();
88 }
89
90 pub fn take_invalidations(&mut self) -> Vec<ModifierInvalidation> {
92 std::mem::take(&mut self.invalidations)
93 }
94
95 pub fn update_requested(&self) -> bool {
98 self.update_requested
99 }
100
101 pub fn take_update_requested(&mut self) -> bool {
103 std::mem::take(&mut self.update_requested)
104 }
105
106 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
108 self.node_id = id;
109 }
110
111 fn push_invalidation(&mut self, kind: InvalidationKind) {
112 let mut capabilities = self.current_capabilities();
113 capabilities.insert(NodeCapabilities::for_invalidation(kind));
114 if let Some(existing) = self
115 .invalidations
116 .iter_mut()
117 .find(|entry| entry.kind() == kind)
118 {
119 let updated = existing.capabilities() | capabilities;
120 *existing = ModifierInvalidation::new(kind, updated);
121 } else {
122 self.invalidations
123 .push(ModifierInvalidation::new(kind, capabilities));
124 }
125 }
126
127 fn current_capabilities(&self) -> NodeCapabilities {
128 self.active_capabilities
129 .last()
130 .copied()
131 .unwrap_or_else(NodeCapabilities::empty)
132 }
133}
134
135impl ModifierNodeContext for BasicModifierNodeContext {
136 fn invalidate(&mut self, kind: InvalidationKind) {
137 self.push_invalidation(kind);
138 }
139
140 fn request_update(&mut self) {
141 self.update_requested = true;
142 }
143
144 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
145 self.active_capabilities.push(capabilities);
146 }
147
148 fn pop_active_capabilities(&mut self) {
149 self.active_capabilities.pop();
150 }
151
152 fn node_id(&self) -> Option<cranpose_core::NodeId> {
153 self.node_id
154 }
155}
156
157const MAX_DELEGATE_DEPTH: usize = 3;
161
162#[derive(Copy, Clone, Debug, PartialEq, Eq)]
163pub(crate) struct NodePath {
164 entry: usize,
165 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
166 delegate_len: u8,
167}
168
169impl NodePath {
170 #[inline]
171 fn root(entry: usize) -> Self {
172 Self {
173 entry,
174 delegate_buf: [0; MAX_DELEGATE_DEPTH],
175 delegate_len: 0,
176 }
177 }
178
179 #[inline]
180 fn from_slice(entry: usize, path: &[usize]) -> Self {
181 debug_assert!(
182 path.len() <= MAX_DELEGATE_DEPTH,
183 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
184 path.len(),
185 MAX_DELEGATE_DEPTH
186 );
187 debug_assert!(
188 path.iter().all(|&i| i <= u8::MAX as usize),
189 "delegate index exceeds u8 range"
190 );
191 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
192 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
193 delegate_buf[i] = v as u8;
194 }
195 Self {
196 entry,
197 delegate_buf,
198 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
199 }
200 }
201
202 #[inline]
203 fn entry(&self) -> usize {
204 self.entry
205 }
206
207 #[inline]
208 fn delegates(&self) -> &[u8] {
209 &self.delegate_buf[..self.delegate_len as usize]
210 }
211}
212
213#[derive(Copy, Clone, Debug, PartialEq, Eq)]
214pub(crate) enum NodeLink {
215 Head,
216 Tail,
217 Entry(NodePath),
218}
219
220#[derive(Debug)]
226pub struct NodeState {
227 aggregate_child_capabilities: Cell<NodeCapabilities>,
228 capabilities: Cell<NodeCapabilities>,
229 parent: RefCell<Option<NodeLink>>,
230 child: RefCell<Option<NodeLink>>,
231 attached: Cell<bool>,
232 is_sentinel: bool,
233}
234
235impl Default for NodeState {
236 fn default() -> Self {
237 Self::new()
238 }
239}
240
241impl NodeState {
242 pub const fn new() -> Self {
243 Self {
244 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
245 capabilities: Cell::new(NodeCapabilities::empty()),
246 parent: RefCell::new(None),
247 child: RefCell::new(None),
248 attached: Cell::new(false),
249 is_sentinel: false,
250 }
251 }
252
253 pub const fn sentinel() -> Self {
254 Self {
255 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
256 capabilities: Cell::new(NodeCapabilities::empty()),
257 parent: RefCell::new(None),
258 child: RefCell::new(None),
259 attached: Cell::new(true),
260 is_sentinel: true,
261 }
262 }
263
264 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
265 self.capabilities.set(capabilities);
266 }
267
268 #[inline]
269 pub fn capabilities(&self) -> NodeCapabilities {
270 self.capabilities.get()
271 }
272
273 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
274 self.aggregate_child_capabilities.set(capabilities);
275 }
276
277 #[inline]
278 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
279 self.aggregate_child_capabilities.get()
280 }
281
282 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
283 *self.parent.borrow_mut() = parent;
284 }
285
286 #[inline]
287 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
288 *self.parent.borrow()
289 }
290
291 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
292 *self.child.borrow_mut() = child;
293 }
294
295 #[inline]
296 pub(crate) fn child_link(&self) -> Option<NodeLink> {
297 *self.child.borrow()
298 }
299
300 pub fn set_attached(&self, attached: bool) {
301 self.attached.set(attached);
302 }
303
304 pub fn is_attached(&self) -> bool {
305 self.attached.get()
306 }
307
308 pub fn is_sentinel(&self) -> bool {
309 self.is_sentinel
310 }
311}
312
313pub trait DelegatableNode {
315 fn node_state(&self) -> &NodeState;
316 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
317 self.node_state().aggregate_child_capabilities()
318 }
319}
320
321pub trait ModifierNode: Any + DelegatableNode {
379 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
380
381 fn on_detach(&mut self) {}
382
383 fn on_reset(&mut self) {}
384
385 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
387 None
388 }
389
390 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
392 None
393 }
394
395 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
397 None
398 }
399
400 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
402 None
403 }
404
405 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
407 None
408 }
409
410 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
412 None
413 }
414
415 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
417 None
418 }
419
420 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
422 None
423 }
424
425 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
427 None
428 }
429
430 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
432 None
433 }
434
435 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
437
438 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
440 }
441}
442
443pub trait LayoutModifierNode: ModifierNode {
449 fn measure(
471 &self,
472 _context: &mut dyn ModifierNodeContext,
473 measurable: &dyn Measurable,
474 constraints: Constraints,
475 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
476 let placeable = measurable.measure(constraints);
477 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
478 width: placeable.width(),
479 height: placeable.height(),
480 })
481 }
482
483 fn min_intrinsic_width(&self, _measurable: &dyn Measurable, _height: f32) -> f32 {
485 0.0
486 }
487
488 fn max_intrinsic_width(&self, _measurable: &dyn Measurable, _height: f32) -> f32 {
490 0.0
491 }
492
493 fn min_intrinsic_height(&self, _measurable: &dyn Measurable, _width: f32) -> f32 {
495 0.0
496 }
497
498 fn max_intrinsic_height(&self, _measurable: &dyn Measurable, _width: f32) -> f32 {
500 0.0
501 }
502}
503
504pub trait DrawModifierNode: ModifierNode {
512 fn draw(&self, _draw_scope: &mut dyn DrawScope) {}
521
522 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
533 None
534 }
535
536 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
541 None
542 }
543}
544
545pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
550
551pub trait PointerInputNode: ModifierNode {
557 fn on_pointer_event(
560 &mut self,
561 _context: &mut dyn ModifierNodeContext,
562 _event: &PointerEvent,
563 ) -> bool {
564 false
565 }
566
567 fn hit_test(&self, _x: f32, _y: f32) -> bool {
570 true
571 }
572
573 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
575 None
576 }
577
578 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
591 None
592 }
593}
594
595pub trait SemanticsNode: ModifierNode {
601 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
603}
604
605#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
610pub enum FocusState {
611 Active,
613 ActiveParent,
615 Captured,
619 #[default]
622 Inactive,
623}
624
625impl FocusState {
626 pub fn is_focused(self) -> bool {
628 matches!(self, FocusState::Active | FocusState::Captured)
629 }
630
631 pub fn has_focus(self) -> bool {
633 matches!(
634 self,
635 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
636 )
637 }
638
639 pub fn is_captured(self) -> bool {
641 matches!(self, FocusState::Captured)
642 }
643}
644
645pub trait FocusNode: ModifierNode {
650 fn focus_state(&self) -> FocusState;
652
653 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
655}
656
657#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
668pub enum SemanticsWidgetRole {
669 Button,
670 Checkbox,
671 Switch,
672 RadioButton,
673 Tab,
674 Image,
675 Header,
680 Dialog,
684}
685
686#[derive(Clone, Copy, Debug, PartialEq)]
694pub struct ProgressBarRangeInfo {
695 pub current: f32,
696 pub start: f32,
697 pub end: f32,
698 pub steps: u32,
701}
702
703impl ProgressBarRangeInfo {
704 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
705 Self {
706 current,
707 start,
708 end,
709 steps,
710 }
711 }
712
713 pub fn fraction(&self) -> f32 {
715 let span = self.end - self.start;
716 if span.abs() < f32::EPSILON {
717 return 0.0;
718 }
719 ((self.current - self.start) / span).clamp(0.0, 1.0)
720 }
721
722 pub fn step(&self) -> f32 {
725 let span = self.end - self.start;
726 if self.steps == 0 {
727 span / 10.0
728 } else {
729 span / (self.steps as f32 + 1.0)
730 }
731 }
732}
733
734#[derive(Clone, Copy, Debug, PartialEq)]
742pub struct ScrollAxisRange {
743 pub value: f32,
744 pub max_value: f32,
745 pub reverse: bool,
746}
747
748impl ScrollAxisRange {
749 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
750 Self {
751 value,
752 max_value,
753 reverse,
754 }
755 }
756
757 pub fn can_scroll_forward(&self) -> bool {
758 self.value < self.max_value
759 }
760
761 pub fn can_scroll_backward(&self) -> bool {
762 self.value > 0.0
763 }
764}
765
766#[derive(Clone)]
772pub struct SemanticsScrollBy {
773 handler: Rc<dyn Fn(f32, f32) -> bool>,
774}
775
776impl SemanticsScrollBy {
777 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
778 Self {
779 handler: Rc::new(handler),
780 }
781 }
782
783 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
784 (self.handler)(dx, dy)
785 }
786}
787
788impl fmt::Debug for SemanticsScrollBy {
789 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
790 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
791 }
792}
793
794impl PartialEq for SemanticsScrollBy {
797 fn eq(&self, _other: &Self) -> bool {
798 true
799 }
800}
801
802impl Eq for SemanticsScrollBy {}
803
804#[derive(Clone)]
810pub struct SemanticsSetProgress {
811 handler: Rc<dyn Fn(f32) -> bool>,
812}
813
814impl SemanticsSetProgress {
815 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
816 Self {
817 handler: Rc::new(handler),
818 }
819 }
820
821 pub fn invoke(&self, value: f32) -> bool {
822 (self.handler)(value)
823 }
824}
825
826impl fmt::Debug for SemanticsSetProgress {
827 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
828 f.debug_struct("SemanticsSetProgress")
829 .finish_non_exhaustive()
830 }
831}
832
833impl PartialEq for SemanticsSetProgress {
838 fn eq(&self, _other: &Self) -> bool {
839 true
840 }
841}
842
843impl Eq for SemanticsSetProgress {}
844
845#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
852pub enum LiveRegionMode {
853 Polite,
855 Assertive,
858}
859
860#[derive(Clone)]
867pub struct SemanticsCustomAction {
868 pub label: String,
870 handler: Rc<dyn Fn()>,
871}
872
873impl SemanticsCustomAction {
874 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
875 Self {
876 label: label.into(),
877 handler: Rc::new(handler),
878 }
879 }
880
881 pub fn invoke(&self) {
882 (self.handler)();
883 }
884}
885
886impl fmt::Debug for SemanticsCustomAction {
887 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
888 f.debug_struct("SemanticsCustomAction")
889 .field("label", &self.label)
890 .finish_non_exhaustive()
891 }
892}
893
894impl PartialEq for SemanticsCustomAction {
904 fn eq(&self, other: &Self) -> bool {
905 self.label == other.label
906 }
907}
908
909impl Eq for SemanticsCustomAction {}
910
911#[derive(Clone, Debug, PartialEq)]
926pub struct CanvasSemanticsNode {
927 pub key: u64,
934 pub bounds: cranpose_ui_graphics::Rect,
936 pub label: String,
937 pub role: Option<SemanticsWidgetRole>,
938 pub state_description: Option<String>,
942 pub on_click_label: Option<String>,
945 pub clickable: bool,
946 pub selected: Option<bool>,
948 pub toggled: Option<bool>,
950 pub enabled: bool,
951 pub custom_actions: Vec<SemanticsCustomAction>,
952}
953
954impl Default for CanvasSemanticsNode {
955 fn default() -> Self {
956 Self {
957 key: 0,
958 bounds: cranpose_ui_graphics::Rect {
959 x: 0.0,
960 y: 0.0,
961 width: 0.0,
962 height: 0.0,
963 },
964 label: String::new(),
965 role: None,
966 state_description: None,
967 on_click_label: None,
968 clickable: false,
969 selected: None,
970 toggled: None,
971 enabled: true,
972 custom_actions: Vec::new(),
973 }
974 }
975}
976
977impl CanvasSemanticsNode {
978 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
980 Self {
981 key,
982 bounds,
983 label: label.into(),
984 clickable: true,
985 ..Self::default()
986 }
987 }
988
989 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
991 Self {
992 key,
993 bounds,
994 label: label.into(),
995 ..Self::default()
996 }
997 }
998
999 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1000 self.role = Some(role);
1001 self
1002 }
1003
1004 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1005 self.state_description = Some(state.into());
1006 self
1007 }
1008
1009 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1010 self.on_click_label = Some(label.into());
1011 self.clickable = true;
1012 self
1013 }
1014
1015 pub fn with_selected(mut self, selected: bool) -> Self {
1016 self.selected = Some(selected);
1017 self
1018 }
1019
1020 pub fn with_toggled(mut self, toggled: bool) -> Self {
1021 self.toggled = Some(toggled);
1022 self
1023 }
1024
1025 pub fn with_enabled(mut self, enabled: bool) -> Self {
1026 self.enabled = enabled;
1027 self
1028 }
1029
1030 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1031 self.custom_actions.push(action);
1032 self
1033 }
1034}
1035
1036#[derive(Clone, Debug, PartialEq)]
1038pub struct SemanticsConfiguration {
1039 pub content_description: Option<String>,
1040 pub state_description: Option<String>,
1042 pub on_click_label: Option<String>,
1044 pub role: Option<SemanticsWidgetRole>,
1046 pub selected: Option<bool>,
1047 pub toggled: Option<bool>,
1048 pub enabled: bool,
1049 pub is_clickable: bool,
1050 pub is_editable_text: bool,
1051 pub text_selection: Option<crate::text::TextRange>,
1052 pub custom_actions: Vec<SemanticsCustomAction>,
1053 pub canvas_children: Vec<CanvasSemanticsNode>,
1056 pub is_modal: bool,
1059 pub live_region: Option<LiveRegionMode>,
1062 pub progress: Option<ProgressBarRangeInfo>,
1065 pub set_progress: Option<SemanticsSetProgress>,
1068 pub vertical_scroll: Option<ScrollAxisRange>,
1071 pub horizontal_scroll: Option<ScrollAxisRange>,
1074 pub scroll_by: Option<SemanticsScrollBy>,
1077}
1078
1079impl Default for SemanticsConfiguration {
1080 fn default() -> Self {
1081 Self {
1082 content_description: None,
1083 state_description: None,
1084 on_click_label: None,
1085 role: None,
1086 selected: None,
1087 toggled: None,
1088 enabled: true,
1089 is_clickable: false,
1090 is_editable_text: false,
1091 text_selection: None,
1092 custom_actions: Vec::new(),
1093 canvas_children: Vec::new(),
1094 is_modal: false,
1095 live_region: None,
1096 progress: None,
1097 set_progress: None,
1098 vertical_scroll: None,
1099 horizontal_scroll: None,
1100 scroll_by: None,
1101 }
1102 }
1103}
1104
1105impl SemanticsConfiguration {
1106 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1107 if let Some(description) = &other.content_description {
1108 self.content_description = Some(description.clone());
1109 }
1110 if let Some(state) = &other.state_description {
1111 self.state_description = Some(state.clone());
1112 }
1113 if let Some(label) = &other.on_click_label {
1114 self.on_click_label = Some(label.clone());
1115 }
1116 if let Some(role) = other.role {
1117 self.role = Some(role);
1118 }
1119 if let Some(selected) = other.selected {
1120 self.selected = Some(selected);
1121 }
1122 if let Some(toggled) = other.toggled {
1123 self.toggled = Some(toggled);
1124 }
1125 self.enabled &= other.enabled;
1126 self.is_clickable |= other.is_clickable;
1127 self.is_editable_text |= other.is_editable_text;
1128 if let Some(selection) = other.text_selection {
1129 self.text_selection = Some(selection);
1130 }
1131 self.custom_actions
1132 .extend(other.custom_actions.iter().cloned());
1133 self.canvas_children
1134 .extend(other.canvas_children.iter().cloned());
1135 self.is_modal |= other.is_modal;
1136 if let Some(live_region) = other.live_region {
1137 self.live_region = Some(live_region);
1138 }
1139 if let Some(set_progress) = &other.set_progress {
1140 self.set_progress = Some(set_progress.clone());
1141 }
1142 if let Some(progress) = other.progress {
1143 self.progress = Some(progress);
1144 }
1145 if let Some(range) = other.vertical_scroll {
1146 self.vertical_scroll = Some(range);
1147 }
1148 if let Some(range) = other.horizontal_scroll {
1149 self.horizontal_scroll = Some(range);
1150 }
1151 if let Some(scroll_by) = &other.scroll_by {
1152 self.scroll_by = Some(scroll_by.clone());
1153 }
1154 }
1155
1156 pub fn is_activatable(&self) -> bool {
1159 self.is_clickable || self.on_click_label.is_some()
1160 }
1161}
1162
1163impl fmt::Debug for dyn ModifierNode {
1164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1165 f.debug_struct("ModifierNode").finish_non_exhaustive()
1166 }
1167}
1168
1169impl dyn ModifierNode {
1170 pub fn as_any(&self) -> &dyn Any {
1171 self
1172 }
1173
1174 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1175 self
1176 }
1177}
1178
1179pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1182 type Node: ModifierNode;
1183
1184 fn create(&self) -> Self::Node;
1186
1187 fn update(&self, node: &mut Self::Node);
1189
1190 fn key(&self) -> Option<u64> {
1192 None
1193 }
1194
1195 fn inspector_name(&self) -> &'static str {
1197 type_name::<Self>()
1198 }
1199
1200 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1202
1203 fn capabilities(&self) -> NodeCapabilities {
1206 NodeCapabilities::default()
1207 }
1208
1209 fn always_update(&self) -> bool {
1215 false
1216 }
1217
1218 fn auto_invalidate_on_update(&self) -> bool {
1221 true
1222 }
1223
1224 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1231 None
1232 }
1233}
1234
1235#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1237pub struct NodeCapabilities(u32);
1238
1239impl NodeCapabilities {
1240 pub const NONE: Self = Self(0);
1242 pub const LAYOUT: Self = Self(1 << 0);
1244 pub const DRAW: Self = Self(1 << 1);
1246 pub const POINTER_INPUT: Self = Self(1 << 2);
1248 pub const SEMANTICS: Self = Self(1 << 3);
1250 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1252 pub const FOCUS: Self = Self(1 << 5);
1254
1255 pub const fn empty() -> Self {
1257 Self::NONE
1258 }
1259
1260 pub const fn contains(self, other: Self) -> bool {
1262 (self.0 & other.0) == other.0
1263 }
1264
1265 pub const fn intersects(self, other: Self) -> bool {
1267 (self.0 & other.0) != 0
1268 }
1269
1270 pub fn insert(&mut self, other: Self) {
1272 self.0 |= other.0;
1273 }
1274
1275 pub const fn bits(self) -> u32 {
1277 self.0
1278 }
1279
1280 pub const fn is_empty(self) -> bool {
1282 self.0 == 0
1283 }
1284
1285 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1287 match kind {
1288 InvalidationKind::Layout => Self::LAYOUT,
1289 InvalidationKind::Draw => Self::DRAW,
1290 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1291 InvalidationKind::Semantics => Self::SEMANTICS,
1292 InvalidationKind::Focus => Self::FOCUS,
1293 }
1294 }
1295}
1296
1297impl Default for NodeCapabilities {
1298 fn default() -> Self {
1299 Self::NONE
1300 }
1301}
1302
1303impl fmt::Debug for NodeCapabilities {
1304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1305 f.debug_struct("NodeCapabilities")
1306 .field("layout", &self.contains(Self::LAYOUT))
1307 .field("draw", &self.contains(Self::DRAW))
1308 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1309 .field("semantics", &self.contains(Self::SEMANTICS))
1310 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1311 .field("focus", &self.contains(Self::FOCUS))
1312 .finish()
1313 }
1314}
1315
1316impl BitOr for NodeCapabilities {
1317 type Output = Self;
1318
1319 fn bitor(self, rhs: Self) -> Self::Output {
1320 Self(self.0 | rhs.0)
1321 }
1322}
1323
1324impl BitOrAssign for NodeCapabilities {
1325 fn bitor_assign(&mut self, rhs: Self) {
1326 self.0 |= rhs.0;
1327 }
1328}
1329
1330#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1332pub struct ModifierInvalidation {
1333 kind: InvalidationKind,
1334 capabilities: NodeCapabilities,
1335}
1336
1337impl ModifierInvalidation {
1338 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
1340 Self { kind, capabilities }
1341 }
1342
1343 pub const fn kind(self) -> InvalidationKind {
1345 self.kind
1346 }
1347
1348 pub const fn capabilities(self) -> NodeCapabilities {
1350 self.capabilities
1351 }
1352}
1353
1354pub trait AnyModifierElement: fmt::Debug {
1356 fn node_type(&self) -> TypeId;
1357
1358 fn element_type(&self) -> TypeId;
1359
1360 fn create_node(&self) -> Box<dyn ModifierNode>;
1361
1362 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
1363
1364 fn update_node(&self, node: &mut dyn ModifierNode);
1365
1366 fn key(&self) -> Option<u64>;
1367
1368 fn capabilities(&self) -> NodeCapabilities {
1369 NodeCapabilities::default()
1370 }
1371
1372 fn hash_code(&self) -> u64;
1373
1374 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
1375
1376 fn inspector_name(&self) -> &'static str;
1377
1378 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
1379
1380 fn requires_update(&self) -> bool;
1381
1382 fn auto_invalidates_on_update(&self) -> bool;
1383
1384 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
1385
1386 fn as_any(&self) -> &dyn Any;
1387}
1388
1389struct TypedModifierElement<E: ModifierNodeElement> {
1390 element: E,
1391 cached_hash: u64,
1392}
1393
1394impl<E: ModifierNodeElement> TypedModifierElement<E> {
1395 fn new(element: E) -> Self {
1396 let mut hasher = default::new();
1397 element.hash(&mut hasher);
1398 Self {
1399 element,
1400 cached_hash: hasher.finish(),
1401 }
1402 }
1403}
1404
1405impl<E> fmt::Debug for TypedModifierElement<E>
1406where
1407 E: ModifierNodeElement,
1408{
1409 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1410 f.debug_struct("TypedModifierElement")
1411 .field("type", &type_name::<E>())
1412 .finish()
1413 }
1414}
1415
1416impl<E> AnyModifierElement for TypedModifierElement<E>
1417where
1418 E: ModifierNodeElement,
1419{
1420 fn node_type(&self) -> TypeId {
1421 TypeId::of::<E::Node>()
1422 }
1423
1424 fn element_type(&self) -> TypeId {
1425 TypeId::of::<E>()
1426 }
1427
1428 fn create_node(&self) -> Box<dyn ModifierNode> {
1429 Box::new(self.element.create())
1430 }
1431
1432 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
1433 node.as_any().is::<E::Node>()
1434 }
1435
1436 fn update_node(&self, node: &mut dyn ModifierNode) {
1437 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
1438 self.element.update(typed);
1439 }
1440 }
1441
1442 fn key(&self) -> Option<u64> {
1443 self.element.key()
1444 }
1445
1446 fn capabilities(&self) -> NodeCapabilities {
1447 self.element.capabilities()
1448 }
1449
1450 fn hash_code(&self) -> u64 {
1451 self.cached_hash
1452 }
1453
1454 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
1455 other
1456 .as_any()
1457 .downcast_ref::<Self>()
1458 .map(|typed| typed.element == self.element)
1459 .unwrap_or(false)
1460 }
1461
1462 fn inspector_name(&self) -> &'static str {
1463 self.element.inspector_name()
1464 }
1465
1466 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
1467 self.element.inspector_properties(visitor);
1468 }
1469
1470 fn requires_update(&self) -> bool {
1471 self.element.always_update()
1472 }
1473
1474 fn auto_invalidates_on_update(&self) -> bool {
1475 self.element.auto_invalidate_on_update()
1476 }
1477
1478 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1479 self.element.update_invalidation_kind()
1480 }
1481
1482 fn as_any(&self) -> &dyn Any {
1483 self
1484 }
1485}
1486
1487fn request_update_auto_invalidations(
1488 element: &dyn AnyModifierElement,
1489 context: &mut dyn ModifierNodeContext,
1490 capabilities: NodeCapabilities,
1491) {
1492 if let Some(kind) = element.update_invalidation_kind() {
1493 let capabilities = NodeCapabilities::for_invalidation(kind);
1494 context.push_active_capabilities(capabilities);
1495 context.invalidate(kind);
1496 context.pop_active_capabilities();
1497 } else if element.auto_invalidates_on_update() {
1498 request_auto_invalidations(context, capabilities);
1499 }
1500}
1501
1502pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
1505 Rc::new(TypedModifierElement::new(element))
1506}
1507
1508pub type DynModifierElement = Rc<dyn AnyModifierElement>;
1510
1511#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1512enum TraversalDirection {
1513 Forward,
1514 Backward,
1515}
1516
1517pub struct ModifierChainIter<'a> {
1522 chain: &'a ModifierNodeChain,
1523 cursor: usize,
1524 remaining: usize,
1525 direction: TraversalDirection,
1526}
1527
1528impl<'a> ModifierChainIter<'a> {
1529 fn forward(chain: &'a ModifierNodeChain) -> Self {
1530 Self {
1531 chain,
1532 cursor: 0,
1533 remaining: chain.ordered_nodes.len(),
1534 direction: TraversalDirection::Forward,
1535 }
1536 }
1537
1538 fn backward(chain: &'a ModifierNodeChain) -> Self {
1539 let len = chain.ordered_nodes.len();
1540 Self {
1541 chain,
1542 cursor: len.wrapping_sub(1),
1543 remaining: len,
1544 direction: TraversalDirection::Backward,
1545 }
1546 }
1547}
1548
1549impl<'a> Iterator for ModifierChainIter<'a> {
1550 type Item = ModifierChainNodeRef<'a>;
1551
1552 #[inline]
1553 fn next(&mut self) -> Option<Self::Item> {
1554 if self.remaining == 0 {
1555 return None;
1556 }
1557 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
1558 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
1559 self.remaining -= 1;
1560 match self.direction {
1561 TraversalDirection::Forward => self.cursor += 1,
1562 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
1563 }
1564 Some(node_ref)
1565 }
1566
1567 #[inline]
1568 fn size_hint(&self) -> (usize, Option<usize>) {
1569 (self.remaining, Some(self.remaining))
1570 }
1571}
1572
1573impl<'a> ExactSizeIterator for ModifierChainIter<'a> {}
1574impl<'a> std::iter::FusedIterator for ModifierChainIter<'a> {}
1575
1576#[derive(Debug)]
1577struct ModifierNodeEntry {
1578 element_type: TypeId,
1579 node_type: TypeId,
1580 key: Option<u64>,
1581 hash_code: u64,
1582 element: DynModifierElement,
1583 node: Rc<RefCell<Box<dyn ModifierNode>>>,
1584 capabilities: NodeCapabilities,
1585}
1586
1587impl ModifierNodeEntry {
1588 fn new(
1589 element_type: TypeId,
1590 node_type: TypeId,
1591 key: Option<u64>,
1592 element: DynModifierElement,
1593 node: Box<dyn ModifierNode>,
1594 hash_code: u64,
1595 capabilities: NodeCapabilities,
1596 ) -> Self {
1597 let node_rc = Rc::new(RefCell::new(node));
1598 let entry = Self {
1599 element_type,
1600 node_type,
1601 key,
1602 hash_code,
1603 element,
1604 node: Rc::clone(&node_rc),
1605 capabilities,
1606 };
1607 entry
1608 .node
1609 .borrow()
1610 .node_state()
1611 .set_capabilities(entry.capabilities);
1612 entry
1613 }
1614}
1615
1616fn visit_node_tree_mut(
1617 node: &mut dyn ModifierNode,
1618 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
1619) {
1620 visitor(node);
1621 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
1622}
1623
1624fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
1625 let mut current = 0usize;
1626 let mut result: Option<&dyn ModifierNode> = None;
1627 node.for_each_delegate(&mut |child| {
1628 if result.is_none() && current == target {
1629 result = Some(child);
1630 }
1631 current += 1;
1632 });
1633 result
1634}
1635
1636fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
1637 let mut current = 0usize;
1638 let mut result: Option<&mut dyn ModifierNode> = None;
1639 node.for_each_delegate_mut(&mut |child| {
1640 if result.is_none() && current == target {
1641 result = Some(child);
1642 }
1643 current += 1;
1644 });
1645 result
1646}
1647
1648fn with_node_context<F, R>(
1649 node: &mut dyn ModifierNode,
1650 context: &mut dyn ModifierNodeContext,
1651 f: F,
1652) -> R
1653where
1654 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
1655{
1656 context.push_active_capabilities(node.node_state().capabilities());
1657 let result = f(node, context);
1658 context.pop_active_capabilities();
1659 result
1660}
1661
1662fn request_auto_invalidations(
1663 context: &mut dyn ModifierNodeContext,
1664 capabilities: NodeCapabilities,
1665) {
1666 if capabilities.is_empty() {
1667 return;
1668 }
1669
1670 context.push_active_capabilities(capabilities);
1671
1672 if capabilities.contains(NodeCapabilities::LAYOUT) {
1673 context.invalidate(InvalidationKind::Layout);
1674 }
1675 if capabilities.contains(NodeCapabilities::DRAW) {
1676 context.invalidate(InvalidationKind::Draw);
1677 }
1678 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
1679 context.invalidate(InvalidationKind::PointerInput);
1680 }
1681 if capabilities.contains(NodeCapabilities::SEMANTICS) {
1682 context.invalidate(InvalidationKind::Semantics);
1683 }
1684 if capabilities.contains(NodeCapabilities::FOCUS) {
1685 context.invalidate(InvalidationKind::Focus);
1686 }
1687
1688 context.pop_active_capabilities();
1689}
1690
1691fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
1699 visit_node_tree_mut(node, &mut |n| {
1700 if !n.node_state().is_attached() {
1701 n.node_state().set_attached(true);
1702 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
1703 }
1704 });
1705}
1706
1707fn reset_node_tree(node: &mut dyn ModifierNode) {
1708 visit_node_tree_mut(node, &mut |n| n.on_reset());
1709}
1710
1711fn detach_node_tree(node: &mut dyn ModifierNode) {
1712 visit_node_tree_mut(node, &mut |n| {
1713 if n.node_state().is_attached() {
1714 n.on_detach();
1715 n.node_state().set_attached(false);
1716 }
1717 n.node_state().set_parent_link(None);
1718 n.node_state().set_child_link(None);
1719 n.node_state()
1720 .set_aggregate_child_capabilities(NodeCapabilities::empty());
1721 });
1722}
1723
1724pub struct ModifierNodeChain {
1731 entries: Vec<ModifierNodeEntry>,
1732 aggregated_capabilities: NodeCapabilities,
1733 head_aggregate_child_capabilities: NodeCapabilities,
1734 head_sentinel: Box<SentinelNode>,
1735 tail_sentinel: Box<SentinelNode>,
1736 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
1737 scratch_old_used: Vec<bool>,
1738 scratch_match_order: Vec<Option<usize>>,
1739 scratch_final_slots: Vec<Option<ModifierNodeEntry>>,
1740 scratch_elements: Vec<DynModifierElement>,
1741}
1742
1743struct SentinelNode {
1744 state: NodeState,
1745}
1746
1747impl SentinelNode {
1748 fn new() -> Self {
1749 Self {
1750 state: NodeState::sentinel(),
1751 }
1752 }
1753}
1754
1755impl DelegatableNode for SentinelNode {
1756 fn node_state(&self) -> &NodeState {
1757 &self.state
1758 }
1759}
1760
1761impl ModifierNode for SentinelNode {}
1762
1763#[derive(Clone)]
1764pub struct ModifierChainNodeRef<'a> {
1765 chain: &'a ModifierNodeChain,
1766 link: NodeLink,
1767 cached_capabilities: Option<NodeCapabilities>,
1768 cached_aggregate_child: Option<NodeCapabilities>,
1769}
1770
1771impl Default for ModifierNodeChain {
1772 fn default() -> Self {
1773 Self::new()
1774 }
1775}
1776
1777struct EntryIndex {
1782 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
1783 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
1784 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
1785}
1786
1787struct EntryMatchQuery<'a> {
1788 element_type: TypeId,
1789 node_type: TypeId,
1790 key: Option<u64>,
1791 hash_code: u64,
1792 element: &'a DynModifierElement,
1793}
1794
1795impl EntryIndex {
1796 fn build(entries: &[ModifierNodeEntry]) -> Self {
1797 let mut keyed = HashMap::default();
1798 let mut hashed = HashMap::default();
1799 let mut typed = HashMap::default();
1800
1801 for (i, entry) in entries.iter().enumerate() {
1802 if let Some(key_value) = entry.key {
1803 keyed
1804 .entry((entry.element_type, entry.node_type, key_value))
1805 .or_insert_with(Vec::new)
1806 .push(i);
1807 } else {
1808 hashed
1809 .entry((entry.element_type, entry.node_type, entry.hash_code))
1810 .or_insert_with(Vec::new)
1811 .push(i);
1812 typed
1813 .entry((entry.element_type, entry.node_type))
1814 .or_insert_with(Vec::new)
1815 .push(i);
1816 }
1817 }
1818
1819 Self {
1820 keyed,
1821 hashed,
1822 typed,
1823 }
1824 }
1825
1826 fn find_match(
1827 &self,
1828 entries: &[ModifierNodeEntry],
1829 used: &[bool],
1830 query: EntryMatchQuery<'_>,
1831 ) -> Option<usize> {
1832 if let Some(key_value) = query.key {
1833 if let Some(candidates) =
1834 self.keyed
1835 .get(&(query.element_type, query.node_type, key_value))
1836 {
1837 for &i in candidates {
1838 if !used[i] {
1839 return Some(i);
1840 }
1841 }
1842 }
1843 } else {
1844 if let Some(candidates) =
1845 self.hashed
1846 .get(&(query.element_type, query.node_type, query.hash_code))
1847 {
1848 for &i in candidates {
1849 if !used[i]
1850 && entries[i]
1851 .element
1852 .as_ref()
1853 .equals_element(query.element.as_ref())
1854 {
1855 return Some(i);
1856 }
1857 }
1858 }
1859
1860 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
1861 for &i in candidates {
1862 if !used[i] {
1863 return Some(i);
1864 }
1865 }
1866 }
1867 }
1868
1869 None
1870 }
1871}
1872
1873impl ModifierNodeChain {
1874 pub fn new() -> Self {
1875 let mut chain = Self {
1876 entries: Vec::new(),
1877 aggregated_capabilities: NodeCapabilities::empty(),
1878 head_aggregate_child_capabilities: NodeCapabilities::empty(),
1879 head_sentinel: Box::new(SentinelNode::new()),
1880 tail_sentinel: Box::new(SentinelNode::new()),
1881 ordered_nodes: Vec::new(),
1882 scratch_old_used: Vec::new(),
1883 scratch_match_order: Vec::new(),
1884 scratch_final_slots: Vec::new(),
1885 scratch_elements: Vec::new(),
1886 };
1887 chain.sync_chain_links();
1888 chain
1889 }
1890
1891 pub fn detach_nodes(&mut self) {
1893 for entry in &self.entries {
1894 detach_node_tree(&mut **entry.node.borrow_mut());
1895 }
1896 }
1897
1898 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
1900 for entry in &self.entries {
1901 attach_node_tree(&mut **entry.node.borrow_mut(), context);
1902 }
1903 }
1904
1905 pub fn repair_chain(&mut self) {
1908 self.sync_chain_links();
1909 }
1910
1911 pub fn update_from_slice(
1917 &mut self,
1918 elements: &[DynModifierElement],
1919 context: &mut dyn ModifierNodeContext,
1920 ) {
1921 self.update_from_ref_iter(elements.iter(), context);
1922 }
1923
1924 pub fn update_from_ref_iter<'a, I>(
1929 &mut self,
1930 elements: I,
1931 context: &mut dyn ModifierNodeContext,
1932 ) where
1933 I: Iterator<Item = &'a DynModifierElement>,
1934 {
1935 let old_len = self.entries.len();
1936 let mut fast_path_failed_at: Option<usize> = None;
1937 let mut elements_count = 0;
1938
1939 self.scratch_elements.clear();
1940
1941 for (idx, element) in elements.enumerate() {
1942 elements_count = idx + 1;
1943
1944 if fast_path_failed_at.is_none() && idx < old_len {
1945 let entry = &mut self.entries[idx];
1946 let same_type = entry.element_type == element.element_type();
1947 let same_node_type = entry.node_type == element.node_type();
1948 let same_key = entry.key == element.key();
1949 let same_hash = entry.hash_code == element.hash_code();
1950
1951 let positional_update = element.requires_update();
1952 if same_type && same_node_type && same_key && (same_hash || positional_update) {
1953 let can_update_node = {
1954 let node_borrow = entry.node.borrow();
1955 element.can_update_node(&**node_borrow)
1956 };
1957 if !can_update_node {
1958 fast_path_failed_at = Some(idx);
1959 self.scratch_elements.push(element.clone());
1960 continue;
1961 }
1962
1963 let same_element = entry.element.as_ref().equals_element(element.as_ref());
1964 let capabilities = element.capabilities();
1965
1966 {
1967 let node_borrow = entry.node.borrow();
1968 if !node_borrow.node_state().is_attached() {
1969 drop(node_borrow);
1970 attach_node_tree(&mut **entry.node.borrow_mut(), context);
1971 }
1972 }
1973
1974 let needs_update = !same_element || element.requires_update();
1975 if needs_update {
1976 element.update_node(&mut **entry.node.borrow_mut());
1977 entry.element = element.clone();
1978 entry.hash_code = element.hash_code();
1979 request_update_auto_invalidations(element.as_ref(), context, capabilities);
1980 }
1981
1982 entry.capabilities = capabilities;
1983 entry
1984 .node
1985 .borrow()
1986 .node_state()
1987 .set_capabilities(capabilities);
1988 continue;
1989 }
1990 fast_path_failed_at = Some(idx);
1991 }
1992
1993 self.scratch_elements.push(element.clone());
1994 }
1995
1996 if fast_path_failed_at.is_none() && self.scratch_elements.is_empty() {
1997 if elements_count < self.entries.len() {
1998 for entry in self.entries.drain(elements_count..) {
1999 request_auto_invalidations(context, entry.capabilities);
2000 detach_node_tree(&mut **entry.node.borrow_mut());
2001 }
2002 }
2003 self.sync_chain_links();
2004 return;
2005 }
2006
2007 let fail_idx = fast_path_failed_at.unwrap_or(old_len);
2008
2009 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2010 let processed_entries_len = self.entries.len();
2011 let old_len = old_entries.len();
2012
2013 self.scratch_old_used.clear();
2014 self.scratch_old_used.resize(old_len, false);
2015
2016 self.scratch_match_order.clear();
2017 self.scratch_match_order.resize(old_len, None);
2018
2019 let index = EntryIndex::build(&old_entries);
2020
2021 let new_elements_count = self.scratch_elements.len();
2022 self.scratch_final_slots.clear();
2023 self.scratch_final_slots.reserve(new_elements_count);
2024
2025 for (new_pos, element) in self.scratch_elements.drain(..).enumerate() {
2026 self.scratch_final_slots.push(None);
2027 let element_type = element.element_type();
2028 let node_type = element.node_type();
2029 let key = element.key();
2030 let hash_code = element.hash_code();
2031 let capabilities = element.capabilities();
2032
2033 let matched_idx = index.find_match(
2034 &old_entries,
2035 &self.scratch_old_used,
2036 EntryMatchQuery {
2037 element_type,
2038 node_type,
2039 key,
2040 hash_code,
2041 element: &element,
2042 },
2043 );
2044
2045 if let Some(idx) = matched_idx {
2046 let entry = &mut old_entries[idx];
2047 let can_update_node = {
2048 let node_borrow = entry.node.borrow();
2049 element.can_update_node(&**node_borrow)
2050 };
2051 if !can_update_node {
2052 let replacement = ModifierNodeEntry::new(
2053 element_type,
2054 node_type,
2055 key,
2056 element.clone(),
2057 element.create_node(),
2058 hash_code,
2059 capabilities,
2060 );
2061 attach_node_tree(&mut **replacement.node.borrow_mut(), context);
2062 element.update_node(&mut **replacement.node.borrow_mut());
2063 request_auto_invalidations(context, capabilities);
2064 self.scratch_final_slots[new_pos] = Some(replacement);
2065 continue;
2066 }
2067
2068 self.scratch_old_used[idx] = true;
2069 self.scratch_match_order[idx] = Some(new_pos);
2070 let moved = idx != new_pos;
2071
2072 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2073
2074 {
2075 let node_borrow = entry.node.borrow();
2076 if !node_borrow.node_state().is_attached() {
2077 drop(node_borrow);
2078 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2079 }
2080 }
2081
2082 let needs_update = !same_element || element.requires_update();
2083 if needs_update {
2084 element.update_node(&mut **entry.node.borrow_mut());
2085 entry.element = element;
2086 entry.hash_code = hash_code;
2087 request_update_auto_invalidations(
2088 entry.element.as_ref(),
2089 context,
2090 capabilities,
2091 );
2092 }
2093 if moved {
2094 request_auto_invalidations(context, capabilities);
2095 }
2096
2097 entry.key = key;
2098 entry.element_type = element_type;
2099 entry.node_type = node_type;
2100 entry.capabilities = capabilities;
2101 entry
2102 .node
2103 .borrow()
2104 .node_state()
2105 .set_capabilities(capabilities);
2106 } else {
2107 let entry = ModifierNodeEntry::new(
2108 element_type,
2109 node_type,
2110 key,
2111 element.clone(),
2112 element.create_node(),
2113 hash_code,
2114 capabilities,
2115 );
2116 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2117 element.update_node(&mut **entry.node.borrow_mut());
2118 request_auto_invalidations(context, capabilities);
2119 self.scratch_final_slots[new_pos] = Some(entry);
2120 }
2121 }
2122
2123 for (i, entry) in old_entries.into_iter().enumerate() {
2124 if self.scratch_old_used[i] {
2125 if let Some(pos) = self.scratch_match_order[i] {
2126 self.scratch_final_slots[pos] = Some(entry);
2127 } else {
2128 request_auto_invalidations(context, entry.capabilities);
2129 detach_node_tree(&mut **entry.node.borrow_mut());
2130 }
2131 } else {
2132 request_auto_invalidations(context, entry.capabilities);
2133 detach_node_tree(&mut **entry.node.borrow_mut());
2134 }
2135 }
2136
2137 self.entries.reserve(self.scratch_final_slots.len());
2138 for slot in self.scratch_final_slots.drain(..) {
2139 if let Some(entry) = slot {
2140 self.entries.push(entry);
2141 } else {
2142 log::error!("modifier reconciliation produced an empty final slot");
2143 }
2144 }
2145
2146 debug_assert_eq!(
2147 self.entries.len(),
2148 processed_entries_len + new_elements_count
2149 );
2150 self.sync_chain_links();
2151 }
2152
2153 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2157 where
2158 I: IntoIterator<Item = DynModifierElement>,
2159 {
2160 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2161 self.update_from_slice(&collected, context);
2162 }
2163
2164 pub fn reset(&mut self) {
2167 for entry in &mut self.entries {
2168 reset_node_tree(&mut **entry.node.borrow_mut());
2169 }
2170 }
2171
2172 pub fn detach_all(&mut self) {
2174 for entry in std::mem::take(&mut self.entries) {
2175 detach_node_tree(&mut **entry.node.borrow_mut());
2176 {
2177 let node_borrow = entry.node.borrow();
2178 let state = node_borrow.node_state();
2179 state.set_capabilities(NodeCapabilities::empty());
2180 }
2181 }
2182 self.aggregated_capabilities = NodeCapabilities::empty();
2183 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2184 self.ordered_nodes.clear();
2185 self.sync_chain_links();
2186 }
2187
2188 pub fn len(&self) -> usize {
2189 self.entries.len()
2190 }
2191
2192 pub fn is_empty(&self) -> bool {
2193 self.entries.is_empty()
2194 }
2195
2196 pub fn capabilities(&self) -> NodeCapabilities {
2198 self.aggregated_capabilities
2199 }
2200
2201 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2203 self.aggregated_capabilities.contains(capability)
2204 }
2205
2206 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2208 self.make_node_ref(NodeLink::Head)
2209 }
2210
2211 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2213 self.make_node_ref(NodeLink::Tail)
2214 }
2215
2216 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2218 ModifierChainIter::forward(self)
2219 }
2220
2221 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2223 ModifierChainIter::backward(self)
2224 }
2225
2226 pub fn for_each_forward<F>(&self, mut f: F)
2228 where
2229 F: FnMut(ModifierChainNodeRef<'_>),
2230 {
2231 for node in self.head_to_tail() {
2232 f(node);
2233 }
2234 }
2235
2236 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2238 where
2239 F: FnMut(ModifierChainNodeRef<'_>),
2240 {
2241 if mask.is_empty() {
2242 self.for_each_forward(f);
2243 return;
2244 }
2245
2246 if !self.head().aggregate_child_capabilities().intersects(mask) {
2247 return;
2248 }
2249
2250 for node in self.head_to_tail() {
2251 if node.kind_set().intersects(mask) {
2252 f(node);
2253 }
2254 }
2255 }
2256
2257 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2259 where
2260 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2261 {
2262 self.for_each_forward_matching(mask, |node_ref| {
2263 node_ref.with_node(|node| f(node_ref.clone(), node));
2264 });
2265 }
2266
2267 pub fn for_each_backward<F>(&self, mut f: F)
2269 where
2270 F: FnMut(ModifierChainNodeRef<'_>),
2271 {
2272 for node in self.tail_to_head() {
2273 f(node);
2274 }
2275 }
2276
2277 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2279 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2280 node as *const dyn ModifierNode as *const ()
2281 }
2282
2283 let target = node_data_ptr(node);
2284 for (index, entry) in self.entries.iter().enumerate() {
2285 if node_data_ptr(&**entry.node.borrow()) == target {
2286 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2287 }
2288 }
2289
2290 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2291 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2292 return None;
2293 }
2294 let matches_target = match link {
2295 NodeLink::Head => node_data_ptr(self.head_sentinel.as_ref()) == target,
2296 NodeLink::Tail => node_data_ptr(self.tail_sentinel.as_ref()) == target,
2297 NodeLink::Entry(path) => {
2298 let node_borrow = self.entries[path.entry()].node.borrow();
2299 node_data_ptr(&**node_borrow) == target
2300 }
2301 };
2302 if matches_target {
2303 Some(self.make_node_ref(*link))
2304 } else {
2305 None
2306 }
2307 })
2308 }
2309
2310 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
2313 self.entries.get(index).and_then(|entry| {
2314 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
2315 boxed_node.as_any().downcast_ref::<N>()
2316 })
2317 .ok()
2318 })
2319 }
2320
2321 pub fn node_mut<N: ModifierNode + 'static>(
2324 &self,
2325 index: usize,
2326 ) -> Option<std::cell::RefMut<'_, N>> {
2327 self.entries.get(index).and_then(|entry| {
2328 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
2329 boxed_node.as_any_mut().downcast_mut::<N>()
2330 })
2331 .ok()
2332 })
2333 }
2334
2335 pub fn get_node_rc(&self, index: usize) -> Option<Rc<RefCell<Box<dyn ModifierNode>>>> {
2338 self.entries.get(index).map(|entry| Rc::clone(&entry.node))
2339 }
2340
2341 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
2343 self.aggregated_capabilities
2344 .contains(NodeCapabilities::for_invalidation(kind))
2345 }
2346
2347 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
2349 where
2350 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
2351 {
2352 for index in 0..self.ordered_nodes.len() {
2353 let (link, cached_caps, _agg) = self.ordered_nodes[index];
2354 match link {
2355 NodeLink::Head => {
2356 f(self.head_sentinel.as_mut(), cached_caps);
2357 }
2358 NodeLink::Tail => {
2359 f(self.tail_sentinel.as_mut(), cached_caps);
2360 }
2361 NodeLink::Entry(path) => {
2362 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
2363 if path.delegates().is_empty() {
2364 f(&mut **node_borrow, cached_caps);
2365 } else {
2366 let mut current: &mut dyn ModifierNode = &mut **node_borrow;
2367 for &delegate_index in path.delegates() {
2368 if let Some(delegate) =
2369 nth_delegate_mut(current, delegate_index as usize)
2370 {
2371 current = delegate;
2372 } else {
2373 return;
2374 }
2375 }
2376 f(current, cached_caps);
2377 }
2378 }
2379 }
2380 }
2381 }
2382
2383 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
2384 ModifierChainNodeRef {
2385 chain: self,
2386 link,
2387 cached_capabilities: None,
2388 cached_aggregate_child: None,
2389 }
2390 }
2391
2392 fn make_node_ref_with_caps(
2393 &self,
2394 link: NodeLink,
2395 caps: NodeCapabilities,
2396 aggregate_child: NodeCapabilities,
2397 ) -> ModifierChainNodeRef<'_> {
2398 ModifierChainNodeRef {
2399 chain: self,
2400 link,
2401 cached_capabilities: Some(caps),
2402 cached_aggregate_child: Some(aggregate_child),
2403 }
2404 }
2405
2406 fn sync_chain_links(&mut self) {
2407 self.rebuild_ordered_nodes();
2408
2409 self.head_sentinel.node_state().set_parent_link(None);
2410 self.tail_sentinel.node_state().set_child_link(None);
2411
2412 if self.ordered_nodes.is_empty() {
2413 self.head_sentinel
2414 .node_state()
2415 .set_child_link(Some(NodeLink::Tail));
2416 self.tail_sentinel
2417 .node_state()
2418 .set_parent_link(Some(NodeLink::Head));
2419 self.aggregated_capabilities = NodeCapabilities::empty();
2420 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2421 self.head_sentinel
2422 .node_state()
2423 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2424 self.tail_sentinel
2425 .node_state()
2426 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2427 return;
2428 }
2429
2430 let mut previous = NodeLink::Head;
2431 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
2432 match &previous {
2433 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
2434 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
2435 NodeLink::Entry(path) => {
2436 let node_borrow = self.entries[path.entry()].node.borrow();
2437 if path.delegates().is_empty() {
2438 node_borrow.node_state().set_child_link(Some(link));
2439 } else {
2440 let mut current: &dyn ModifierNode = &**node_borrow;
2441 for &delegate_index in path.delegates() {
2442 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2443 current = delegate;
2444 }
2445 }
2446 current.node_state().set_child_link(Some(link));
2447 }
2448 }
2449 }
2450 match &link {
2451 NodeLink::Head => self
2452 .head_sentinel
2453 .node_state()
2454 .set_parent_link(Some(previous)),
2455 NodeLink::Tail => self
2456 .tail_sentinel
2457 .node_state()
2458 .set_parent_link(Some(previous)),
2459 NodeLink::Entry(path) => {
2460 let node_borrow = self.entries[path.entry()].node.borrow();
2461 if path.delegates().is_empty() {
2462 node_borrow.node_state().set_parent_link(Some(previous));
2463 } else {
2464 let mut current: &dyn ModifierNode = &**node_borrow;
2465 for &delegate_index in path.delegates() {
2466 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2467 current = delegate;
2468 }
2469 }
2470 current.node_state().set_parent_link(Some(previous));
2471 }
2472 }
2473 }
2474 previous = link;
2475 }
2476
2477 match &previous {
2478 NodeLink::Head => self
2479 .head_sentinel
2480 .node_state()
2481 .set_child_link(Some(NodeLink::Tail)),
2482 NodeLink::Tail => self
2483 .tail_sentinel
2484 .node_state()
2485 .set_child_link(Some(NodeLink::Tail)),
2486 NodeLink::Entry(path) => {
2487 let node_borrow = self.entries[path.entry()].node.borrow();
2488 if path.delegates().is_empty() {
2489 node_borrow
2490 .node_state()
2491 .set_child_link(Some(NodeLink::Tail));
2492 } else {
2493 let mut current: &dyn ModifierNode = &**node_borrow;
2494 for &delegate_index in path.delegates() {
2495 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2496 current = delegate;
2497 }
2498 }
2499 current.node_state().set_child_link(Some(NodeLink::Tail));
2500 }
2501 }
2502 }
2503 self.tail_sentinel
2504 .node_state()
2505 .set_parent_link(Some(previous));
2506 self.tail_sentinel.node_state().set_child_link(None);
2507
2508 let mut aggregate = NodeCapabilities::empty();
2509 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
2510 aggregate |= *cached_caps;
2511 *cached_aggregate = aggregate;
2512 match link {
2513 NodeLink::Head => {
2514 self.head_sentinel
2515 .node_state()
2516 .set_aggregate_child_capabilities(aggregate);
2517 }
2518 NodeLink::Tail => {
2519 self.tail_sentinel
2520 .node_state()
2521 .set_aggregate_child_capabilities(aggregate);
2522 }
2523 NodeLink::Entry(path) => {
2524 let node_borrow = self.entries[path.entry()].node.borrow();
2525 let state = if path.delegates().is_empty() {
2526 node_borrow.node_state()
2527 } else {
2528 let mut current: &dyn ModifierNode = &**node_borrow;
2529 for &delegate_index in path.delegates() {
2530 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2531 current = delegate;
2532 }
2533 }
2534 current.node_state()
2535 };
2536 state.set_aggregate_child_capabilities(aggregate);
2537 }
2538 }
2539 }
2540
2541 self.aggregated_capabilities = aggregate;
2542 self.head_aggregate_child_capabilities = aggregate;
2543 self.head_sentinel
2544 .node_state()
2545 .set_aggregate_child_capabilities(aggregate);
2546 self.tail_sentinel
2547 .node_state()
2548 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2549 }
2550
2551 fn rebuild_ordered_nodes(&mut self) {
2552 self.ordered_nodes.clear();
2553 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
2554 for (index, entry) in self.entries.iter().enumerate() {
2555 let node_borrow = entry.node.borrow();
2556 Self::enumerate_link_order(
2557 &**node_borrow,
2558 index,
2559 &mut path_buf,
2560 0,
2561 &mut self.ordered_nodes,
2562 );
2563 }
2564 }
2565
2566 fn enumerate_link_order(
2567 node: &dyn ModifierNode,
2568 entry: usize,
2569 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
2570 path_len: usize,
2571 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2572 ) {
2573 let caps = node.node_state().capabilities();
2574 out.push((
2575 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
2576 caps,
2577 NodeCapabilities::empty(),
2578 ));
2579 let mut delegate_index = 0usize;
2580 node.for_each_delegate(&mut |child| {
2581 if path_len < MAX_DELEGATE_DEPTH {
2582 path_buf[path_len] = delegate_index;
2583 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
2584 }
2585 delegate_index += 1;
2586 });
2587 }
2588}
2589
2590impl<'a> ModifierChainNodeRef<'a> {
2591 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
2592 match &self.link {
2593 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
2594 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
2595 NodeLink::Entry(path) => {
2596 let node_borrow = self.chain.entries[path.entry()].node.borrow();
2597 if path.delegates().is_empty() {
2598 f(node_borrow.node_state())
2599 } else {
2600 let mut current: &dyn ModifierNode = &**node_borrow;
2601 for &delegate_index in path.delegates() {
2602 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2603 current = delegate;
2604 } else {
2605 return f(node_borrow.node_state());
2606 }
2607 }
2608 f(current.node_state())
2609 }
2610 }
2611 }
2612 }
2613
2614 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
2617 match &self.link {
2618 NodeLink::Head => None,
2619 NodeLink::Tail => None,
2620 NodeLink::Entry(path) => {
2621 let node_borrow = self.chain.entries[path.entry()].node.borrow();
2622 if path.delegates().is_empty() {
2623 Some(f(&**node_borrow))
2624 } else {
2625 let mut current: &dyn ModifierNode = &**node_borrow;
2626 for &delegate_index in path.delegates() {
2627 current = nth_delegate(current, delegate_index as usize)?;
2628 }
2629 Some(f(current))
2630 }
2631 }
2632 }
2633 }
2634
2635 #[inline]
2637 pub fn parent(&self) -> Option<Self> {
2638 self.with_state(|state| state.parent_link())
2639 .map(|link| self.chain.make_node_ref(link))
2640 }
2641
2642 #[inline]
2644 pub fn child(&self) -> Option<Self> {
2645 self.with_state(|state| state.child_link())
2646 .map(|link| self.chain.make_node_ref(link))
2647 }
2648
2649 #[inline]
2651 pub fn kind_set(&self) -> NodeCapabilities {
2652 if let Some(caps) = self.cached_capabilities {
2653 return caps;
2654 }
2655 match &self.link {
2656 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
2657 NodeLink::Entry(_) => self.with_state(|state| state.capabilities()),
2658 }
2659 }
2660
2661 pub fn entry_index(&self) -> Option<usize> {
2663 match &self.link {
2664 NodeLink::Entry(path) => Some(path.entry()),
2665 _ => None,
2666 }
2667 }
2668
2669 pub fn delegate_depth(&self) -> usize {
2671 match &self.link {
2672 NodeLink::Entry(path) => path.delegates().len(),
2673 _ => 0,
2674 }
2675 }
2676
2677 #[inline]
2679 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
2680 if let Some(agg) = self.cached_aggregate_child {
2681 return agg;
2682 }
2683 if self.is_tail() {
2684 NodeCapabilities::empty()
2685 } else {
2686 self.with_state(|state| state.aggregate_child_capabilities())
2687 }
2688 }
2689
2690 pub fn is_head(&self) -> bool {
2692 matches!(self.link, NodeLink::Head)
2693 }
2694
2695 pub fn is_tail(&self) -> bool {
2697 matches!(self.link, NodeLink::Tail)
2698 }
2699
2700 pub fn is_sentinel(&self) -> bool {
2702 matches!(self.link, NodeLink::Head | NodeLink::Tail)
2703 }
2704
2705 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
2707 !mask.is_empty() && self.kind_set().intersects(mask)
2708 }
2709
2710 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
2712 where
2713 F: FnMut(ModifierChainNodeRef<'a>),
2714 {
2715 let mut current = if include_self {
2716 Some(self)
2717 } else {
2718 self.child()
2719 };
2720 while let Some(node) = current {
2721 if node.is_tail() {
2722 break;
2723 }
2724 if !node.is_sentinel() {
2725 f(node.clone());
2726 }
2727 current = node.child();
2728 }
2729 }
2730
2731 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
2733 where
2734 F: FnMut(ModifierChainNodeRef<'a>),
2735 {
2736 if mask.is_empty() {
2737 self.visit_descendants(include_self, f);
2738 return;
2739 }
2740
2741 if !self.aggregate_child_capabilities().intersects(mask) {
2742 return;
2743 }
2744
2745 self.visit_descendants(include_self, |node| {
2746 if node.kind_set().intersects(mask) {
2747 f(node);
2748 }
2749 });
2750 }
2751
2752 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
2754 where
2755 F: FnMut(ModifierChainNodeRef<'a>),
2756 {
2757 let mut current = if include_self {
2758 Some(self)
2759 } else {
2760 self.parent()
2761 };
2762 while let Some(node) = current {
2763 if node.is_head() {
2764 break;
2765 }
2766 f(node.clone());
2767 current = node.parent();
2768 }
2769 }
2770
2771 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
2773 where
2774 F: FnMut(ModifierChainNodeRef<'a>),
2775 {
2776 if mask.is_empty() {
2777 self.visit_ancestors(include_self, f);
2778 return;
2779 }
2780
2781 self.visit_ancestors(include_self, |node| {
2782 if node.kind_set().intersects(mask) {
2783 f(node);
2784 }
2785 });
2786 }
2787}
2788
2789#[cfg(test)]
2790#[path = "tests/modifier_tests.rs"]
2791mod tests;