1use alloc::vec::Vec;
4use core::{
5 cmp::Ordering,
6 hash::{BuildHasher, Hash},
7 mem,
8};
9
10use hashbrown::{HashMap, HashSet};
11use indexmap::IndexSet;
12use scratchpads::{Scratchpad, ScratchpadMap};
13
14#[cfg(debug_assertions)]
15use contracts::contract;
16
17#[cfg(feature = "rkyv")]
18use rkyv::{
19 Archive, Deserialize, Serialize,
20 bytecheck::Verify,
21 collections::swiss_table::{ArchivedHashMap, ArchivedHashSet, ArchivedIndexSet},
22 rancor::{Fallible, Source, fail},
23 with::Skip,
24};
25
26#[cfg(feature = "serde")]
27use serde::{
28 Deserialize as SerdeDeserialize, Deserializer as SerdeDeserializer,
29 Serialize as SerdeSerialize, de::Error as _,
30};
31
32use crate::{
33 ActivePathWeave, BookmarkableWeave, DiscreteContentResult, DiscreteContents, DiscreteWeave,
34 IndependentContents, MetadataWeave, Node, SemiIndependentWeave, SortableBookmarkableWeave,
35 SortableWeave, Weave, ancestor_subgraph, ancestor_subgraph_reaches,
36 contract::valid_topology,
37 dependent::{DependentNode, DependentWeave},
38 descendant_subgraph, descendant_subgraph_reaches, longest_candidate_path_to_root,
39 shortest_path_to_ancestor, topological_sort, topological_sort_subgraph,
40};
41
42#[cfg(debug_assertions)]
43use crate::contract::{lacks_duplicates, valid_path, valid_topological_sort};
44
45#[cfg(feature = "rkyv")]
46use crate::{
47 ImmutableActivePathWeave, ImmutableBookmarkableWeave, ImmutableMetadataWeave, ImmutableWeave,
48 archived_ancestor_subgraph, archived_descendant_subgraph,
49 archived_longest_candidate_path_to_root, archived_shortest_path_to_ancestor,
50 archived_topological_sort, archived_topological_sort_subgraph,
51 contract::archived_valid_topology,
52};
53
54#[cfg(any(feature = "serde", feature = "rkyv"))]
55use crate::contract::ValidationError;
56
57#[derive(Default, Debug, Clone)]
58#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
59#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
60#[must_use]
62pub struct IndependentNode<K, T, S>
63where
64 K: Hash + Copy + Eq + Ord,
65 T: IndependentContents,
66 S: BuildHasher + Default + Clone,
67{
68 pub id: K,
70 #[cfg_attr(
72 feature = "serde",
73 serde(bound(
74 serialize = "IndexSet<K, S>: SerdeSerialize",
75 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
76 ))
77 )]
78 pub from: IndexSet<K, S>,
79 #[cfg_attr(
81 feature = "serde",
82 serde(bound(
83 serialize = "IndexSet<K, S>: SerdeSerialize",
84 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
85 ))
86 )]
87 pub to: IndexSet<K, S>,
88 pub active: bool,
92 pub bookmarked: bool,
94 pub contents: T,
96}
97
98#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
99impl<K, T, S> PartialEq for IndependentNode<K, T, S>
100where
101 K: Hash + Copy + Eq + Ord,
102 T: IndependentContents + PartialEq,
103 S: BuildHasher + Default + Clone,
104{
105 #[inline]
106 fn eq(&self, other: &Self) -> bool {
107 self.id == other.id
108 && self.from.len() == other.from.len()
109 && self.to.len() == other.to.len()
110 && self.active == other.active
111 && self.bookmarked == other.bookmarked
112 && self.from.iter().zip(other.from.iter()).all(|(a, b)| a == b)
113 && self.to.iter().zip(other.to.iter()).all(|(a, b)| a == b)
114 && self.contents == other.contents
115 }
116}
117
118#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
119impl<K, T, S> Eq for IndependentNode<K, T, S>
120where
121 K: Hash + Copy + Eq + Ord,
122 T: IndependentContents + Eq,
123 S: BuildHasher + Default + Clone,
124{
125}
126
127impl<K, T, S> IndependentNode<K, T, S>
128where
129 K: Hash + Copy + Eq + Ord,
130 T: IndependentContents,
131 S: BuildHasher + Default + Clone,
132{
133 fn validate(&self) -> bool {
134 self.from.is_disjoint(&self.to)
135 && !self.from.contains(&self.id)
136 && !self.to.contains(&self.id)
137 }
138}
139
140impl<K, T, S> Node<K, T> for IndependentNode<K, T, S>
141where
142 K: Hash + Copy + Eq + Ord,
143 T: IndependentContents,
144 S: BuildHasher + Default + Clone,
145{
146 type From = IndexSet<K, S>;
147 type To = IndexSet<K, S>;
148
149 #[inline]
150 fn id(&self) -> K {
151 self.id
152 }
153 #[inline]
154 fn from(&self) -> &Self::From {
155 &self.from
156 }
157 #[inline]
158 fn to(&self) -> &Self::To {
159 &self.to
160 }
161 #[inline]
162 fn is_active(&self) -> bool {
163 self.active
164 }
165 #[inline]
166 fn contents(&self) -> &T {
167 &self.contents
168 }
169}
170
171impl<K, T, S> From<DependentNode<K, T, S>> for IndependentNode<K, T, S>
172where
173 K: Hash + Copy + Eq + Ord,
174 T: IndependentContents,
175 S: BuildHasher + Default + Clone,
176{
177 #[inline]
178 fn from(value: DependentNode<K, T, S>) -> Self {
179 Self {
180 id: value.id,
181 from: IndexSet::from_iter(value.from),
182 to: value.to,
183 active: value.active,
184 bookmarked: value.bookmarked,
185 contents: value.contents,
186 }
187 }
188}
189
190impl<K, T, S> TryFrom<IndependentNode<K, T, S>> for DependentNode<K, T, S>
191where
192 K: Hash + Copy + Eq + Ord,
193 T: IndependentContents,
194 S: BuildHasher + Default + Clone,
195{
196 type Error = IndependentNode<K, T, S>;
197
198 #[inline]
199 fn try_from(value: IndependentNode<K, T, S>) -> Result<Self, Self::Error> {
200 if value.from.len() < 2 {
201 Ok(Self {
202 id: value.id,
203 from: value.from.into_iter().next(),
204 to: value.to,
205 active: value.active,
206 bookmarked: value.bookmarked,
207 contents: value.contents,
208 })
209 } else {
210 Err(value)
211 }
212 }
213}
214
215#[derive(Default, Debug, Clone)]
223#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
224#[cfg_attr(feature = "serde", derive(SerdeSerialize))]
225#[cfg_attr(feature = "rkyv", rkyv(bytecheck(verify)))]
226#[must_use]
227pub struct IndependentWeave<K, T, M, S>
228where
229 K: Hash + Copy + Eq + Ord,
230 T: IndependentContents,
231 S: BuildHasher + Default + Clone,
232{
233 #[cfg_attr(
234 feature = "serde",
235 serde(bound(
236 serialize = "HashMap<K, IndependentNode<K, T, S>, S>: SerdeSerialize",
237 deserialize = "HashMap<K, IndependentNode<K, T, S>, S>: SerdeDeserialize<'de>"
238 ))
239 )]
240 nodes: HashMap<K, IndependentNode<K, T, S>, S>,
241 #[cfg_attr(
242 feature = "serde",
243 serde(bound(
244 serialize = "IndexSet<K, S>: SerdeSerialize",
245 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
246 ))
247 )]
248 roots: IndexSet<K, S>,
249 #[cfg_attr(
250 feature = "serde",
251 serde(bound(
252 serialize = "HashSet<K, S>: SerdeSerialize",
253 deserialize = "HashSet<K, S>: SerdeDeserialize<'de>"
254 ))
255 )]
256 active: HashSet<K, S>,
257 #[cfg_attr(
258 feature = "serde",
259 serde(bound(
260 serialize = "IndexSet<K, S>: SerdeSerialize",
261 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
262 ))
263 )]
264 bookmarked: IndexSet<K, S>,
265
266 #[cfg_attr(feature = "rkyv", rkyv(with = Skip))]
267 #[cfg_attr(feature = "serde", serde(skip))]
268 scratchpad: Scratchpad,
269
270 pub metadata: M,
272}
273
274#[cfg(feature = "serde")]
275#[derive(SerdeDeserialize)]
276#[serde(rename = "IndependentWeave")]
277struct ProxyIndependentWeave<K, T, M, S>
278where
279 K: Hash + Copy + Eq + Ord,
280 T: IndependentContents,
281 S: BuildHasher + Default + Clone,
282{
283 #[serde(bound(
284 serialize = "HashMap<K, IndependentNode<K, T, S>, S>: SerdeSerialize",
285 deserialize = "HashMap<K, IndependentNode<K, T, S>, S>: SerdeDeserialize<'de>"
286 ))]
287 nodes: HashMap<K, IndependentNode<K, T, S>, S>,
288 #[serde(bound(
289 serialize = "IndexSet<K, S>: SerdeSerialize",
290 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
291 ))]
292 roots: IndexSet<K, S>,
293 #[serde(bound(
294 serialize = "HashSet<K, S>: SerdeSerialize",
295 deserialize = "HashSet<K, S>: SerdeDeserialize<'de>"
296 ))]
297 active: HashSet<K, S>,
298 #[serde(bound(
299 serialize = "IndexSet<K, S>: SerdeSerialize",
300 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
301 ))]
302 bookmarked: IndexSet<K, S>,
303 metadata: M,
304}
305
306#[cfg(feature = "serde")]
307#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
308impl<'de, K, T, M, S> SerdeDeserialize<'de> for IndependentWeave<K, T, M, S>
309where
310 K: Hash + Copy + Eq + Ord + SerdeDeserialize<'de>,
311 T: IndependentContents + SerdeDeserialize<'de>,
312 M: SerdeDeserialize<'de>,
313 S: BuildHasher + Default + Clone,
314{
315 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
316 where
317 D: SerdeDeserializer<'de>,
318 {
319 let proxy = ProxyIndependentWeave::deserialize(deserializer)?;
320 let weave = Self {
321 nodes: proxy.nodes,
322 roots: proxy.roots,
323 active: proxy.active,
324 bookmarked: proxy.bookmarked,
325 scratchpad: Scratchpad::new(),
326 metadata: proxy.metadata,
327 };
328
329 if weave.validate() {
330 Ok(weave)
331 } else {
332 Err(D::Error::custom(ValidationError))
333 }
334 }
335}
336
337#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
338impl<K, T, M, S> PartialEq for IndependentWeave<K, T, M, S>
339where
340 K: Hash + Copy + Eq + Ord,
341 T: IndependentContents + PartialEq,
342 M: PartialEq,
343 S: BuildHasher + Default + Clone,
344{
345 #[inline]
346 fn eq(&self, other: &Self) -> bool {
347 self.roots.len() == other.roots.len()
348 && self.bookmarked.len() == other.bookmarked.len()
349 && self.nodes.len() == other.nodes.len()
350 && self.active == other.active
351 && self
352 .roots
353 .iter()
354 .zip(other.roots.iter())
355 .all(|(a, b)| a == b)
356 && self
357 .bookmarked
358 .iter()
359 .zip(other.bookmarked.iter())
360 .all(|(a, b)| a == b)
361 && self.nodes == other.nodes
362 && self.metadata == other.metadata
363 }
364}
365
366#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
367impl<K, T, M, S> Eq for IndependentWeave<K, T, M, S>
368where
369 K: Hash + Copy + Eq + Ord,
370 T: IndependentContents + Eq,
371 M: Eq,
372 S: BuildHasher + Default + Clone,
373{
374}
375
376impl<K, T, M, S> IndependentWeave<K, T, M, S>
377where
378 K: Hash + Copy + Eq + Ord,
379 T: IndependentContents,
380 S: BuildHasher + Default + Clone,
381{
382 #[cfg_attr(debug_assertions, contract(
384 ensures(ret.nodes.is_empty()),
385 ensures(ret.validate())
386 ))]
387 pub fn with_capacity(capacity: usize, metadata: M) -> Self {
388 let nodes = HashMap::with_capacity_and_hasher(capacity, S::default());
389 let capacity = nodes.capacity();
390
391 Self {
392 nodes,
393 roots: IndexSet::with_capacity_and_hasher(capacity, S::default()),
394 active: HashSet::with_capacity_and_hasher(capacity, S::default()),
395 bookmarked: IndexSet::with_capacity_and_hasher(capacity, S::default()),
396 scratchpad: Scratchpad::new(),
397 metadata,
398 }
399 }
400 #[inline]
404 pub fn capacity(&self) -> usize {
405 self.nodes
406 .capacity()
407 .min(self.roots.capacity())
408 .min(self.active.capacity())
409 .min(self.bookmarked.capacity())
410 }
411 #[cfg_attr(debug_assertions, contract(
413 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
414 ensures(old(self.roots.clone()) == self.roots),
415 ensures(old(self.active.clone()) == self.active),
416 ensures(old(self.bookmarked.clone()) == self.bookmarked),
417 invariant(self.validate())
418 ))]
419 pub fn reserve(&mut self, additional: usize) {
420 self.nodes.reserve(additional);
421 self.roots
422 .reserve(self.nodes.capacity().saturating_sub(self.roots.len()));
423 self.active
424 .reserve(self.nodes.capacity().saturating_sub(self.active.len()));
425 self.bookmarked
426 .reserve(self.nodes.capacity().saturating_sub(self.bookmarked.len()));
427 }
428 #[cfg_attr(debug_assertions, contract(
430 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
431 ensures(old(self.roots.clone()) == self.roots),
432 ensures(old(self.active.clone()) == self.active),
433 ensures(old(self.bookmarked.clone()) == self.bookmarked),
434 invariant(self.validate())
435 ))]
436 pub fn shrink_to(&mut self, min_capacity: usize) {
437 self.nodes.shrink_to(min_capacity);
438 self.roots.shrink_to(min_capacity);
439 self.active.shrink_to(min_capacity);
440 self.bookmarked.shrink_to(min_capacity);
441 }
442 #[allow(
443 clippy::too_many_lines,
444 reason = "Cannot be split into smaller functions"
445 )]
446 #[cfg_attr(debug_assertions, contract(
447 ensures(ret == self.nodes.contains_key(id)),
448 ensures(!ret || value == self.active.contains(id)),
449 ensures(self.validate())
450 ))]
451 fn update_node_activity_in_place(&mut self, id: &K, value: bool) -> bool {
452 let at_end = if let Some(node) = self.nodes.get(id) {
453 if node.active == value {
454 return true;
455 }
456
457 if value {
458 (node.from.is_empty() && self.active.is_empty())
459 || node.from.iter().any(|parent| {
460 self.active.contains(parent)
461 && self.nodes[parent]
462 .to
463 .iter()
464 .all(|child| !self.active.contains(child))
465 })
466 } else {
467 node.to.iter().all(|child| !self.active.contains(child))
468 }
469 } else {
470 return false;
471 };
472
473 let node = self.nodes.get_mut(id).unwrap();
474 node.active = value;
475 if value {
476 self.active.insert(node.id);
477 } else {
478 self.active.remove(id);
479 }
480
481 if at_end {
482 return true;
483 }
484
485 if value {
486 let has_descendants = !node.to.is_empty();
487
488 let guard = self.scratchpad.guard();
489
490 let mut stack = guard.vec();
491 let mut closure = guard.set(S::default());
492 let mut closure_roots = guard.vec();
493
494 ancestor_subgraph(&self.nodes, *id, &mut stack, &mut closure, |id| {
495 closure_roots.push(id);
496 });
497
498 let mut topological = guard.vec_with_capacity(closure.len());
499 let mut scratchpad_map = guard.map_with_capacity(closure.len(), S::default());
500 let mut scratchpad_map_2: ScratchpadMap<'_, K, ((usize, usize), Option<K>), S> =
501 guard.map_with_capacity(closure.len(), S::default());
502 let mut scratchpad_set = guard.set(S::default());
503
504 for root in closure_roots.drain(..) {
505 topological_sort_subgraph(
506 &self.nodes,
507 |id| closure.contains(id),
508 root,
509 &mut stack,
510 |id| topological.push(id),
511 &mut scratchpad_map,
512 );
513 }
514
515 for id in topological.iter().copied() {
516 let node = &self.nodes[&id];
517
518 let best_parent = node
519 .from
520 .iter()
521 .map(|id| (id, scratchpad_map_2[id].0)) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
523
524 let (parent, score) = if let Some((parent, mut score)) = best_parent {
525 if node.active {
526 score.1 = score.1.strict_add(1);
527 } else {
528 score.0 = score.0.strict_add(1);
529 }
530
531 (Some(parent), score)
532 } else {
533 (None, if node.active { (0, 1) } else { (1, 0) })
534 };
535
536 scratchpad_map_2.insert(id, (score, parent.copied()));
537 }
538
539 let mut current = Some(id);
540
541 while let Some(id) = current {
542 scratchpad_set.insert(*id);
543 current = scratchpad_map_2
544 .get(id)
545 .and_then(|(_, parent)| parent.as_ref());
546 }
547
548 closure.clear();
549 topological.clear();
550 scratchpad_map.clear();
551 scratchpad_map_2.clear();
552
553 if self.active.len() != 1 && has_descendants {
554 descendant_subgraph(&self.nodes, *id, &mut stack, &mut closure);
555
556 let has_active_descendant = if closure.len() >= self.active.len() {
557 self.active.iter().any(|a| a != id && closure.contains(a))
558 } else {
559 closure.iter().any(|d| d != id && self.active.contains(d))
560 };
561
562 if has_active_descendant {
563 topological_sort_subgraph(
564 &self.nodes,
565 |id| closure.contains(id),
566 *id,
567 &mut stack,
568 |id| topological.push(id),
569 &mut scratchpad_map,
570 );
571
572 for id in topological.drain(..).rev() {
573 let node = &self.nodes[&id];
574
575 let best_child = node
576 .to
577 .iter()
578 .map(|id| (id, scratchpad_map_2[id].0)) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
580
581 let (child, score) = if let Some((child, mut score)) = best_child {
582 if node.active {
583 score.1 = score.1.strict_add(1);
584 } else {
585 score.0 = score.0.strict_add(1);
586 }
587
588 (Some(child), score)
589 } else {
590 (None, if node.active { (0, 1) } else { (1, 0) })
591 };
592
593 scratchpad_map_2.insert(id, (score, child.copied()));
594 }
595
596 let mut current = Some(id);
597
598 while let Some(id) = current {
599 scratchpad_set.insert(*id);
600
601 let (score, successor) = &scratchpad_map_2[id];
602 current = if score.1 > usize::from(self.nodes[id].active) {
603 successor.as_ref()
604 } else {
605 None
606 };
607 }
608 }
609 }
610
611 let mut disjoint = topological;
612
613 disjoint.extend(
614 self.active
615 .iter()
616 .filter(|id| !scratchpad_set.contains(*id))
617 .copied(),
618 );
619
620 for id in disjoint.drain(..) {
621 self.nodes.get_mut(&id).unwrap().active = false;
622 self.active.remove(&id);
623 }
624
625 disjoint.extend(
626 scratchpad_set
627 .iter()
628 .filter(|id| !self.active.contains(*id))
629 .copied(),
630 );
631
632 for id in disjoint.drain(..) {
633 self.nodes.get_mut(&id).unwrap().active = true;
634 self.active.insert(id);
635 }
636 } else {
637 self.fix_orphaned_activations();
638 }
639
640 true
641 }
642 #[cfg_attr(debug_assertions, contract(
643 ensures(self.validate())
644 ))]
645 fn fix_orphaned_activations(&mut self) {
646 if self.active.is_empty() {
647 return;
648 }
649
650 let guard = self.scratchpad.guard();
651
652 let mut stack = guard.vec();
653 let mut closure = guard.set_with_capacity(self.active.len(), S::default());
654
655 for id in self.active.iter().copied() {
656 ancestor_subgraph(&self.nodes, id, &mut stack, &mut closure, |_| {});
657 }
658
659 let mut topological = guard.vec_with_capacity(closure.len());
660 let mut scratchpad_map = guard.map_with_capacity(closure.len(), S::default());
661
662 for root in self
663 .roots
664 .iter()
665 .filter(|id| closure.contains(*id))
666 .copied()
667 {
668 topological_sort_subgraph(
669 &self.nodes,
670 |id| closure.contains(id),
671 root,
672 &mut stack,
673 |id| topological.push(id),
674 &mut scratchpad_map,
675 );
676 }
677
678 scratchpad_map.clear();
679
680 let mut candidate_path = guard.vec_with_capacity(self.active.len());
681
682 longest_candidate_path_to_root(
683 &self.nodes,
684 &topological,
685 |id| self.active.contains(id),
686 &mut scratchpad_map,
687 |id| candidate_path.push(id),
688 );
689
690 topological.clear();
691 let mut disjoint = topological;
692
693 closure.clear();
694 let mut candidate_path_set = closure;
695
696 candidate_path_set.extend(candidate_path.drain(..));
697
698 disjoint.extend(
699 self.active
700 .iter()
701 .filter(|id| !candidate_path_set.contains(*id))
702 .copied(),
703 );
704
705 for orphan in disjoint.drain(..) {
706 self.active.remove(&orphan);
707 if let Some(node) = self.nodes.get_mut(&orphan) {
708 node.active = false;
709 }
710 }
711 }
712 #[cfg_attr(debug_assertions, contract(
713 ensures(!ret || value || !self.active.contains(id) || (old(self.active.clone()) == self.active && self.nodes[id].to.iter().any(|id| self.contains_active(id)))),
714 ensures(!ret || !value || self.contains_active(id) && !self.nodes[id].to.iter().any(|id| self.active.contains(id))),
715 ensures(ret || old(self.active.clone()) == self.active),
716 ensures(ret == self.nodes.contains_key(id)),
717 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
718 ensures(old(self.roots.clone()) == self.roots),
719 ensures(old(self.bookmarked.clone()) == self.bookmarked),
720 invariant(self.validate())
721 ))]
722 #[allow(
723 clippy::too_many_lines,
724 reason = "Cannot be split into smaller functions"
725 )]
726 #[allow(clippy::missing_panics_doc, reason = "Should never panic")]
727 pub fn set_active_dependent_semantics(&mut self, id: &K, value: bool) -> bool {
729 if value {
730 if let Some(node) = self.nodes.get(id) {
731 if node.active && !node.to.iter().any(|id| self.active.contains(id)) {
732 return true;
733 }
734
735 if !node.active
736 && ((node.from.is_empty() && self.active.is_empty())
737 || node.from.iter().any(|parent| {
738 self.active.contains(parent)
739 && self.nodes[parent]
740 .to
741 .iter()
742 .all(|child| !self.active.contains(child))
743 }))
744 {
745 self.nodes.get_mut(id).unwrap().active = true;
746 self.active.insert(*id);
747 return true;
748 }
749 } else {
750 return false;
751 }
752
753 let guard = self.scratchpad.guard();
754
755 let mut stack = guard.vec();
756 let mut closure = guard.set(S::default());
757 let mut closure_roots = guard.vec();
758
759 ancestor_subgraph(&self.nodes, *id, &mut stack, &mut closure, |id| {
760 closure_roots.push(id);
761 });
762
763 let mut topological = guard.vec_with_capacity(closure.len());
764 let mut scratchpad_map = guard.map_with_capacity(closure.len(), S::default());
765 let mut scratchpad_map_2: ScratchpadMap<'_, K, ((usize, usize), Option<K>), S> =
766 guard.map_with_capacity(closure.len(), S::default());
767
768 for root in closure_roots.drain(..) {
769 topological_sort_subgraph(
770 &self.nodes,
771 |id| closure.contains(id),
772 root,
773 &mut stack,
774 |id| topological.push(id), &mut scratchpad_map,
776 );
777 }
778
779 for id in topological.drain(..) {
780 let node = &self.nodes[&id];
781
782 let best_parent = node
783 .from
784 .iter()
785 .map(|id| (id, scratchpad_map_2[id].0)) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
787
788 let (parent, score) = if let Some((parent, mut score)) = best_parent {
789 if node.active {
790 score.1 = score.1.strict_add(1);
791 } else {
792 score.0 = score.0.strict_add(1);
793 }
794
795 (Some(parent), score)
796 } else {
797 (None, if node.active { (0, 1) } else { (1, 0) })
798 };
799
800 scratchpad_map_2.insert(id, (score, parent.copied()));
801 }
802
803 closure.clear();
804 let mut scratchpad_set = closure;
805
806 let mut disjoint = topological;
807
808 let mut current = Some(id);
809
810 while let Some(id) = current {
811 scratchpad_set.insert(*id);
812 current = scratchpad_map_2
813 .get(id)
814 .and_then(|(_, parent)| parent.as_ref());
815 }
816
817 disjoint.extend(
818 self.active
819 .iter()
820 .filter(|id| !scratchpad_set.contains(*id))
821 .copied(),
822 );
823
824 for id in disjoint.drain(..) {
825 self.nodes.get_mut(&id).unwrap().active = false;
826 self.active.remove(&id);
827 }
828
829 disjoint.extend(
830 scratchpad_set
831 .iter()
832 .filter(|id| !self.active.contains(*id))
833 .copied(),
834 );
835
836 for id in disjoint.drain(..) {
837 self.nodes.get_mut(&id).unwrap().active = true;
838 self.active.insert(id);
839 }
840 } else if let Some(node) = self.nodes.get_mut(id) {
841 if !node.active || node.to.iter().any(|id| self.active.contains(id)) {
842 return true;
843 }
844
845 node.active = false;
846 self.active.remove(&node.id);
847 } else {
848 return false;
849 }
850
851 true
852 }
853}
854
855impl<K, T, M, S> From<DependentWeave<K, T, M, S>> for IndependentWeave<K, T, M, S>
856where
857 K: Hash + Copy + Eq + Ord,
858 T: IndependentContents,
859 S: BuildHasher + Default + Clone,
860{
861 fn from(value: DependentWeave<K, T, M, S>) -> Self {
862 let mut output = Self {
863 active: HashSet::with_capacity_and_hasher(value.nodes.capacity(), S::default()),
864 nodes: {
865 let mut map =
866 HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default());
867 map.extend(value.nodes.into_iter().map(|(id, mut node)| {
868 node.active = false;
869 (id, node.into())
870 }));
871
872 map
873 },
874 roots: value.roots,
875 bookmarked: value.bookmarked,
876 scratchpad: value.scratchpad,
877 metadata: value.metadata,
878 };
879
880 if let Some(active) = value.active {
881 output.set_active(&active, true);
882 }
883
884 debug_assert!(output.validate(), "Converted weave is malformed");
885
886 output
887 }
888}
889
890#[allow(clippy::panic_in_result_fn, reason = "Should never panic")]
891#[allow(clippy::unreachable, reason = "Should never panic")]
892impl<K, T, M, S> TryFrom<IndependentWeave<K, T, M, S>> for DependentWeave<K, T, M, S>
893where
894 K: Hash + Copy + Eq + Ord,
895 T: IndependentContents,
896 S: BuildHasher + Default + Clone,
897{
898 type Error = IndependentWeave<K, T, M, S>;
899
900 fn try_from(value: IndependentWeave<K, T, M, S>) -> Result<Self, Self::Error> {
901 if value.nodes.iter().all(|(_, node)| node.from.len() < 2) {
902 let mut active = None;
903
904 let output = Self {
905 nodes: {
906 let mut map =
907 HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default());
908 map.extend(value.nodes.into_iter().map(|(id, mut node)| {
909 node.active =
910 node.active && !node.to.iter().any(|id| value.active.contains(id));
911 if node.active {
912 active = Some(id);
913 }
914
915 node.try_into()
916 .map_or_else(|_| unreachable!(), |node| (id, node))
917 }));
918
919 map
920 },
921 roots: value.roots,
922 active,
923 bookmarked: value.bookmarked,
924 scratchpad: value.scratchpad,
925 metadata: value.metadata,
926 };
927
928 debug_assert!(output.validate(), "Converted weave is malformed");
929
930 Ok(output)
931 } else {
932 Err(value)
933 }
934 }
935}
936
937impl<K, T, M, S> Weave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
938where
939 K: Hash + Copy + Eq + Ord,
940 T: IndependentContents,
941 S: BuildHasher + Default + Clone,
942{
943 type Nodes = HashMap<K, IndependentNode<K, T, S>, S>;
944 type Roots = IndexSet<K, S>;
945
946 #[inline]
947 fn len(&self) -> usize {
948 self.nodes.len()
949 }
950 #[inline]
951 fn is_empty(&self) -> bool {
952 self.nodes.is_empty()
953 }
954 #[inline]
955 fn nodes(&self) -> &Self::Nodes {
956 &self.nodes
957 }
958 #[inline]
959 fn roots(&self) -> &Self::Roots {
960 &self.roots
961 }
962 #[inline]
963 fn contains(&self, id: &K) -> bool {
964 self.nodes.contains_key(id)
965 }
966 #[inline]
967 fn contains_active(&self, id: &K) -> bool {
968 self.active.contains(id)
969 }
970 #[inline]
971 fn get(&self, id: &K) -> Option<&IndependentNode<K, T, S>> {
972 self.nodes.get(id)
973 }
974 #[inline]
975 fn get_parents(&self, id: &K) -> Option<&IndexSet<K, S>> {
976 self.nodes.get(id).map(|node| &node.from)
977 }
978 #[inline]
979 fn get_children(&self, id: &K) -> Option<&IndexSet<K, S>> {
980 self.nodes.get(id).map(|node| &node.to)
981 }
982 #[inline]
983 fn get_contents(&self, id: &K) -> Option<&T> {
984 self.nodes.get(id).map(|node| &node.contents)
985 }
986 #[cfg_attr(debug_assertions, contract(
987 ensures(output.len() == self.nodes.len()),
988 ensures(valid_topological_sort(&self.nodes, output)),
989 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
990 ensures(old(self.roots.clone()) == self.roots),
991 ensures(old(self.active.clone()) == self.active),
992 ensures(old(self.bookmarked.clone()) == self.bookmarked),
993 invariant(self.validate())
994 ))]
995 fn get_ordered_identifiers(&mut self, output: &mut Vec<K>) {
996 output.clear();
997 output.reserve(self.nodes.len());
998
999 let guard = self.scratchpad.guard();
1000
1001 topological_sort(
1002 &self.nodes,
1003 self.roots.iter().copied(),
1004 &mut guard.vec_with_capacity(self.roots.len()),
1005 |id| output.push(id),
1006 &mut guard
1007 .map_with_capacity(self.nodes.len().strict_sub(self.roots.len()), S::default()),
1008 );
1009 }
1010 #[cfg_attr(debug_assertions, contract(
1011 ensures(lacks_duplicates(output)),
1012 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1013 ensures(self.nodes.contains_key(id) || output.is_empty()),
1014 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1015 ensures(old(self.roots.clone()) == self.roots),
1016 ensures(old(self.active.clone()) == self.active),
1017 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1018 invariant(self.validate())
1019 ))]
1020 fn get_ordered_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
1021 output.clear();
1022
1023 if self.nodes.contains_key(id) {
1024 let guard = self.scratchpad.guard();
1025
1026 let mut stack = guard.vec();
1027 let mut descendants = guard.set(S::default());
1028
1029 descendant_subgraph(&self.nodes, *id, &mut stack, &mut descendants);
1030
1031 output.reserve(descendants.len());
1032
1033 topological_sort_subgraph(
1034 &self.nodes,
1035 |id| descendants.contains(id),
1036 *id,
1037 &mut stack,
1038 |id| output.push(id),
1039 &mut guard.map_with_capacity(descendants.len(), S::default()),
1040 );
1041 }
1042 }
1043 #[cfg_attr(debug_assertions, contract(
1044 ensures(output.len() == self.active.len()),
1045 ensures(output.iter().all(|i| self.active.contains(i))),
1046 ensures(lacks_duplicates(output)),
1047 ensures(valid_path(&self.nodes, output)),
1048 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1049 ensures(old(self.roots.clone()) == self.roots),
1050 ensures(old(self.active.clone()) == self.active),
1051 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1052 invariant(self.validate())
1053 ))]
1054 fn get_active_path(&mut self, output: &mut Vec<K>) {
1055 output.clear();
1056
1057 if self.active.is_empty() {
1058 return;
1059 }
1060
1061 output.reserve(self.active.len());
1062
1063 let guard = self.scratchpad.guard();
1064
1065 let mut stack = guard.vec();
1066 let mut topological_subgraph = guard.vec_with_capacity(self.active.len());
1067 let mut scratchpad_map = guard.map_with_capacity(self.active.len(), S::default());
1068
1069 for root in self
1070 .roots
1071 .iter()
1072 .filter(|id| self.active.contains(*id))
1073 .copied()
1074 {
1075 topological_sort_subgraph(
1076 &self.nodes,
1077 |id| self.active.contains(id),
1078 root,
1079 &mut stack,
1080 |id| topological_subgraph.push(id),
1081 &mut scratchpad_map,
1082 );
1083 }
1084
1085 scratchpad_map.clear();
1086
1087 longest_candidate_path_to_root(
1088 &self.nodes,
1089 &topological_subgraph,
1090 |id| self.active.contains(id),
1091 &mut scratchpad_map,
1092 |id| output.push(id),
1093 );
1094 }
1095 #[cfg_attr(debug_assertions, contract(
1096 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1097 ensures(self.nodes.contains_key(id) || output.is_empty()),
1098 ensures(lacks_duplicates(output)),
1099 ensures(valid_path(&self.nodes, output)),
1100 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1101 ensures(old(self.roots.clone()) == self.roots),
1102 ensures(old(self.active.clone()) == self.active),
1103 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1104 invariant(self.validate())
1105 ))]
1106 fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
1107 output.clear();
1108 if !self.nodes.contains_key(id) {
1109 return;
1110 }
1111
1112 let guard = self.scratchpad.guard();
1113 let mut stack = guard.vec();
1114 let mut ancestors = guard.set(S::default());
1115 let mut root_ancestors = guard.vec();
1116
1117 ancestor_subgraph(&self.nodes, *id, &mut stack, &mut ancestors, |id| {
1118 root_ancestors.push(id);
1119 });
1120
1121 let mut active_topological_subgraph =
1122 guard.vec_with_capacity(self.active.len().min(ancestors.len()));
1123 let mut scratchpad_map =
1124 guard.map_with_capacity(self.active.len().min(ancestors.len()), S::default());
1125
1126 for root in root_ancestors
1127 .drain(..)
1128 .filter(|id| self.active.contains(id))
1129 {
1130 topological_sort_subgraph(
1131 &self.nodes,
1132 |id| self.active.contains(id) && ancestors.contains(id),
1133 root,
1134 &mut stack,
1135 |id| active_topological_subgraph.push(id),
1136 &mut scratchpad_map,
1137 );
1138 }
1139
1140 scratchpad_map.clear();
1141
1142 let mut reversed_path = guard.vec();
1143
1144 longest_candidate_path_to_root(
1145 &self.nodes,
1146 &active_topological_subgraph,
1147 |id| self.active.contains(id) && ancestors.contains(id),
1148 &mut scratchpad_map,
1149 |id| reversed_path.push(id),
1150 );
1151
1152 let mut scratchpad_map_2 = guard.map_with_capacity(ancestors.len(), S::default());
1153
1154 ancestors.clear();
1155 let mut scratchpad_set = ancestors;
1156
1157 if let Some(target) = reversed_path.first().copied() {
1158 shortest_path_to_ancestor(
1159 &self.nodes,
1160 id,
1161 |node| node.id == target,
1162 &mut stack,
1163 &mut scratchpad_map_2,
1164 &mut scratchpad_set,
1165 output,
1166 );
1167
1168 output.reverse();
1169 output.pop();
1170 output.extend_from_slice(&reversed_path);
1171 } else {
1172 shortest_path_to_ancestor(
1173 &self.nodes,
1174 id,
1175 |node| node.from.is_empty(),
1176 &mut stack,
1177 &mut scratchpad_map_2,
1178 &mut scratchpad_set,
1179 output,
1180 );
1181
1182 output.reverse();
1183 }
1184 }
1185 #[cfg_attr(debug_assertions, contract(
1186 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1187 ensures(!ret || old(!self.nodes.contains_key(&node.id))),
1188 ensures(!ret || self.nodes.contains_key(&old(node.id))),
1189 ensures(!ret || old(node.active) == self.active.contains(&old(node.id)) || (!old(node.active) && self.active.contains(&old(node.id)) && old(node.to.iter().any(|c| self.active.contains(c))))),
1190 ensures(!ret || old(node.bookmarked) == self.bookmarked.contains(&old(node.id))),
1191 ensures(!ret || old(!node.from.is_empty()) || self.roots.contains(&old(node.id))),
1192 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1193 ensures(ret || old(self.roots.clone()) == self.roots),
1194 ensures(ret || old(self.active.clone()) == self.active),
1195 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1196 invariant(self.validate())
1197 ))]
1198 fn insert(&mut self, mut node: IndependentNode<K, T, S>) -> bool {
1199 if self.nodes.contains_key(&node.id)
1200 || !node.validate()
1201 || !node.from.iter().all(|id| self.nodes.contains_key(id))
1202 || !node.to.iter().all(|id| self.nodes.contains_key(id))
1203 {
1204 return false;
1205 }
1206
1207 if !node.to.is_empty() && !node.from.is_empty() {
1208 let guard = self.scratchpad.guard();
1209
1210 if ancestor_subgraph_reaches(
1211 &self.nodes,
1212 node.from.iter().copied(),
1213 |id| node.to.contains(id),
1214 &mut guard.vec_with_capacity(node.from.len()),
1215 &mut guard.set_with_capacity(node.from.len(), S::default()),
1216 ) {
1217 return false;
1218 }
1219 }
1220
1221 let root_index = if node.from.is_empty() {
1222 node.to
1223 .iter()
1224 .filter_map(|child| self.roots.get_index_of(child))
1225 .min()
1226 } else {
1227 None
1228 };
1229
1230 let mut detached_root = false;
1231
1232 for child in &node.to {
1233 let child = self.nodes.get_mut(child).unwrap();
1234
1235 if child.from.is_empty() {
1236 node.active |= child.active;
1237 detached_root = true;
1238 }
1239
1240 child.from.insert(node.id);
1241 }
1242
1243 if detached_root {
1244 self.roots.retain(|id| !node.to.contains(id));
1245 }
1246
1247 let extends_active = node.active
1248 && node.to.is_empty()
1249 && node.from.iter().map(|id| &self.nodes[id]).any(|parent| {
1250 parent.active && parent.to.iter().all(|child| !self.active.contains(child))
1251 });
1252
1253 if node.from.is_empty() {
1254 if let Some(index) = root_index {
1255 self.roots.shift_insert(index, node.id);
1256 } else {
1257 self.roots.insert(node.id);
1258 }
1259 } else {
1260 for parent in &node.from {
1261 let parent = self.nodes.get_mut(parent).unwrap();
1262 parent.to.insert(node.id);
1263 }
1264 }
1265
1266 if node.bookmarked {
1267 self.bookmarked.insert(node.id);
1268 }
1269
1270 let id = node.id;
1271 let active = node.active;
1272
1273 if !extends_active {
1274 node.active = false;
1275 }
1276
1277 self.nodes.insert(node.id, node);
1278
1279 if extends_active {
1280 self.active.insert(id);
1281 } else if active {
1282 self.update_node_activity_in_place(&id, true);
1283 }
1284
1285 true
1286 }
1287 #[cfg_attr(debug_assertions, contract(
1288 ensures(!ret || value == self.contains_active(id)),
1289 ensures(ret || old(self.active.clone()) == self.active),
1290 ensures(ret == self.nodes.contains_key(id)),
1291 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1292 ensures(old(self.roots.clone()) == self.roots),
1293 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1294 invariant(self.validate())
1295 ))]
1296 fn set_active(&mut self, id: &K, value: bool) -> bool {
1297 self.update_node_activity_in_place(id, value)
1298 }
1299 #[cfg_attr(debug_assertions, contract(
1300 ensures(!self.nodes.contains_key(id)),
1301 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1302 ensures(ret.as_ref().is_none_or(|node| &node.id == id)),
1303 ensures(ret.is_none() || old(self.nodes.len()) > self.nodes.len()),
1304 ensures(ret.is_none() || old(self.active.len()) >= self.active.len()),
1305 ensures(ret.is_none() || old(self.bookmarked.len()) >= self.bookmarked.len()),
1306 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1307 ensures(ret.is_some() || old(self.roots.clone()) == self.roots),
1308 ensures(ret.is_some() || old(self.active.clone()) == self.active),
1309 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1310 invariant(self.validate())
1311 ))]
1312 fn remove(&mut self, id: &K) -> Option<IndependentNode<K, T, S>> {
1313 let node = self.nodes.remove(id)?;
1314
1315 if node.from.is_empty() {
1316 self.roots.shift_remove(id);
1317 } else {
1318 for parent in &node.from {
1319 if let Some(parent) = self.nodes.get_mut(parent) {
1320 parent.to.shift_remove(id);
1321 }
1322 }
1323 }
1324
1325 let mut removed_active = node.active;
1326 let mut removed_bookmark = node.bookmarked;
1327
1328 if removed_active {
1329 self.active.remove(id);
1330 }
1331
1332 if node.to.is_empty() {
1333 if removed_bookmark {
1334 self.bookmarked.shift_remove(id);
1335 }
1336 return Some(node);
1337 }
1338
1339 {
1340 let guard = self.scratchpad.guard();
1341 let mut stack = guard.vec();
1342 let mut removed = guard.vec_with_capacity(node.to.len().strict_add(1));
1343 let mut remaining_parents = guard.map_with_capacity(node.to.len(), S::default());
1344
1345 removed.push(*id);
1346
1347 for child in node.to.iter().rev().copied() {
1348 let remaining = remaining_parents
1349 .entry(child)
1350 .or_insert_with(|| self.nodes[&child].from.len());
1351 *remaining = remaining.strict_sub(1);
1352
1353 if *remaining == 0 {
1354 stack.push(child);
1355 }
1356 }
1357
1358 while let Some(id) = stack.pop() {
1359 let node = self.nodes.remove(&id).unwrap();
1360 removed.push(id);
1361
1362 removed_bookmark |= node.bookmarked;
1363 if node.active {
1364 self.active.remove(&id);
1365 removed_active = true;
1366 }
1367
1368 for child in node.to.iter().rev().copied() {
1369 let remaining = remaining_parents
1370 .entry(child)
1371 .or_insert_with(|| self.nodes[&child].from.len());
1372 *remaining = remaining.strict_sub(1);
1373
1374 if *remaining == 0 {
1375 stack.push(child);
1376 }
1377 }
1378 }
1379
1380 if removed_active
1381 && !remaining_parents
1382 .iter()
1383 .any(|(child, remaining)| *remaining > 0 && self.active.contains(child))
1384 {
1385 removed_active = false;
1386 }
1387
1388 if removed.len() == 1 {
1389 for (child, _) in remaining_parents {
1390 if let Some(child) = self.nodes.get_mut(&child) {
1391 child.from.shift_remove(id);
1392 }
1393 }
1394 if removed_bookmark {
1395 self.bookmarked.shift_remove(id);
1396 }
1397 } else {
1398 let mut removed_set = guard.set_with_capacity(removed.len(), S::default());
1399 removed_set.extend(removed);
1400
1401 for (child, remaining) in remaining_parents {
1402 if remaining > 0
1403 && let Some(child) = self.nodes.get_mut(&child)
1404 {
1405 child.from.retain(|parent| !removed_set.contains(parent));
1406 }
1407 }
1408
1409 if removed_bookmark {
1410 self.bookmarked.retain(|id| !removed_set.contains(id));
1411 }
1412 }
1413 }
1414
1415 if removed_active {
1416 self.fix_orphaned_activations();
1417 }
1418
1419 Some(node)
1420 }
1421 #[cfg_attr(debug_assertions, contract(
1422 ensures(!self.nodes.contains_key(id)),
1423 ensures(ret == old(self.nodes.contains_key(id))),
1424 ensures(!ret || old(self.nodes.len()) > self.nodes.len()),
1425 ensures(!ret || old(self.active.len()) >= self.active.len()),
1426 ensures(!ret || old(self.bookmarked.len()) >= self.bookmarked.len()),
1427 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1428 ensures(ret || old(self.roots.clone()) == self.roots),
1429 ensures(ret || old(self.active.clone()) == self.active),
1430 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1431 invariant(self.validate())
1432 ))]
1433 fn remove_tracked(
1434 &mut self,
1435 id: &K,
1436 mut on_removal: impl FnMut(IndependentNode<K, T, S>),
1437 ) -> bool {
1438 let Some(node) = self.nodes.remove(id) else {
1439 return false;
1440 };
1441
1442 if node.from.is_empty() {
1443 self.roots.shift_remove(id);
1444 } else {
1445 for parent in &node.from {
1446 if let Some(parent) = self.nodes.get_mut(parent) {
1447 parent.to.shift_remove(id);
1448 }
1449 }
1450 }
1451
1452 let mut removed_active = node.active;
1453 let mut removed_bookmark = node.bookmarked;
1454
1455 if removed_active {
1456 self.active.remove(id);
1457 }
1458
1459 if node.to.is_empty() {
1460 if removed_bookmark {
1461 self.bookmarked.shift_remove(id);
1462 }
1463 on_removal(node);
1464 return true;
1465 }
1466
1467 {
1468 let guard = self.scratchpad.guard();
1469 let mut stack = guard.vec();
1470 let mut removed = guard.vec_with_capacity(node.to.len().strict_add(1));
1471 let mut remaining_parents = guard.map_with_capacity(node.to.len(), S::default());
1472
1473 removed.push(*id);
1474
1475 for child in node.to.iter().rev().copied() {
1476 let remaining = remaining_parents
1477 .entry(child)
1478 .or_insert_with(|| self.nodes[&child].from.len());
1479 *remaining = remaining.strict_sub(1);
1480
1481 if *remaining == 0 {
1482 stack.push(child);
1483 }
1484 }
1485
1486 on_removal(node);
1487
1488 while let Some(id) = stack.pop() {
1489 let node = self.nodes.remove(&id).unwrap();
1490 removed.push(id);
1491
1492 removed_bookmark |= node.bookmarked;
1493 if node.active {
1494 self.active.remove(&id);
1495 removed_active = true;
1496 }
1497
1498 for child in node.to.iter().rev().copied() {
1499 let remaining = remaining_parents
1500 .entry(child)
1501 .or_insert_with(|| self.nodes[&child].from.len());
1502 *remaining = remaining.strict_sub(1);
1503
1504 if *remaining == 0 {
1505 stack.push(child);
1506 }
1507 }
1508
1509 on_removal(node);
1510 }
1511
1512 if removed_active
1513 && !remaining_parents
1514 .iter()
1515 .any(|(child, remaining)| *remaining > 0 && self.active.contains(child))
1516 {
1517 removed_active = false;
1518 }
1519
1520 if removed.len() == 1 {
1521 for (child, _) in remaining_parents {
1522 if let Some(child) = self.nodes.get_mut(&child) {
1523 child.from.shift_remove(id);
1524 }
1525 }
1526 if removed_bookmark {
1527 self.bookmarked.shift_remove(id);
1528 }
1529 } else {
1530 let mut removed_set = guard.set_with_capacity(removed.len(), S::default());
1531 removed_set.extend(removed);
1532
1533 for (child, remaining) in remaining_parents {
1534 if remaining > 0
1535 && let Some(child) = self.nodes.get_mut(&child)
1536 {
1537 child.from.retain(|parent| !removed_set.contains(parent));
1538 }
1539 }
1540
1541 if removed_bookmark {
1542 self.bookmarked.retain(|id| !removed_set.contains(id));
1543 }
1544 }
1545 }
1546
1547 if removed_active {
1548 self.fix_orphaned_activations();
1549 }
1550
1551 true
1552 }
1553 #[cfg_attr(debug_assertions, contract(
1554 ensures(self.nodes.is_empty()),
1555 ensures(self.validate())
1556 ))]
1557 fn clear(&mut self) {
1558 self.nodes.clear();
1559 self.roots.clear();
1560 self.active.clear();
1561 self.bookmarked.clear();
1562 }
1563}
1564
1565impl<K, T, M, S> IndependentWeave<K, T, M, S>
1566where
1567 K: Hash + Copy + Eq + Ord,
1568 T: IndependentContents,
1569 S: BuildHasher + Default + Clone,
1570{
1571 pub fn validate(&self) -> bool {
1573 self.roots
1574 .iter()
1575 .all(move |value| self.nodes.contains_key(value))
1576 && self
1577 .active
1578 .iter()
1579 .all(move |value| self.nodes.contains_key(value))
1580 && self
1581 .bookmarked
1582 .iter()
1583 .all(move |value| self.nodes.contains_key(value))
1584 && self.nodes.iter().all(|(key, value)| {
1585 value.validate()
1586 && value.id == *key
1587 && value
1588 .from
1589 .iter()
1590 .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
1591 && value
1592 .to
1593 .iter()
1594 .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
1595 && value.from.is_empty() == self.roots.contains(key)
1596 && value.active == self.active.contains(key)
1597 && value.bookmarked == self.bookmarked.contains(key)
1598 })
1599 && valid_topology(&self.nodes, &self.roots, &self.active)
1600 }
1601}
1602
1603impl<K, T, M, S> MetadataWeave<K, IndependentNode<K, T, S>, T, M> for IndependentWeave<K, T, M, S>
1604where
1605 K: Hash + Copy + Eq + Ord,
1606 T: IndependentContents,
1607 S: BuildHasher + Default + Clone,
1608{
1609 #[inline]
1610 fn metadata(&self) -> &M {
1611 &self.metadata
1612 }
1613 #[cfg_attr(debug_assertions, contract(
1614 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1615 ensures(old(self.roots.clone()) == self.roots),
1616 ensures(old(self.active.clone()) == self.active),
1617 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1618 invariant(self.validate())
1619 ))]
1620 #[inline]
1621 fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
1622 callback(&mut self.metadata)
1623 }
1624}
1625
1626impl<K, T, M, S> BookmarkableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1627where
1628 K: Hash + Copy + Eq + Ord,
1629 T: IndependentContents,
1630 S: BuildHasher + Default + Clone,
1631{
1632 type Bookmarks = IndexSet<K, S>;
1633
1634 #[inline]
1635 fn bookmarks(&self) -> &Self::Bookmarks {
1636 &self.bookmarked
1637 }
1638 #[inline]
1639 fn contains_bookmark(&self, id: &K) -> bool {
1640 self.bookmarked.contains(id)
1641 }
1642 #[cfg_attr(debug_assertions, contract(
1643 ensures(!ret || value == self.bookmarked.contains(id)),
1644 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1645 ensures(ret == self.nodes.contains_key(id)),
1646 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1647 ensures(old(self.roots.clone()) == self.roots),
1648 ensures(old(self.active.clone()) == self.active),
1649 invariant(self.validate())
1650 ))]
1651 fn set_bookmarked(&mut self, id: &K, value: bool) -> bool {
1652 match self.nodes.get_mut(id) {
1653 Some(node) => {
1654 node.bookmarked = value;
1655 if value {
1656 self.bookmarked.insert(node.id);
1657 } else {
1658 self.bookmarked.shift_remove(id);
1659 }
1660
1661 true
1662 }
1663 None => false,
1664 }
1665 }
1666}
1667
1668impl<K, T, M, S> SortableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1669where
1670 K: Hash + Copy + Eq + Ord,
1671 T: IndependentContents,
1672 S: BuildHasher + Default + Clone,
1673{
1674 #[cfg_attr(debug_assertions, contract(
1675 ensures(ret == self.nodes.contains_key(id)),
1676 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1677 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1678 ensures(old(self.roots.clone()) == self.roots),
1679 ensures(old(self.active.clone()) == self.active),
1680 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1681 invariant(self.validate())
1682 ))]
1683 fn sort_children_by(
1684 &mut self,
1685 id: &K,
1686 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1687 ) -> bool {
1688 if let Some(node) = self.nodes.get_mut(id) {
1689 let mut set = mem::take(&mut node.to);
1690
1691 if set.len() > 20 {
1692 let guard = self.scratchpad.guard();
1693 let mut nodes = guard
1694 .arena()
1695 .alloc_iter_exact(set.drain(..).map(|id| &self.nodes[&id]));
1696 nodes.sort_by(|a, b| cmp(*a, *b));
1697
1698 set.extend(nodes.into_iter().map(|node| node.id));
1699 } else {
1700 set.sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1701 }
1702
1703 self.nodes.get_mut(id).unwrap().to = set;
1704
1705 true
1706 } else {
1707 false
1708 }
1709 }
1710 #[cfg_attr(debug_assertions, contract(
1711 ensures(ret == self.nodes.contains_key(id)),
1712 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1713 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1714 ensures(old(self.roots.clone()) == self.roots),
1715 ensures(old(self.active.clone()) == self.active),
1716 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1717 invariant(self.validate())
1718 ))]
1719 fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
1720 if let Some(node) = self.nodes.get_mut(id) {
1721 node.to.sort_by(cmp);
1722
1723 true
1724 } else {
1725 false
1726 }
1727 }
1728 #[cfg_attr(debug_assertions, contract(
1729 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1730 ensures(old(self.roots.clone()) == self.roots),
1731 ensures(old(self.active.clone()) == self.active),
1732 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1733 invariant(self.validate())
1734 ))]
1735 fn sort_roots_by(
1736 &mut self,
1737 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1738 ) {
1739 if self.roots.len() > 20 {
1740 let guard = self.scratchpad.guard();
1741
1742 let mut nodes = guard
1743 .arena()
1744 .alloc_iter_exact(self.roots.iter().map(|id| &self.nodes[id]));
1745 nodes.sort_by(|a, b| cmp(*a, *b));
1746
1747 self.roots.clear();
1748 self.roots.extend(nodes.into_iter().map(|node| node.id));
1749 } else {
1750 self.roots
1751 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1752 }
1753 }
1754 #[cfg_attr(debug_assertions, contract(
1755 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1756 ensures(old(self.roots.clone()) == self.roots),
1757 ensures(old(self.active.clone()) == self.active),
1758 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1759 invariant(self.validate())
1760 ))]
1761 fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1762 self.roots.sort_by(cmp);
1763 }
1764}
1765
1766impl<K, T, M, S> SortableBookmarkableWeave<K, IndependentNode<K, T, S>, T>
1767 for IndependentWeave<K, T, M, S>
1768where
1769 K: Hash + Copy + Eq + Ord,
1770 T: IndependentContents,
1771 S: BuildHasher + Default + Clone,
1772{
1773 #[cfg_attr(debug_assertions, contract(
1774 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1775 ensures(old(self.roots.clone()) == self.roots),
1776 ensures(old(self.active.clone()) == self.active),
1777 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1778 invariant(self.validate())
1779 ))]
1780 fn sort_bookmarks_by(
1781 &mut self,
1782 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1783 ) {
1784 if self.bookmarked.len() > 20 {
1785 let guard = self.scratchpad.guard();
1786
1787 let mut nodes = guard
1788 .arena()
1789 .alloc_iter_exact(self.bookmarked.iter().map(|id| &self.nodes[id]));
1790 nodes.sort_by(|a, b| cmp(*a, *b));
1791
1792 self.bookmarked.clear();
1793 self.bookmarked
1794 .extend(nodes.into_iter().map(|node| node.id));
1795 } else {
1796 self.bookmarked
1797 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1798 }
1799 }
1800 #[cfg_attr(debug_assertions, contract(
1801 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1802 ensures(old(self.roots.clone()) == self.roots),
1803 ensures(old(self.active.clone()) == self.active),
1804 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1805 invariant(self.validate())
1806 ))]
1807 fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1808 self.bookmarked.sort_by(cmp);
1809 }
1810}
1811
1812impl<K, T, M, S> ActivePathWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1813where
1814 K: Hash + Copy + Eq + Ord,
1815 T: IndependentContents,
1816 S: BuildHasher + Default + Clone,
1817{
1818 type Active = HashSet<K, S>;
1819
1820 #[inline]
1821 fn active(&self) -> &Self::Active {
1822 &self.active
1823 }
1824 #[cfg_attr(debug_assertions, contract(
1825 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1826 ensures(old(self.roots.clone()) == self.roots),
1827 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1828 invariant(self.validate())
1829 ))]
1830 fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
1831 self.active.drain().for_each(|active| {
1832 self.nodes.get_mut(&active).unwrap().active = false;
1833 });
1834 self.active
1835 .extend(active.filter(|id| self.nodes.contains_key(id)));
1836 self.active.iter().for_each(|active| {
1837 self.nodes.get_mut(active).unwrap().active = true;
1838 });
1839 self.fix_orphaned_activations();
1840 }
1841}
1842
1843impl<K, T, M, S> DiscreteWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1844where
1845 K: Hash + Copy + Eq + Ord,
1846 T: IndependentContents + DiscreteContents,
1847 S: BuildHasher + Default + Clone,
1848{
1849 #[cfg_attr(debug_assertions, contract(
1850 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1851 ensures(!ret || self.nodes.contains_key(id)),
1852 ensures(!ret || self.nodes.contains_key(&new_id)),
1853 ensures(!ret || old(!self.nodes.contains_key(&new_id))),
1854 ensures(!ret || self.nodes[id].to.contains(&new_id) && self.nodes[id].to.len() == 1),
1855 ensures(!ret || self.nodes[&new_id].from.contains(id) && self.nodes[&new_id].from.len() == 1),
1856 ensures(!ret || old(self.nodes.get(id).map(|n| n.to.clone())).unwrap() == self.nodes[&new_id].to),
1857 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1858 ensures(ret || old(self.active.clone()) == self.active),
1859 ensures(old(self.roots.clone()) == self.roots),
1860 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1861 invariant(self.validate())
1862 ))]
1863 fn split(&mut self, id: &K, at: usize, new_id: K) -> bool {
1864 if self.nodes.contains_key(&new_id) || *id == new_id {
1865 return false;
1866 }
1867
1868 if let Some(mut node) = self.nodes.remove(id) {
1869 match node.contents.split(at) {
1870 DiscreteContentResult::Two(left, right) => {
1871 let left_node = IndependentNode {
1872 id: node.id,
1873 from: node.from,
1874 to: IndexSet::from_iter([new_id]),
1875 active: node.active,
1876 bookmarked: node.bookmarked,
1877 contents: left,
1878 };
1879
1880 node.from = IndexSet::from_iter([node.id]);
1881 node.id = new_id;
1882 node.contents = right;
1883 node.active = false;
1884 node.bookmarked = false;
1885
1886 let mut child_active = false;
1887
1888 for child in &node.to {
1889 let child = self.nodes.get_mut(child).unwrap();
1890 let index = child.from.get_index_of(&left_node.id).unwrap();
1891
1892 assert!(
1893 child.from.replace_index(index, node.id).is_ok(),
1894 "Should be unreachable"
1895 );
1896
1897 child_active |= child.active;
1898 }
1899
1900 if left_node.active && child_active {
1901 node.active = true;
1902 self.active.insert(node.id);
1903 }
1904
1905 self.nodes.insert(left_node.id, left_node);
1906 self.nodes.insert(node.id, node);
1907
1908 true
1909 }
1910 DiscreteContentResult::One(content) => {
1911 node.contents = content;
1912 self.nodes.insert(node.id, node);
1913 false
1914 }
1915 }
1916 } else {
1917 false
1918 }
1919 }
1920 #[cfg_attr(debug_assertions, contract(
1921 ensures(ret.is_none() || old(self.nodes.len()) - 1 == self.nodes.len()),
1922 ensures(ret.is_none() || !self.nodes.contains_key(id)),
1923 ensures(ret.is_none() || old(self.nodes.contains_key(id))),
1924 ensures(ret.is_none() || !old(self.contains_active(id)) || old(self.contains_active(id)) && self.contains_active(&ret.unwrap())),
1925 ensures(ret.is_none() || old(self.nodes.get(id).and_then(|n| n.from.first()).and_then(|p| self.nodes.get(p)).map(|p| p.active)).unwrap() == self.nodes[&ret.unwrap()].active),
1926 ensures(ret.is_none() || old(self.nodes.get(id).and_then(|n| n.from.first()).and_then(|p| self.nodes.get(p)).map(|p| p.from.clone())).unwrap() == self.nodes[&ret.unwrap()].from),
1927 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.to.clone())).unwrap() == self.nodes[&ret.unwrap()].to),
1928 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.from.len() == 1)).unwrap()),
1929 ensures(ret.is_none() || ret.unwrap() == old(self.nodes.get(id).and_then(|node| node.from.first().copied())).unwrap()),
1930 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1931 ensures(ret.is_some() || old(self.active.clone()) == self.active),
1932 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1933 ensures(old(self.roots.clone()) == self.roots),
1934 invariant(self.validate())
1935 ))]
1936 fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1937 if let Some(mut node) = self.nodes.remove(id) {
1938 if node.from.len() != 1 {
1939 self.nodes.insert(node.id, node);
1940 return None;
1941 }
1942
1943 if let Some(mut parent) = node.from.first().and_then(|id| self.nodes.remove(id)) {
1944 if parent.to.len() > 1 {
1945 self.nodes.insert(parent.id, parent);
1946 self.nodes.insert(node.id, node);
1947 return None;
1948 }
1949
1950 match parent.contents.merge(node.contents) {
1951 DiscreteContentResult::Two(left, right) => {
1952 parent.contents = left;
1953 node.contents = right;
1954 self.nodes.insert(parent.id, parent);
1955 self.nodes.insert(node.id, node);
1956 None
1957 }
1958 DiscreteContentResult::One(content) => {
1959 parent.contents = content;
1960 parent.to = node.to;
1961
1962 for child in &parent.to {
1963 let child = self.nodes.get_mut(child).unwrap();
1964 let index = child.from.get_index_of(&node.id).unwrap();
1965
1966 assert!(
1967 child.from.replace_index(index, parent.id).is_ok(),
1968 "Should be unreachable"
1969 );
1970 }
1971
1972 let parent_id = parent.id;
1973
1974 if node.bookmarked && !parent.bookmarked {
1975 parent.bookmarked = true;
1976 assert!(
1977 self.bookmarked
1978 .replace_index(
1979 self.bookmarked.get_index_of(&node.id).unwrap(),
1980 parent.id,
1981 )
1982 .is_ok(),
1983 "Should be unreachable"
1984 );
1985 } else if node.bookmarked {
1986 self.bookmarked.shift_remove(&node.id);
1987 }
1988
1989 self.nodes.insert(parent.id, parent);
1990 self.active.remove(&node.id);
1991
1992 Some(parent_id)
1993 }
1994 }
1995 } else {
1996 self.nodes.insert(node.id, node);
1997 None
1998 }
1999 } else {
2000 None
2001 }
2002 }
2003}
2004
2005impl<K, T, M, S> SemiIndependentWeave<K, IndependentNode<K, T, S>, T>
2006 for IndependentWeave<K, T, M, S>
2007where
2008 K: Hash + Copy + Eq + Ord,
2009 T: IndependentContents,
2010 S: BuildHasher + Default + Clone,
2011{
2012 #[cfg_attr(debug_assertions, contract(
2013 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
2014 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
2015 ensures(old(self.roots.clone()) == self.roots),
2016 ensures(old(self.active.clone()) == self.active),
2017 ensures(old(self.bookmarked.clone()) == self.bookmarked),
2018 invariant(self.validate())
2019 ))]
2020 #[inline]
2021 fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
2022 self.nodes
2023 .get_mut(id)
2024 .map(|node| callback(&mut node.contents))
2025 }
2026}
2027
2028impl<K, T, M, S> crate::IndependentWeave<K, IndependentNode<K, T, S>, T>
2029 for IndependentWeave<K, T, M, S>
2030where
2031 K: Hash + Copy + Eq + Ord,
2032 T: IndependentContents,
2033 S: BuildHasher + Default + Clone,
2034{
2035 #[cfg_attr(debug_assertions, contract(
2036 ensures(!ret || self.nodes[id].from.iter().copied().collect::<HashSet<_>>() == new_parents.iter().copied().collect::<HashSet<_>>()),
2037 ensures(ret || old(self.nodes.get(id).map(|node| node.from.clone())).as_ref() == self.nodes.get(id).map(|node| &node.from)),
2038 ensures(ret || old(self.roots.clone()) == self.roots),
2039 ensures(ret || old(self.active.clone()) == self.active),
2040 ensures(old(self.nodes.get(id).map(|node| node.to.clone())).as_ref() == self.nodes.get(id).map(|node| &node.to)),
2041 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
2042 ensures(old(self.bookmarked.clone()) == self.bookmarked),
2043 ensures(old(self.active.contains(id)) == self.active.contains(id)),
2044 invariant(self.validate())
2045 ))]
2046 fn move_to(&mut self, id: &K, new_parents: &[K]) -> bool {
2047 if new_parents
2048 .iter()
2049 .any(|new_parent| !self.nodes.contains_key(new_parent))
2050 {
2051 return false;
2052 }
2053
2054 let Some(node) = self.nodes.get(id) else {
2055 return false;
2056 };
2057
2058 if node.from.iter().eq(new_parents) {
2059 return true;
2060 }
2061
2062 let new_parents: IndexSet<K, S> = new_parents.iter().copied().collect();
2063
2064 if new_parents.contains(id) {
2065 return false;
2066 }
2067
2068 if !node.to.is_empty() && !new_parents.is_empty() {
2069 let guard = self.scratchpad.guard();
2070
2071 if descendant_subgraph_reaches(
2072 &self.nodes,
2073 node.to.iter().copied(),
2074 |id| new_parents.contains(id),
2075 &mut guard.vec_with_capacity(node.to.len()),
2076 &mut guard.set_with_capacity(node.to.len(), S::default()),
2077 ) {
2078 return false;
2079 }
2080 }
2081
2082 if let Some(node) = self.nodes.get_mut(id) {
2083 let old_parents = mem::take(&mut node.from);
2084
2085 for old_parent in &old_parents {
2086 if !new_parents.contains(old_parent)
2087 && let Some(old_parent) = self.nodes.get_mut(old_parent)
2088 {
2089 old_parent.to.shift_remove(id);
2090 }
2091 }
2092
2093 for new_parent in &new_parents {
2094 if !old_parents.contains(new_parent)
2095 && let Some(new_parent) = self.nodes.get_mut(new_parent)
2096 {
2097 new_parent.to.insert(*id);
2098 }
2099 }
2100 }
2101
2102 let node = self.nodes.get_mut(id).unwrap();
2103 node.from = new_parents;
2104
2105 if node.from.is_empty() {
2106 self.roots.insert(node.id);
2107 } else {
2108 self.roots.shift_remove(&node.id);
2109 }
2110
2111 if node.active {
2112 node.active = false;
2113 self.active.remove(id);
2114 self.update_node_activity_in_place(id, true);
2115 }
2116
2117 true
2118 }
2119}
2120
2121#[cfg(feature = "rkyv")]
2122impl<K, T, S> ArchivedIndependentNode<K, T, S>
2123where
2124 K: Archive + Hash + Copy + Eq + Ord,
2125 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2126 T: Archive + IndependentContents,
2127 S: BuildHasher + Default + Clone,
2128{
2129 #[inline]
2130 fn validate(&self) -> bool {
2131 (if self.from.len() <= self.to.len() {
2132 self.from.iter().all(|v| !self.to.contains(v))
2133 } else {
2134 self.to.iter().all(|v| !self.from.contains(v))
2135 }) && !self.from.contains(&self.id)
2136 && !self.to.contains(&self.id)
2137 }
2138}
2139
2140#[cfg(feature = "rkyv")]
2141impl<K, T, S> Node<K::Archived, T::Archived> for ArchivedIndependentNode<K, T, S>
2142where
2143 K: Archive + Hash + Copy + Eq + Ord,
2144 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2145 T: Archive + IndependentContents,
2146 S: BuildHasher + Default + Clone,
2147{
2148 type From = ArchivedIndexSet<K::Archived>;
2149 type To = ArchivedIndexSet<K::Archived>;
2150
2151 #[inline]
2152 fn id(&self) -> K::Archived {
2153 self.id
2154 }
2155 #[inline]
2156 fn from(&self) -> &Self::From {
2157 &self.from
2158 }
2159 #[inline]
2160 fn to(&self) -> &Self::To {
2161 &self.to
2162 }
2163 #[inline]
2164 fn is_active(&self) -> bool {
2165 self.active
2166 }
2167 #[inline]
2168 fn contents(&self) -> &T::Archived {
2169 &self.contents
2170 }
2171}
2172
2173#[cfg(feature = "rkyv")]
2174impl<K, T, M, S> ArchivedIndependentWeave<K, T, M, S>
2175where
2176 K: Archive + Hash + Copy + Eq + Ord,
2177 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2178 T: Archive + IndependentContents,
2179 M: Archive,
2180 S: BuildHasher + Default + Clone,
2181{
2182 fn validate(&self) -> bool {
2183 self.roots
2184 .iter()
2185 .all(move |value| self.nodes.contains_key(value))
2186 && self
2187 .active
2188 .iter()
2189 .all(move |value| self.nodes.contains_key(value))
2190 && self
2191 .bookmarked
2192 .iter()
2193 .all(move |value| self.nodes.contains_key(value))
2194 && self.nodes.iter().all(|(key, value)| {
2195 value.validate()
2196 && value.id == *key
2197 && value
2198 .from
2199 .iter()
2200 .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
2201 && value
2202 .to
2203 .iter()
2204 .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
2205 && value.from.is_empty() == self.roots.contains(key)
2206 && value.active == self.active.contains(key)
2207 && value.bookmarked == self.bookmarked.contains(key)
2208 })
2209 && archived_valid_topology(&self.nodes, &self.roots, &self.active)
2210 }
2211}
2212
2213#[cfg(feature = "rkyv")]
2214unsafe impl<K, T, M, S, C> Verify<C> for ArchivedIndependentWeave<K, T, M, S>
2217where
2218 K: Archive + Hash + Copy + Eq + Ord,
2219 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2220 T: Archive + IndependentContents,
2221 M: Archive,
2222 S: BuildHasher + Default + Clone,
2223 C: Fallible + ?Sized,
2224 C::Error: Source,
2225{
2226 fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
2227 if !self.validate() {
2228 fail!(ValidationError)
2229 }
2230
2231 Ok(())
2232 }
2233}
2234
2235#[cfg(feature = "rkyv")]
2236impl<K, T, M, S> ImmutableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2237 for ArchivedIndependentWeave<K, T, M, S>
2238where
2239 K: Archive + Hash + Copy + Eq + Ord,
2240 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2241 T: Archive + IndependentContents,
2242 M: Archive,
2243 S: BuildHasher + Default + Clone,
2244{
2245 type Nodes = ArchivedHashMap<K::Archived, ArchivedIndependentNode<K, T, S>>;
2246 type Roots = ArchivedIndexSet<K::Archived>;
2247
2248 #[inline]
2249 fn len(&self) -> usize {
2250 self.nodes.len()
2251 }
2252 #[inline]
2253 fn is_empty(&self) -> bool {
2254 self.nodes.is_empty()
2255 }
2256 #[inline]
2257 fn nodes(&self) -> &Self::Nodes {
2258 &self.nodes
2259 }
2260 #[inline]
2261 fn roots(&self) -> &Self::Roots {
2262 &self.roots
2263 }
2264 #[inline]
2265 fn contains(&self, id: &K::Archived) -> bool {
2266 self.nodes.contains_key(id)
2267 }
2268 #[inline]
2269 fn contains_active(&self, id: &K::Archived) -> bool {
2270 self.active.contains(id)
2271 }
2272 #[inline]
2273 fn get(&self, id: &K::Archived) -> Option<&ArchivedIndependentNode<K, T, S>> {
2274 self.nodes.get(id)
2275 }
2276 #[inline]
2277 fn get_parents(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
2278 self.nodes.get(id).map(|node| &node.from)
2279 }
2280 #[inline]
2281 fn get_children(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
2282 self.nodes.get(id).map(|node| &node.to)
2283 }
2284 #[inline]
2285 fn get_contents(&self, id: &K::Archived) -> Option<&T::Archived> {
2286 self.nodes.get(id).map(|node| &node.contents)
2287 }
2288 fn get_ordered_identifiers(&self, output: &mut Vec<K::Archived>) {
2289 output.clear();
2290 output.reserve(self.nodes.len());
2291
2292 let mut scratchpad = Scratchpad::new();
2293 let guard = scratchpad.guard();
2294
2295 archived_topological_sort(
2296 &self.nodes,
2297 &self.roots,
2298 &mut guard.vec_with_capacity(self.roots.len()),
2299 |id| output.push(id),
2300 &mut guard
2301 .map_with_capacity(self.nodes.len().strict_sub(self.roots.len()), S::default()),
2302 );
2303 }
2304 fn get_ordered_identifiers_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2305 output.clear();
2306
2307 if self.nodes.contains_key(id) {
2308 let mut scratchpad = Scratchpad::new();
2309 let guard = scratchpad.guard();
2310
2311 let mut stack = guard.vec();
2312 let mut descendants = guard.set(S::default());
2313
2314 archived_descendant_subgraph(&self.nodes, *id, &mut stack, &mut descendants);
2315
2316 output.reserve(descendants.len());
2317
2318 archived_topological_sort_subgraph(
2319 &self.nodes,
2320 |id| descendants.contains(id),
2321 *id,
2322 &mut stack,
2323 |id| output.push(id),
2324 &mut guard.map_with_capacity(descendants.len(), S::default()),
2325 );
2326 }
2327 }
2328 fn get_active_path(&self, output: &mut Vec<K::Archived>) {
2329 output.clear();
2330
2331 if self.active.is_empty() {
2332 return;
2333 }
2334
2335 output.reserve(self.active.len());
2336
2337 let mut scratchpad = Scratchpad::new();
2338 let guard = scratchpad.guard();
2339
2340 let mut stack = guard.vec();
2341 let mut topological_subgraph = guard.vec_with_capacity(self.active.len());
2342 let mut scratchpad_map = guard.map_with_capacity(self.active.len(), S::default());
2343
2344 for root in self
2345 .roots
2346 .iter()
2347 .filter(|id| self.active.contains(*id))
2348 .copied()
2349 {
2350 archived_topological_sort_subgraph(
2351 &self.nodes,
2352 |id| self.active.contains(id),
2353 root,
2354 &mut stack,
2355 |id| topological_subgraph.push(id),
2356 &mut scratchpad_map,
2357 );
2358 }
2359
2360 scratchpad_map.clear();
2361
2362 archived_longest_candidate_path_to_root(
2363 &self.nodes,
2364 &topological_subgraph,
2365 |id| self.active.contains(id),
2366 &mut scratchpad_map,
2367 |id| output.push(id),
2368 );
2369 }
2370 fn get_path_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2371 output.clear();
2372 if !self.nodes.contains_key(id) {
2373 return;
2374 }
2375
2376 let mut scratchpad = Scratchpad::new();
2377 let guard = scratchpad.guard();
2378 let mut stack = guard.vec();
2379 let mut ancestors = guard.set(S::default());
2380 let mut root_ancestors = guard.vec();
2381
2382 archived_ancestor_subgraph(&self.nodes, *id, &mut stack, &mut ancestors, |id| {
2383 root_ancestors.push(id);
2384 });
2385
2386 let mut active_topological_subgraph =
2387 guard.vec_with_capacity(self.active.len().min(ancestors.len()));
2388 let mut scratchpad_map =
2389 guard.map_with_capacity(self.active.len().min(ancestors.len()), S::default());
2390
2391 for root in root_ancestors
2392 .drain(..)
2393 .filter(|id| self.active.contains(id))
2394 {
2395 archived_topological_sort_subgraph(
2396 &self.nodes,
2397 |id| self.active.contains(id) && ancestors.contains(id),
2398 root,
2399 &mut stack,
2400 |id| active_topological_subgraph.push(id),
2401 &mut scratchpad_map,
2402 );
2403 }
2404
2405 scratchpad_map.clear();
2406
2407 let mut reversed_path = guard.vec();
2408
2409 archived_longest_candidate_path_to_root(
2410 &self.nodes,
2411 &active_topological_subgraph,
2412 |id| self.active.contains(id) && ancestors.contains(id),
2413 &mut scratchpad_map,
2414 |id| reversed_path.push(id),
2415 );
2416
2417 let mut scratchpad_map_2 = guard.map_with_capacity(ancestors.len(), S::default());
2418
2419 ancestors.clear();
2420 let mut scratchpad_set = ancestors;
2421
2422 if let Some(target) = reversed_path.first().copied() {
2423 archived_shortest_path_to_ancestor(
2424 &self.nodes,
2425 id,
2426 |node| node.id == target,
2427 &mut stack,
2428 &mut scratchpad_map_2,
2429 &mut scratchpad_set,
2430 output,
2431 );
2432
2433 output.reverse();
2434 output.pop();
2435 output.extend_from_slice(&reversed_path);
2436 } else {
2437 archived_shortest_path_to_ancestor(
2438 &self.nodes,
2439 id,
2440 |node| node.from.is_empty(),
2441 &mut stack,
2442 &mut scratchpad_map_2,
2443 &mut scratchpad_set,
2444 output,
2445 );
2446
2447 output.reverse();
2448 }
2449 }
2450}
2451
2452#[cfg(feature = "rkyv")]
2453impl<K, T, M, S>
2454 ImmutableMetadataWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived, M::Archived>
2455 for ArchivedIndependentWeave<K, T, M, S>
2456where
2457 K: Archive + Hash + Copy + Eq + Ord,
2458 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2459 T: Archive + IndependentContents,
2460 M: Archive,
2461 S: BuildHasher + Default + Clone,
2462{
2463 #[inline]
2464 fn metadata(&self) -> &M::Archived {
2465 &self.metadata
2466 }
2467}
2468
2469#[cfg(feature = "rkyv")]
2470impl<K, T, M, S>
2471 ImmutableBookmarkableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2472 for ArchivedIndependentWeave<K, T, M, S>
2473where
2474 K: Archive + Hash + Copy + Eq + Ord,
2475 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2476 T: Archive + IndependentContents,
2477 M: Archive,
2478 S: BuildHasher + Default + Clone,
2479{
2480 type Bookmarks = ArchivedIndexSet<K::Archived>;
2481
2482 #[inline]
2483 fn bookmarks(&self) -> &Self::Bookmarks {
2484 &self.bookmarked
2485 }
2486 #[inline]
2487 fn contains_bookmark(&self, id: &K::Archived) -> bool {
2488 self.bookmarked.contains(id)
2489 }
2490}
2491
2492#[cfg(feature = "rkyv")]
2493impl<K, T, M, S>
2494 ImmutableActivePathWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2495 for ArchivedIndependentWeave<K, T, M, S>
2496where
2497 K: Archive + Hash + Copy + Eq + Ord,
2498 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2499 T: Archive + IndependentContents,
2500 M: Archive,
2501 S: BuildHasher + Default + Clone,
2502{
2503 type Active = ArchivedHashSet<K::Archived>;
2504
2505 #[inline]
2506 fn active(&self) -> &Self::Active {
2507 &self.active
2508 }
2509}