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