1use crate::{
32 slot_storage::{GroupId, SlotStorage, StartGroup, ValueSlotId},
33 AnchorId, Key, NodeId, Owned, ScopeId,
34};
35use std::any::Any;
36use std::cell::Cell;
37use std::collections::HashMap;
38
39#[derive(Default)]
44pub struct SplitSlotStorage {
45 layout: Vec<LayoutSlot>,
47 payload: HashMap<usize, Box<dyn Any>>,
49 cursor: usize,
51 group_stack: Vec<GroupFrame>,
53 anchors: Vec<usize>,
55 anchors_dirty: bool,
57 next_anchor_id: Cell<usize>,
59 last_start_was_gap: bool,
61}
62
63struct GroupFrame {
64 #[allow(dead_code)] key: Key,
66 start: usize,
67 end: usize,
68 #[allow(dead_code)] force_children_recompose: bool,
70}
71
72enum LayoutSlot {
74 Group {
75 key: Key,
76 anchor: AnchorId,
77 len: usize,
78 scope: Option<ScopeId>,
79 has_gap_children: bool,
80 },
81 ValueRef {
83 anchor: AnchorId,
84 },
85 Node {
86 anchor: AnchorId,
87 id: NodeId,
88 },
89 Gap {
90 anchor: AnchorId,
91 group_key: Option<Key>,
92 group_scope: Option<ScopeId>,
93 group_len: usize,
94 },
95}
96
97impl LayoutSlot {
98 fn anchor_id(&self) -> AnchorId {
99 match self {
100 LayoutSlot::Group { anchor, .. } => *anchor,
101 LayoutSlot::ValueRef { anchor } => *anchor,
102 LayoutSlot::Node { anchor, .. } => *anchor,
103 LayoutSlot::Gap { anchor, .. } => *anchor,
104 }
105 }
106}
107
108impl Default for LayoutSlot {
109 fn default() -> Self {
110 LayoutSlot::Gap {
111 anchor: AnchorId::INVALID,
112 group_key: None,
113 group_scope: None,
114 group_len: 0,
115 }
116 }
117}
118
119impl SplitSlotStorage {
120 pub fn new() -> Self {
121 Self {
122 next_anchor_id: Cell::new(1), ..Default::default()
124 }
125 }
126
127 fn alloc_anchor(&self) -> AnchorId {
128 let id = self.next_anchor_id.get();
129 self.next_anchor_id.set(id + 1);
130 AnchorId::new(id)
131 }
132
133 fn ensure_capacity(&mut self) {
134 const INITIAL_CAP: usize = 32;
135 if self.layout.is_empty() {
136 self.layout.resize_with(INITIAL_CAP, LayoutSlot::default);
137 } else if self.cursor >= self.layout.len() {
138 let new_size = self.layout.len() * 2;
139 self.layout.resize_with(new_size, LayoutSlot::default);
140 }
141 }
142
143 fn insert_at_cursor(&mut self, slot: LayoutSlot) {
144 self.ensure_capacity();
145
146 if matches!(self.layout.get(self.cursor), Some(LayoutSlot::Gap { .. })) {
148 self.layout[self.cursor] = slot;
149 } else {
150 if self.cursor < self.layout.len() {
153 self.layout[self.cursor] = slot;
154 }
155 }
156
157 if let Some(frame) = self.group_stack.last_mut() {
159 if self.cursor >= frame.end {
160 frame.end = self.cursor + 1;
161 }
162 }
163 self.anchors_dirty = true;
164 }
165
166 fn start_group(&mut self, key: Key) -> (usize, bool) {
167 self.ensure_capacity();
168
169 if let Some(LayoutSlot::Gap {
171 group_key: Some(gap_key),
172 group_scope,
173 group_len,
174 anchor: gap_anchor,
175 }) = self.layout.get(self.cursor)
176 {
177 if *gap_key == key {
178 let anchor = if gap_anchor.is_valid() {
180 *gap_anchor
181 } else {
182 self.alloc_anchor()
183 };
184 let scope = *group_scope;
185 let len = *group_len;
186 self.layout[self.cursor] = LayoutSlot::Group {
187 key,
188 anchor,
189 len,
190 scope,
191 has_gap_children: true,
192 };
193
194 let start = self.cursor;
195 self.cursor += 1;
196 self.group_stack.push(GroupFrame {
201 key,
202 start,
203 end: start + len + 1,
204 force_children_recompose: true,
205 });
206 self.last_start_was_gap = true;
207 self.anchors_dirty = true;
208 return (start, true);
209 }
210 }
211
212 let anchor = self.alloc_anchor();
214 let slot = LayoutSlot::Group {
215 key,
216 anchor,
217 len: 0,
218 scope: None,
219 has_gap_children: false,
220 };
221
222 self.insert_at_cursor(slot);
223 let start = self.cursor;
224 self.cursor += 1;
225 self.group_stack.push(GroupFrame {
226 key,
227 start,
228 end: start,
229 force_children_recompose: false,
230 });
231 self.last_start_was_gap = false;
232 (start, false)
233 }
234
235 fn do_end_group(&mut self) {
236 if let Some(frame) = self.group_stack.pop() {
237 let len = self.cursor.saturating_sub(frame.start + 1);
238 if let Some(LayoutSlot::Group { len: slot_len, .. }) = self.layout.get_mut(frame.start)
239 {
240 *slot_len = len;
241 }
242 }
243 }
244
245 fn do_finalize_current_group(&mut self) -> bool {
246 let frame_end = match self.group_stack.last() {
247 Some(frame) => frame.end,
248 None => {
249 if self.cursor >= self.layout.len() {
251 return false;
252 }
253 let mut marked = false;
254 while self.cursor < self.layout.len() {
255 let slot = &mut self.layout[self.cursor];
256 let anchor = slot.anchor_id();
257 let (group_key, group_scope, group_len) = match slot {
258 LayoutSlot::Group {
259 key, scope, len, ..
260 } => (Some(*key), *scope, *len),
261 _ => (None, None, 0),
262 };
263 *slot = LayoutSlot::Gap {
264 anchor,
265 group_key,
266 group_scope,
267 group_len,
268 };
269 marked = true;
270 self.cursor += 1;
271 }
272 self.anchors_dirty = true;
274 return marked;
275 }
276 };
277
278 let mut marked = false;
279 while self.cursor < frame_end && self.cursor < self.layout.len() {
280 let slot = &mut self.layout[self.cursor];
281 let anchor = slot.anchor_id();
282 let (group_key, group_scope, group_len) = match slot {
283 LayoutSlot::Group {
284 key, scope, len, ..
285 } => (Some(*key), *scope, *len),
286 _ => (None, None, 0),
287 };
288
289 *slot = LayoutSlot::Gap {
293 anchor,
294 group_key,
295 group_scope,
296 group_len,
297 };
298 marked = true;
299 self.cursor += 1;
300 }
301
302 if let Some(frame) = self.group_stack.last_mut() {
303 frame.end = self.cursor;
304 }
305 marked
306 }
307}
308
309impl SlotStorage for SplitSlotStorage {
310 type Group = GroupId;
311 type ValueSlot = ValueSlotId;
312
313 fn begin_group(&mut self, key: Key) -> StartGroup<Self::Group> {
314 let (idx, restored) = self.start_group(key);
315 StartGroup {
316 group: GroupId::new(idx),
317 restored_from_gap: restored,
318 }
319 }
320
321 fn set_group_scope(&mut self, group: Self::Group, scope: ScopeId) {
322 if let Some(LayoutSlot::Group {
323 scope: slot_scope, ..
324 }) = self.layout.get_mut(group.index())
325 {
326 *slot_scope = Some(scope);
327 }
328 }
329
330 fn end_group(&mut self) {
331 self.do_end_group();
332 }
333
334 fn skip_current_group(&mut self) {
335 if let Some(LayoutSlot::Group { len, .. }) = self.layout.get(self.cursor) {
336 self.cursor += 1 + len;
337 }
338 }
339
340 fn nodes_in_current_group(&self) -> Vec<NodeId> {
341 let mut nodes = Vec::new();
342 if let Some(frame) = self.group_stack.last() {
343 for pos in (frame.start + 1)..frame.end {
344 if let Some(LayoutSlot::Node { id, .. }) = self.layout.get(pos) {
345 nodes.push(*id);
346 }
347 }
348 }
349 nodes
350 }
351
352 fn begin_recranpose_at_scope(&mut self, scope: ScopeId) -> Option<Self::Group> {
353 for (idx, slot) in self.layout.iter().enumerate() {
354 if let LayoutSlot::Group { scope: Some(s), .. } = slot {
355 if *s == scope {
356 self.cursor = idx;
357 return Some(GroupId::new(idx));
358 }
359 }
360 }
361 None
362 }
363
364 fn end_recompose(&mut self) {
365 }
367
368 fn alloc_value_slot<T: 'static>(&mut self, init: impl FnOnce() -> T) -> Self::ValueSlot {
369 self.ensure_capacity();
370
371 if let Some(LayoutSlot::ValueRef { anchor }) = self.layout.get(self.cursor) {
373 let anchor_id = anchor.0;
374 if let Some(data) = self.payload.get(&anchor_id) {
376 if data.is::<T>() {
377 let slot_id = ValueSlotId::new(self.cursor);
379 self.cursor += 1;
380 return slot_id;
381 } else {
382 self.payload.insert(anchor_id, Box::new(init()));
384 let slot_id = ValueSlotId::new(self.cursor);
385 self.cursor += 1;
386 return slot_id;
387 }
388 } else {
389 self.payload.insert(anchor_id, Box::new(init()));
391 let slot_id = ValueSlotId::new(self.cursor);
392 self.cursor += 1;
393 return slot_id;
394 }
395 }
396
397 if matches!(self.layout.get(self.cursor), Some(LayoutSlot::Gap { .. })) {
399 let anchor = self.alloc_anchor();
401 let anchor_id = anchor.0;
402
403 self.payload.insert(anchor_id, Box::new(init()));
405
406 self.layout[self.cursor] = LayoutSlot::ValueRef { anchor };
408
409 let slot_id = ValueSlotId::new(self.cursor);
410 self.cursor += 1;
411
412 if let Some(frame) = self.group_stack.last_mut() {
413 if self.cursor > frame.end {
414 frame.end = self.cursor;
415 }
416 }
417 self.anchors_dirty = true;
418 return slot_id;
419 }
420
421 let anchor = self.alloc_anchor();
423 let anchor_id = anchor.0;
424
425 self.payload.insert(anchor_id, Box::new(init()));
427
428 let slot = LayoutSlot::ValueRef { anchor };
430 self.insert_at_cursor(slot);
431
432 let slot_id = ValueSlotId::new(self.cursor);
433 self.cursor += 1;
434 slot_id
435 }
436
437 fn read_value<T: 'static>(&self, slot: Self::ValueSlot) -> &T {
438 let layout_slot = self
439 .layout
440 .get(slot.index())
441 .expect("layout slot not found");
442 let anchor = layout_slot.anchor_id();
443 let data = self.payload.get(&anchor.0).expect("payload not found");
444 data.downcast_ref::<T>().expect("type mismatch")
445 }
446
447 fn read_value_mut<T: 'static>(&mut self, slot: Self::ValueSlot) -> &mut T {
448 let layout_slot = self
449 .layout
450 .get(slot.index())
451 .expect("layout slot not found");
452 let anchor = layout_slot.anchor_id();
453 let data = self.payload.get_mut(&anchor.0).expect("payload not found");
454 data.downcast_mut::<T>().expect("type mismatch")
455 }
456
457 fn write_value<T: 'static>(&mut self, slot: Self::ValueSlot, value: T) {
458 let layout_slot = self
459 .layout
460 .get(slot.index())
461 .expect("layout slot not found");
462 let anchor = layout_slot.anchor_id();
463 self.payload.insert(anchor.0, Box::new(value));
464 }
465
466 fn remember<T: 'static>(&mut self, init: impl FnOnce() -> T) -> Owned<T> {
467 let slot = self.alloc_value_slot(|| Owned::new(init()));
468 self.read_value::<Owned<T>>(slot).clone()
469 }
470
471 fn peek_node(&self) -> Option<NodeId> {
472 if let Some(LayoutSlot::Node { id, .. }) = self.layout.get(self.cursor) {
473 Some(*id)
474 } else {
475 None
476 }
477 }
478
479 fn record_node(&mut self, id: NodeId) {
480 self.ensure_capacity();
481 let anchor = self.alloc_anchor();
482 let slot = LayoutSlot::Node { anchor, id };
483 self.insert_at_cursor(slot);
484 self.cursor += 1;
485 }
486
487 fn advance_after_node_read(&mut self) {
488 self.cursor += 1;
489 }
490
491 fn step_back(&mut self) {
492 self.cursor = self.cursor.saturating_sub(1);
493 }
494
495 fn finalize_current_group(&mut self) -> bool {
496 self.do_finalize_current_group()
497 }
498
499 fn reset(&mut self) {
500 self.cursor = 0;
501 self.group_stack.clear();
502 }
503
504 fn flush(&mut self) {
505 if self.anchors_dirty {
507 for pos in self.anchors.iter_mut() {
508 *pos = usize::MAX;
509 }
510
511 for (idx, slot) in self.layout.iter().enumerate() {
512 let anchor = slot.anchor_id();
513 if anchor.is_valid() {
514 let id = anchor.0;
515 if id >= self.anchors.len() {
516 self.anchors.resize(id + 1, usize::MAX);
517 }
518 self.anchors[id] = idx;
519 }
520 }
521
522 self.anchors_dirty = false;
523 }
524 }
525}
526
527impl SplitSlotStorage {
528 pub fn debug_dump_groups(&self) -> Vec<(usize, Key, Option<ScopeId>, usize)> {
530 self.layout
531 .iter()
532 .enumerate()
533 .filter_map(|(i, slot)| match slot {
534 LayoutSlot::Group {
535 key, len, scope, ..
536 } => Some((i, *key, *scope, *len)),
537 _ => None,
538 })
539 .collect()
540 }
541
542 pub fn debug_dump_all_slots(&self) -> Vec<(usize, String)> {
544 self.layout
545 .iter()
546 .enumerate()
547 .map(|(i, slot)| {
548 let desc = match slot {
549 LayoutSlot::Group {
550 key,
551 scope,
552 len,
553 has_gap_children,
554 ..
555 } => {
556 format!(
557 "Group(key={}, scope={:?}, len={}, gaps={})",
558 key, scope, len, has_gap_children
559 )
560 }
561 LayoutSlot::ValueRef { .. } => "ValueRef".to_string(),
562 LayoutSlot::Node { id, .. } => format!("Node(id={})", id),
563 LayoutSlot::Gap {
564 group_key,
565 group_scope,
566 group_len,
567 ..
568 } => {
569 format!(
570 "Gap(key={:?}, scope={:?}, len={})",
571 group_key, group_scope, group_len
572 )
573 }
574 };
575 (i, desc)
576 })
577 .collect()
578 }
579}