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