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 if let Some(node) = self.nodes.get_mut(id) {
544 if node.active == value {
545 return true;
546 }
547
548 node.active = value;
549 if value {
550 self.active.insert(node.id);
551 } else {
552 self.active.remove(id);
553 }
554 } else {
555 return false;
556 }
557
558 if value {
559 for root in &self.roots {
560 topological_sort(
561 &self.nodes,
562 root,
563 &mut self.scratchpad_stack,
564 &mut self.scratchpad_list, &mut self.scratchpad_set,
566 &mut self.scratchpad_map,
567 );
568 }
569
570 self.scratchpad_set.clear();
571 self.scratchpad_map.clear();
572
573 for id in self.scratchpad_list.iter().copied() {
574 let node = &self.nodes[&id];
575
576 let best_parent = node
577 .from
578 .iter()
579 .map(|id| (id, self.scratchpad_map_3[id])) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
581
582 let (parent, score) = if let Some((parent, mut score)) = best_parent {
583 if node.active {
584 score.1 = score.1.strict_add(1);
585 } else {
586 score.0 = score.0.strict_add(1);
587 }
588
589 (Some(parent), score)
590 } else {
591 (None, if node.active { (0, 1) } else { (1, 0) })
592 };
593
594 if let Some(parent) = parent {
595 self.scratchpad_map_2.insert(id, *parent); }
597
598 self.scratchpad_map_3.insert(id, score);
599 }
600
601 let mut current = Some(id);
602
603 while let Some(id) = current {
604 self.scratchpad_set.insert(*id);
605 current = self.scratchpad_map_2.get(id);
606 }
607
608 self.scratchpad_map_2.clear();
609 self.scratchpad_map_3.clear();
610
611 for id in self.scratchpad_list.drain(..).rev() {
612 let node = &self.nodes[&id];
613
614 let best_child = node
615 .to
616 .iter()
617 .map(|id| (id, self.scratchpad_map_3[id])) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
619
620 let (child, score) = if let Some((child, mut score)) = best_child {
621 if node.active {
622 score.1 = score.1.strict_add(1);
623 } else {
624 score.0 = score.0.strict_add(1);
625 }
626
627 (Some(child), score)
628 } else {
629 (None, if node.active { (0, 1) } else { (1, 0) })
630 };
631
632 if let Some(child) = child {
633 self.scratchpad_map_2.insert(id, *child); }
635
636 self.scratchpad_map_3.insert(id, score);
637 }
638
639 let mut current = Some(id);
640
641 while let Some(id) = current {
642 self.scratchpad_set.insert(*id);
643
644 current = if self.scratchpad_map_3[id].1 > usize::from(self.nodes[id].active) {
645 self.scratchpad_map_2.get(id)
646 } else {
647 None
648 };
649 }
650
651 self.scratchpad_map_2.clear();
652 self.scratchpad_map_3.clear();
653
654 self.scratchpad_list
655 .extend(self.active.difference(&self.scratchpad_set).copied());
656
657 for id in self.scratchpad_list.drain(..) {
658 self.nodes.get_mut(&id).unwrap().active = false;
659 self.active.remove(&id);
660 }
661
662 self.scratchpad_list
663 .extend(self.scratchpad_set.difference(&self.active).copied());
664
665 self.scratchpad_set.clear();
666
667 for id in self.scratchpad_list.drain(..) {
668 self.nodes.get_mut(&id).unwrap().active = true;
669 self.active.insert(id);
670 }
671 } else {
672 self.fix_orphaned_activations();
673 }
674
675 true
676 }
677 #[cfg_attr(debug_assertions, contract(
678 requires(self.validate_scratchpads()),
679 ensures(self.validate())
680 ))]
681 fn fix_orphaned_activations(&mut self) {
682 for root in &self.roots {
683 topological_sort(
684 &self.nodes,
685 root,
686 &mut self.scratchpad_stack,
687 &mut self.scratchpad_list,
688 &mut self.scratchpad_set,
689 &mut self.scratchpad_map,
690 );
691 }
692
693 self.scratchpad_map.clear();
694
695 longest_candidate_path_to_root(
696 &self.nodes,
697 &self.scratchpad_list,
698 &|id| self.active.contains(id),
699 &mut self.scratchpad_map,
700 &mut self.scratchpad_list_2,
701 );
702
703 self.scratchpad_list.clear();
704 self.scratchpad_set.clear();
705 self.scratchpad_map.clear();
706
707 self.scratchpad_set.extend(self.scratchpad_list_2.drain(..));
708 self.scratchpad_list
709 .extend(self.active.difference(&self.scratchpad_set).copied());
710
711 self.scratchpad_set.clear();
712
713 for orphan in self.scratchpad_list.drain(..) {
714 self.active.remove(&orphan);
715 if let Some(node) = self.nodes.get_mut(&orphan) {
716 node.active = false;
717 }
718 }
719 }
720 #[cfg_attr(debug_assertions, contract(
721 ensures(!ret || value || !self.active.contains(id) || (old(self.active.clone()) == self.active && self.nodes[id].to.iter().any(|id| self.contains_active(id)))),
722 ensures(!ret || !value || self.contains_active(id) && !self.nodes[id].to.iter().any(|id| self.active.contains(id))),
723 ensures(ret || old(self.active.clone()) == self.active),
724 ensures(ret == self.nodes.contains_key(id)),
725 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
726 ensures(old(self.roots.clone()) == self.roots),
727 ensures(old(self.bookmarked.clone()) == self.bookmarked),
728 invariant(self.validate())
729 ))]
730 #[allow(clippy::missing_panics_doc, reason = "Should never panic")]
731 pub fn set_active_dependent_semantics(&mut self, id: &K, value: bool) -> bool {
733 if value {
734 if let Some(node) = self.nodes.get(id) {
735 if node.active && !node.to.iter().any(|id| self.active.contains(id)) {
736 return true;
737 }
738 } else {
739 return false;
740 }
741
742 for root in &self.roots {
743 topological_sort(
744 &self.nodes,
745 root,
746 &mut self.scratchpad_stack,
747 &mut self.scratchpad_list, &mut self.scratchpad_set,
749 &mut self.scratchpad_map,
750 );
751 }
752
753 self.scratchpad_set.clear();
754 self.scratchpad_map.clear();
755
756 for id in self.scratchpad_list.drain(..) {
757 let node = &self.nodes[&id];
758
759 let best_parent = node
760 .from
761 .iter()
762 .map(|id| (id, self.scratchpad_map_3[id])) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
764
765 let (parent, score) = if let Some((parent, mut score)) = best_parent {
766 if node.active {
767 score.1 = score.1.strict_add(1);
768 } else {
769 score.0 = score.0.strict_add(1);
770 }
771
772 (Some(parent), score)
773 } else {
774 (None, if node.active { (0, 1) } else { (1, 0) })
775 };
776
777 if let Some(parent) = parent {
778 self.scratchpad_map_2.insert(id, *parent); }
780
781 self.scratchpad_map_3.insert(id, score);
782 }
783
784 let mut current = Some(id);
785
786 while let Some(id) = current {
787 self.scratchpad_set.insert(*id);
788 current = self.scratchpad_map_2.get(id);
789 }
790
791 self.scratchpad_map_2.clear();
792 self.scratchpad_map_3.clear();
793
794 self.scratchpad_list
795 .extend(self.active.difference(&self.scratchpad_set).copied());
796
797 for id in self.scratchpad_list.drain(..) {
798 self.nodes.get_mut(&id).unwrap().active = false;
799 self.active.remove(&id);
800 }
801
802 self.scratchpad_list
803 .extend(self.scratchpad_set.difference(&self.active).copied());
804
805 self.scratchpad_set.clear();
806
807 for id in self.scratchpad_list.drain(..) {
808 self.nodes.get_mut(&id).unwrap().active = true;
809 self.active.insert(id);
810 }
811 } else if let Some(node) = self.nodes.get_mut(id) {
812 if !node.active || node.to.iter().any(|id| self.active.contains(id)) {
813 return true;
814 }
815
816 node.active = false;
817 self.active.remove(&node.id);
818 } else {
819 return false;
820 }
821
822 true
823 }
824}
825
826impl<K, T, M, S> From<DependentWeave<K, T, M, S>> for IndependentWeave<K, T, M, S>
827where
828 K: Hash + Copy + Eq + Ord,
829 T: IndependentContents,
830 S: BuildHasher + Default + Clone,
831{
832 fn from(value: DependentWeave<K, T, M, S>) -> Self {
833 let mut output = Self {
834 active: HashSet::with_capacity_and_hasher(value.nodes.capacity(), S::default()),
835 scratchpad_list: Vec::with_capacity(value.nodes.capacity()),
836 scratchpad_list_2: Vec::with_capacity(value.nodes.capacity()),
837 scratchpad_set: HashSet::with_capacity_and_hasher(value.nodes.capacity(), S::default()),
838 scratchpad_set_2: HashSet::with_capacity_and_hasher(
839 value.nodes.capacity(),
840 S::default(),
841 ),
842 scratchpad_map: HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default()),
843 scratchpad_map_2: HashMap::with_capacity_and_hasher(
844 value.nodes.capacity(),
845 S::default(),
846 ),
847 scratchpad_map_3: HashMap::with_capacity_and_hasher(
848 value.nodes.capacity(),
849 S::default(),
850 ),
851 scratchpad_stack: Vec::with_capacity(value.nodes.capacity()),
852 scratchpad_queue: VecDeque::with_capacity(value.nodes.capacity()),
853 nodes: {
854 let mut map =
855 HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default());
856 map.extend(value.nodes.into_iter().map(|(id, mut node)| {
857 node.active = false;
858 (id, node.into())
859 }));
860
861 map
862 },
863 roots: value.roots,
864 bookmarked: value.bookmarked,
865 metadata: value.metadata,
866 };
867
868 if let Some(active) = value.active {
869 output.set_active(&active, true);
870 }
871
872 debug_assert!(output.validate(), "Converted weave is malformed");
873
874 output
875 }
876}
877
878#[allow(clippy::panic_in_result_fn, reason = "Should never panic")]
879#[allow(clippy::unreachable, reason = "Should never panic")]
880impl<K, T, M, S> TryFrom<IndependentWeave<K, T, M, S>> for DependentWeave<K, T, M, S>
881where
882 K: Hash + Copy + Eq + Ord,
883 T: IndependentContents,
884 S: BuildHasher + Default + Clone,
885{
886 type Error = IndependentWeave<K, T, M, S>;
887
888 fn try_from(value: IndependentWeave<K, T, M, S>) -> Result<Self, Self::Error> {
889 if value.nodes.iter().all(|(_, node)| node.from.len() < 2) {
890 let mut active = None;
891
892 let output = Self {
893 nodes: {
894 let mut map =
895 HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default());
896 map.extend(value.nodes.into_iter().map(|(id, mut node)| {
897 node.active =
898 node.active && !node.to.iter().any(|id| value.active.contains(id));
899 if node.active {
900 active = Some(id);
901 }
902
903 node.try_into()
904 .map_or_else(|_| unreachable!(), |node| (id, node))
905 }));
906
907 map
908 },
909 roots: value.roots,
910 active,
911 bookmarked: value.bookmarked,
912 scratchpad: value.scratchpad_stack,
913 metadata: value.metadata,
914 };
915
916 debug_assert!(output.validate(), "Converted weave is malformed");
917
918 Ok(output)
919 } else {
920 Err(value)
921 }
922 }
923}
924
925impl<K, T, M, S> Weave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
926where
927 K: Hash + Copy + Eq + Ord,
928 T: IndependentContents,
929 S: BuildHasher + Default + Clone,
930{
931 type Nodes = HashMap<K, IndependentNode<K, T, S>, S>;
932 type Roots = IndexSet<K, S>;
933
934 #[inline]
935 fn len(&self) -> usize {
936 self.nodes.len()
937 }
938 #[inline]
939 fn is_empty(&self) -> bool {
940 self.nodes.is_empty()
941 }
942 #[inline]
943 fn nodes(&self) -> &Self::Nodes {
944 &self.nodes
945 }
946 #[inline]
947 fn roots(&self) -> &Self::Roots {
948 &self.roots
949 }
950 #[inline]
951 fn contains(&self, id: &K) -> bool {
952 self.nodes.contains_key(id)
953 }
954 #[inline]
955 fn contains_active(&self, id: &K) -> bool {
956 self.active.contains(id)
957 }
958 #[inline]
959 fn get(&self, id: &K) -> Option<&IndependentNode<K, T, S>> {
960 self.nodes.get(id)
961 }
962 #[inline]
963 fn get_parents(&self, id: &K) -> Option<&IndexSet<K, S>> {
964 self.nodes.get(id).map(|node| &node.from)
965 }
966 #[inline]
967 fn get_children(&self, id: &K) -> Option<&IndexSet<K, S>> {
968 self.nodes.get(id).map(|node| &node.to)
969 }
970 #[inline]
971 fn get_contents(&self, id: &K) -> Option<&T> {
972 self.nodes.get(id).map(|node| &node.contents)
973 }
974 #[cfg_attr(debug_assertions, contract(
975 ensures(output.len() == self.nodes.len()),
976 ensures(valid_topological_sort(&self.nodes, output)),
977 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
978 ensures(old(self.roots.clone()) == self.roots),
979 ensures(old(self.active.clone()) == self.active),
980 ensures(old(self.bookmarked.clone()) == self.bookmarked),
981 invariant(self.validate())
982 ))]
983 fn get_ordered_identifiers(&mut self, output: &mut Vec<K>) {
984 output.clear();
985
986 for root in &self.roots {
987 topological_sort(
988 &self.nodes,
989 root,
990 &mut self.scratchpad_stack,
991 output,
992 &mut self.scratchpad_set,
993 &mut self.scratchpad_map,
994 );
995 }
996
997 self.scratchpad_set.clear();
998 self.scratchpad_map.clear();
999 }
1000 #[cfg_attr(debug_assertions, contract(
1001 ensures(lacks_duplicates(output)),
1002 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1003 ensures(self.nodes.contains_key(id) || output.is_empty()),
1004 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1005 ensures(old(self.roots.clone()) == self.roots),
1006 ensures(old(self.active.clone()) == self.active),
1007 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1008 invariant(self.validate())
1009 ))]
1010 fn get_ordered_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
1011 output.clear();
1012
1013 if self.nodes.contains_key(id) {
1014 descendant_subgraph(
1015 &self.nodes,
1016 *id,
1017 &mut self.scratchpad_stack,
1018 &mut self.scratchpad_set,
1019 );
1020
1021 topological_sort_subgraph(
1022 &self.nodes,
1023 &|id| self.scratchpad_set.contains(id),
1024 id,
1025 &mut self.scratchpad_stack,
1026 output,
1027 &mut self.scratchpad_set_2,
1028 &mut self.scratchpad_map,
1029 );
1030
1031 self.scratchpad_set.clear();
1032 self.scratchpad_set_2.clear();
1033 self.scratchpad_map.clear();
1034 }
1035 }
1036 #[cfg_attr(debug_assertions, contract(
1037 ensures(output.len() == self.active.len()),
1038 ensures(output.iter().all(|i| self.active.contains(i))),
1039 ensures(lacks_duplicates(output)),
1040 ensures(valid_path(&self.nodes, output)),
1041 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1042 ensures(old(self.roots.clone()) == self.roots),
1043 ensures(old(self.active.clone()) == self.active),
1044 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1045 invariant(self.validate())
1046 ))]
1047 fn get_active_path(&mut self, output: &mut Vec<K>) {
1048 output.clear();
1049
1050 for root in &self.roots {
1051 topological_sort_subgraph(
1052 &self.nodes,
1053 &|id| self.active.contains(id),
1054 root,
1055 &mut self.scratchpad_stack,
1056 &mut self.scratchpad_list,
1057 &mut self.scratchpad_set,
1058 &mut self.scratchpad_map,
1059 );
1060 }
1061
1062 self.scratchpad_set.clear();
1063 self.scratchpad_map.clear();
1064
1065 longest_candidate_path_to_root(
1066 &self.nodes,
1067 &self.scratchpad_list,
1068 &|id| self.active.contains(id),
1069 &mut self.scratchpad_map,
1070 output,
1071 );
1072
1073 self.scratchpad_list.clear();
1074 self.scratchpad_map.clear();
1075 }
1076 #[cfg_attr(debug_assertions, contract(
1077 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1078 ensures(self.nodes.contains_key(id) || output.is_empty()),
1079 ensures(lacks_duplicates(output)),
1080 ensures(valid_path(&self.nodes, output)),
1081 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1082 ensures(old(self.roots.clone()) == self.roots),
1083 ensures(old(self.active.clone()) == self.active),
1084 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1085 invariant(self.validate())
1086 ))]
1087 fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
1088 output.clear();
1089 if !self.nodes.contains_key(id) {
1090 return;
1091 }
1092
1093 ancestor_subgraph(
1094 &self.nodes,
1095 *id,
1096 &mut self.scratchpad_stack,
1097 &mut self.scratchpad_set,
1098 );
1099
1100 for root in &self.roots {
1101 topological_sort_subgraph(
1102 &self.nodes,
1103 &|id| self.active.contains(id),
1104 root,
1105 &mut self.scratchpad_stack,
1106 &mut self.scratchpad_list,
1107 &mut self.scratchpad_set_2,
1108 &mut self.scratchpad_map,
1109 );
1110 }
1111
1112 self.scratchpad_map.clear();
1113
1114 longest_candidate_path_to_root(
1115 &self.nodes,
1116 &self.scratchpad_list,
1117 &|id| self.active.contains(id) && self.scratchpad_set.contains(id),
1118 &mut self.scratchpad_map,
1119 &mut self.scratchpad_list_2,
1120 );
1121
1122 self.scratchpad_list.clear();
1123 self.scratchpad_set.clear();
1124 self.scratchpad_set_2.clear();
1125 self.scratchpad_map.clear();
1126 self.scratchpad_map_2.clear();
1127
1128 if let Some(target) = self.scratchpad_list_2.first().copied() {
1129 shortest_path_to_ancestor(
1130 &self.nodes,
1131 id,
1132 &|node| node.id == target,
1133 &mut self.scratchpad_queue,
1134 &mut self.scratchpad_map_2,
1135 &mut self.scratchpad_set_2,
1136 output,
1137 );
1138
1139 output.reverse();
1140 output.pop();
1141 output.append(&mut self.scratchpad_list_2);
1142 } else {
1143 shortest_path_to_ancestor(
1144 &self.nodes,
1145 id,
1146 &|node| node.from.is_empty(),
1147 &mut self.scratchpad_queue,
1148 &mut self.scratchpad_map_2,
1149 &mut self.scratchpad_set_2,
1150 output,
1151 );
1152
1153 output.reverse();
1154 }
1155
1156 self.scratchpad_set_2.clear();
1157 self.scratchpad_map_2.clear();
1158 }
1159 #[cfg_attr(debug_assertions, contract(
1160 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1161 ensures(!ret || old(!self.nodes.contains_key(&node.id))),
1162 ensures(!ret || self.nodes.contains_key(&old(node.id))),
1163 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))))),
1164 ensures(!ret || old(node.bookmarked) == self.bookmarked.contains(&old(node.id))),
1165 ensures(!ret || old(!node.from.is_empty()) || self.roots.contains(&old(node.id))),
1166 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1167 ensures(ret || old(self.roots.clone()) == self.roots),
1168 ensures(ret || old(self.active.clone()) == self.active),
1169 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1170 invariant(self.validate())
1171 ))]
1172 fn insert(&mut self, mut node: IndependentNode<K, T, S>) -> bool {
1173 if self.nodes.contains_key(&node.id)
1174 || !node.validate()
1175 || !node.from.iter().all(|id| self.nodes.contains_key(id))
1176 || !node.to.iter().all(|id| self.nodes.contains_key(id))
1177 {
1178 return false;
1179 }
1180
1181 if !node.to.is_empty() && !node.from.is_empty() {
1182 for parent in node.from.iter().copied() {
1183 ancestor_subgraph(
1184 &self.nodes,
1185 parent,
1186 &mut self.scratchpad_stack,
1187 &mut self.scratchpad_set,
1188 );
1189 }
1190
1191 if node
1192 .to
1193 .iter()
1194 .any(|child| self.scratchpad_set.contains(child))
1195 {
1196 self.scratchpad_set.clear();
1197 return false;
1198 }
1199
1200 self.scratchpad_set.clear();
1201 }
1202
1203 let root_index = if node.from.is_empty() {
1204 node.to
1205 .iter()
1206 .filter_map(|child| self.roots.get_index_of(child))
1207 .min()
1208 } else {
1209 None
1210 };
1211
1212 for child in &node.to {
1213 let child = &self.nodes[child];
1214 if child.from.is_empty() {
1215 if child.active {
1216 node.active = true;
1217 }
1218 self.roots.shift_remove(&child.id);
1219 }
1220 }
1221
1222 let extends_active = node.active
1223 && node.to.is_empty()
1224 && node.from.iter().map(|id| &self.nodes[id]).any(|parent| {
1225 parent.active && parent.to.iter().all(|child| !self.active.contains(child))
1226 });
1227
1228 if node.from.is_empty() {
1229 if let Some(index) = root_index {
1230 self.roots.shift_insert(index, node.id);
1231 } else {
1232 self.roots.insert(node.id);
1233 }
1234 } else {
1235 for parent in &node.from {
1236 let parent = self.nodes.get_mut(parent).unwrap();
1237 parent.to.insert(node.id);
1238 }
1239 }
1240
1241 for child in &node.to {
1242 let child = self.nodes.get_mut(child).unwrap();
1243 child.from.insert(node.id);
1244 }
1245
1246 if node.bookmarked {
1247 self.bookmarked.insert(node.id);
1248 }
1249
1250 let id = node.id;
1251 let active = node.active;
1252
1253 if !extends_active {
1254 node.active = false;
1255 }
1256
1257 self.nodes.insert(node.id, node);
1258
1259 if extends_active {
1260 self.active.insert(id);
1261 } else if active {
1262 self.update_node_activity_in_place(&id, true);
1263 }
1264
1265 true
1266 }
1267 #[cfg_attr(debug_assertions, contract(
1268 ensures(!ret || value == self.contains_active(id)),
1269 ensures(ret || old(self.active.clone()) == self.active),
1270 ensures(ret == self.nodes.contains_key(id)),
1271 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1272 ensures(old(self.roots.clone()) == self.roots),
1273 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1274 invariant(self.validate())
1275 ))]
1276 fn set_active(&mut self, id: &K, value: bool) -> bool {
1277 self.update_node_activity_in_place(id, value)
1278 }
1279 #[cfg_attr(debug_assertions, contract(
1280 ensures(!self.nodes.contains_key(id)),
1281 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1282 ensures(ret.as_ref().is_none_or(|node| &node.id == id)),
1283 ensures(ret.is_none() || old(self.nodes.len()) > self.nodes.len()),
1284 ensures(ret.is_none() || old(self.active.len()) >= self.active.len()),
1285 ensures(ret.is_none() || old(self.bookmarked.len()) >= self.bookmarked.len()),
1286 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1287 ensures(ret.is_some() || old(self.roots.clone()) == self.roots),
1288 ensures(ret.is_some() || old(self.active.clone()) == self.active),
1289 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1290 invariant(self.validate())
1291 ))]
1292 fn remove(&mut self, id: &K) -> Option<IndependentNode<K, T, S>> {
1293 let mut removed_node = None;
1294 let mut removed_active = false;
1295
1296 self.scratchpad_stack.push(*id);
1297
1298 while let Some(id) = self.scratchpad_stack.pop() {
1299 if let Some(node) = self.nodes.remove(&id) {
1300 if node.from.is_empty() {
1301 self.roots.shift_remove(&id);
1302 }
1303 if node.bookmarked {
1304 self.bookmarked.shift_remove(&id);
1305 }
1306 if node.active {
1307 self.active.remove(&id);
1308 removed_active = true;
1309 }
1310
1311 for parent in &node.from {
1312 if let Some(parent) = self.nodes.get_mut(parent) {
1313 parent.to.shift_remove(&node.id);
1314 }
1315 }
1316 for child in node.to.iter().rev() {
1317 if let Some(child) = self.nodes.get_mut(child) {
1318 child.from.shift_remove(&node.id);
1319
1320 if child.from.is_empty() {
1321 self.scratchpad_stack.push(child.id);
1322 }
1323 }
1324 }
1325
1326 if removed_node.is_none() {
1327 removed_node = Some(node);
1328 }
1329 }
1330 }
1331
1332 if removed_node.is_some() {
1333 if removed_active {
1334 self.fix_orphaned_activations();
1336 }
1337 removed_node
1338 } else {
1339 None
1340 }
1341 }
1342 #[cfg_attr(debug_assertions, contract(
1343 ensures(!self.nodes.contains_key(id)),
1344 ensures(ret == old(self.nodes.contains_key(id))),
1345 ensures(!ret || old(self.nodes.len()) > self.nodes.len()),
1346 ensures(!ret || old(self.active.len()) >= self.active.len()),
1347 ensures(!ret || old(self.bookmarked.len()) >= self.bookmarked.len()),
1348 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1349 ensures(ret || old(self.roots.clone()) == self.roots),
1350 ensures(ret || old(self.active.clone()) == self.active),
1351 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1352 invariant(self.validate())
1353 ))]
1354 fn remove_tracked(
1355 &mut self,
1356 id: &K,
1357 mut on_removal: impl FnMut(IndependentNode<K, T, S>),
1358 ) -> bool {
1359 let had_node = self.nodes.contains_key(id);
1360 let mut removed_active = false;
1361
1362 self.scratchpad_stack.push(*id);
1363
1364 while let Some(id) = self.scratchpad_stack.pop() {
1365 if let Some(node) = self.nodes.remove(&id) {
1366 if node.from.is_empty() {
1367 self.roots.shift_remove(&id);
1368 }
1369 if node.bookmarked {
1370 self.bookmarked.shift_remove(&id);
1371 }
1372 if node.active {
1373 self.active.remove(&id);
1374 removed_active = true;
1375 }
1376
1377 for parent in &node.from {
1378 if let Some(parent) = self.nodes.get_mut(parent) {
1379 parent.to.shift_remove(&node.id);
1380 }
1381 }
1382 for child in node.to.iter().rev() {
1383 if let Some(child) = self.nodes.get_mut(child) {
1384 child.from.shift_remove(&node.id);
1385
1386 if child.from.is_empty() {
1387 self.scratchpad_stack.push(child.id);
1388 }
1389 }
1390 }
1391
1392 on_removal(node);
1393 }
1394 }
1395
1396 if had_node {
1397 if removed_active {
1398 self.fix_orphaned_activations();
1399 }
1400 true
1401 } else {
1402 false
1403 }
1404 }
1405 #[cfg_attr(debug_assertions, contract(
1406 ensures(self.nodes.is_empty()),
1407 ensures(self.validate())
1408 ))]
1409 fn clear(&mut self) {
1410 self.nodes.clear();
1411 self.roots.clear();
1412 self.active.clear();
1413 self.bookmarked.clear();
1414 }
1415}
1416
1417impl<K, T, M, S> IndependentWeave<K, T, M, S>
1418where
1419 K: Hash + Copy + Eq + Ord,
1420 T: IndependentContents,
1421 S: BuildHasher + Default + Clone,
1422{
1423 pub fn validate(&self) -> bool {
1425 let mut scratchpad = Vec::with_capacity(self.nodes.len());
1426 let mut scratchpad_map = HashMap::with_capacity_and_hasher(self.nodes.len(), S::default());
1427
1428 self.validate_scratchpads()
1429 && self
1430 .roots
1431 .iter()
1432 .all(move |value| self.nodes.contains_key(value))
1433 && self
1434 .active
1435 .iter()
1436 .all(move |value| self.nodes.contains_key(value))
1437 && self
1438 .bookmarked
1439 .iter()
1440 .all(move |value| self.nodes.contains_key(value))
1441 && self.nodes.iter().all(|(key, value)| {
1442 value.validate()
1443 && value.id == *key
1444 && value
1445 .from
1446 .iter()
1447 .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
1448 && value
1449 .to
1450 .iter()
1451 .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
1452 && value.from.is_empty() == self.roots.contains(key)
1453 && value.active == self.active.contains(key)
1454 && value.bookmarked == self.bookmarked.contains(key)
1455 })
1456 && !detect_cycles(
1457 &self.nodes,
1458 self.roots.iter().copied(),
1459 &mut scratchpad,
1460 &mut scratchpad_map,
1461 )
1462 && active_path_is_valid(&self.nodes, self.roots.iter(), &self.active)
1463 }
1464 fn validate_scratchpads(&self) -> bool {
1465 self.scratchpad_list.is_empty()
1466 && self.scratchpad_list_2.is_empty()
1467 && self.scratchpad_set.is_empty()
1468 && self.scratchpad_set_2.is_empty()
1469 && self.scratchpad_map.is_empty()
1470 && self.scratchpad_map_2.is_empty()
1471 && self.scratchpad_map_3.is_empty()
1472 && self.scratchpad_stack.is_empty()
1473 && self.scratchpad_queue.is_empty()
1474 }
1475}
1476
1477impl<K, T, M, S> MetadataWeave<K, IndependentNode<K, T, S>, T, M> for IndependentWeave<K, T, M, S>
1478where
1479 K: Hash + Copy + Eq + Ord,
1480 T: IndependentContents,
1481 S: BuildHasher + Default + Clone,
1482{
1483 #[inline]
1484 fn metadata(&self) -> &M {
1485 &self.metadata
1486 }
1487 #[cfg_attr(debug_assertions, contract(
1488 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1489 ensures(old(self.roots.clone()) == self.roots),
1490 ensures(old(self.active.clone()) == self.active),
1491 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1492 invariant(self.validate())
1493 ))]
1494 #[inline]
1495 fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
1496 callback(&mut self.metadata)
1497 }
1498}
1499
1500impl<K, T, M, S> BookmarkableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1501where
1502 K: Hash + Copy + Eq + Ord,
1503 T: IndependentContents,
1504 S: BuildHasher + Default + Clone,
1505{
1506 type Bookmarks = IndexSet<K, S>;
1507
1508 #[inline]
1509 fn bookmarks(&self) -> &Self::Bookmarks {
1510 &self.bookmarked
1511 }
1512 #[inline]
1513 fn contains_bookmark(&self, id: &K) -> bool {
1514 self.bookmarked.contains(id)
1515 }
1516 #[cfg_attr(debug_assertions, contract(
1517 ensures(!ret || value == self.bookmarked.contains(id)),
1518 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1519 ensures(ret == self.nodes.contains_key(id)),
1520 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1521 ensures(old(self.roots.clone()) == self.roots),
1522 ensures(old(self.active.clone()) == self.active),
1523 invariant(self.validate())
1524 ))]
1525 fn set_bookmarked(&mut self, id: &K, value: bool) -> bool {
1526 match self.nodes.get_mut(id) {
1527 Some(node) => {
1528 node.bookmarked = value;
1529 if value {
1530 self.bookmarked.insert(node.id);
1531 } else {
1532 self.bookmarked.shift_remove(id);
1533 }
1534
1535 true
1536 }
1537 None => false,
1538 }
1539 }
1540}
1541
1542impl<K, T, M, S> SortableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1543where
1544 K: Hash + Copy + Eq + Ord,
1545 T: IndependentContents,
1546 S: BuildHasher + Default + Clone,
1547{
1548 #[cfg_attr(debug_assertions, contract(
1549 ensures(ret == self.nodes.contains_key(id)),
1550 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1551 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1552 ensures(old(self.roots.clone()) == self.roots),
1553 ensures(old(self.active.clone()) == self.active),
1554 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1555 invariant(self.validate())
1556 ))]
1557 fn sort_children_by(
1558 &mut self,
1559 id: &K,
1560 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1561 ) -> bool {
1562 if let Some(mut node) = self.nodes.remove(id) {
1563 node.to.sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1564 self.nodes.insert(node.id, node);
1565
1566 true
1567 } else {
1568 false
1569 }
1570 }
1571 #[cfg_attr(debug_assertions, contract(
1572 ensures(ret == self.nodes.contains_key(id)),
1573 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1574 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1575 ensures(old(self.roots.clone()) == self.roots),
1576 ensures(old(self.active.clone()) == self.active),
1577 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1578 invariant(self.validate())
1579 ))]
1580 fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
1581 if let Some(node) = self.nodes.get_mut(id) {
1582 node.to.sort_by(cmp);
1583
1584 true
1585 } else {
1586 false
1587 }
1588 }
1589 #[cfg_attr(debug_assertions, contract(
1590 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1591 ensures(old(self.roots.clone()) == self.roots),
1592 ensures(old(self.active.clone()) == self.active),
1593 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1594 invariant(self.validate())
1595 ))]
1596 fn sort_roots_by(
1597 &mut self,
1598 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1599 ) {
1600 self.roots
1601 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1602 }
1603 #[cfg_attr(debug_assertions, contract(
1604 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1605 ensures(old(self.roots.clone()) == self.roots),
1606 ensures(old(self.active.clone()) == self.active),
1607 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1608 invariant(self.validate())
1609 ))]
1610 fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1611 self.roots.sort_by(cmp);
1612 }
1613}
1614
1615impl<K, T, M, S> SortableBookmarkableWeave<K, IndependentNode<K, T, S>, T>
1616 for IndependentWeave<K, T, M, S>
1617where
1618 K: Hash + Copy + Eq + Ord,
1619 T: IndependentContents,
1620 S: BuildHasher + Default + Clone,
1621{
1622 #[cfg_attr(debug_assertions, contract(
1623 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1624 ensures(old(self.roots.clone()) == self.roots),
1625 ensures(old(self.active.clone()) == self.active),
1626 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1627 invariant(self.validate())
1628 ))]
1629 fn sort_bookmarks_by(
1630 &mut self,
1631 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1632 ) {
1633 self.bookmarked
1634 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1635 }
1636 #[cfg_attr(debug_assertions, contract(
1637 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1638 ensures(old(self.roots.clone()) == self.roots),
1639 ensures(old(self.active.clone()) == self.active),
1640 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1641 invariant(self.validate())
1642 ))]
1643 fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1644 self.bookmarked.sort_by(cmp);
1645 }
1646}
1647
1648impl<K, T, M, S> ActivePathWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1649where
1650 K: Hash + Copy + Eq + Ord,
1651 T: IndependentContents,
1652 S: BuildHasher + Default + Clone,
1653{
1654 type Active = HashSet<K, S>;
1655
1656 #[inline]
1657 fn active(&self) -> &Self::Active {
1658 &self.active
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.bookmarked.clone()) == self.bookmarked),
1664 invariant(self.validate())
1665 ))]
1666 fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
1667 self.active.iter().for_each(|active| {
1668 self.nodes.get_mut(active).unwrap().active = false;
1669 });
1670 self.active.clear();
1671 self.active
1672 .extend(active.filter(|id| self.nodes.contains_key(id)));
1673 self.active.iter().for_each(|active| {
1674 self.nodes.get_mut(active).unwrap().active = true;
1675 });
1676 self.fix_orphaned_activations();
1677 }
1678}
1679
1680impl<K, T, M, S> DiscreteWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1681where
1682 K: Hash + Copy + Eq + Ord,
1683 T: IndependentContents + DiscreteContents,
1684 S: BuildHasher + Default + Clone,
1685{
1686 #[cfg_attr(debug_assertions, contract(
1687 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1688 ensures(!ret || self.nodes.contains_key(id)),
1689 ensures(!ret || self.nodes.contains_key(&new_id)),
1690 ensures(!ret || old(!self.nodes.contains_key(&new_id))),
1691 ensures(!ret || self.nodes[id].to.contains(&new_id) && self.nodes[id].to.len() == 1),
1692 ensures(!ret || self.nodes[&new_id].from.contains(id) && self.nodes[&new_id].from.len() == 1),
1693 ensures(!ret || old(self.nodes.get(id).map(|n| n.to.clone())).unwrap() == self.nodes[&new_id].to),
1694 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1695 ensures(ret || old(self.active.clone()) == self.active),
1696 ensures(old(self.roots.clone()) == self.roots),
1697 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1698 invariant(self.validate())
1699 ))]
1700 fn split(&mut self, id: &K, at: usize, new_id: K) -> bool {
1701 if self.nodes.contains_key(&new_id) || *id == new_id {
1702 return false;
1703 }
1704
1705 if let Some(mut node) = self.nodes.remove(id) {
1706 match node.contents.split(at) {
1707 DiscreteContentResult::Two(left, right) => {
1708 let left_node = IndependentNode {
1709 id: node.id,
1710 from: node.from,
1711 to: IndexSet::from_iter([new_id]),
1712 active: node.active,
1713 bookmarked: node.bookmarked,
1714 contents: left,
1715 };
1716
1717 node.from = IndexSet::from_iter([node.id]);
1718 node.id = new_id;
1719 node.contents = right;
1720 node.active = false;
1721 node.bookmarked = false;
1722
1723 for child in &node.to {
1724 let child = self.nodes.get_mut(child).unwrap();
1725
1726 if let Some(index) = child.from.get_index_of(&left_node.id) {
1727 assert!(
1728 child.from.replace_index(index, node.id).is_ok(),
1729 "Should be unreachable"
1730 );
1731 } else {
1732 child.from.insert(node.id);
1733 }
1734 if child.active && left_node.active {
1735 node.active = true;
1736 self.active.insert(node.id);
1737 }
1738 }
1739
1740 self.nodes.insert(left_node.id, left_node);
1741 self.nodes.insert(node.id, node);
1742
1743 true
1744 }
1745 DiscreteContentResult::One(content) => {
1746 node.contents = content;
1747 self.nodes.insert(node.id, node);
1748 false
1749 }
1750 }
1751 } else {
1752 false
1753 }
1754 }
1755 #[cfg_attr(debug_assertions, contract(
1756 ensures(ret.is_none() || old(self.nodes.len()) - 1 == self.nodes.len()),
1757 ensures(ret.is_none() || !self.nodes.contains_key(id)),
1758 ensures(ret.is_none() || old(self.nodes.contains_key(id))),
1759 ensures(ret.is_none() || !old(self.contains_active(id)) || old(self.contains_active(id)) && self.contains_active(&ret.unwrap())),
1760 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),
1761 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),
1762 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.to.clone())).unwrap() == self.nodes[&ret.unwrap()].to),
1763 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.from.len() == 1)).unwrap()),
1764 ensures(ret.is_none() || ret.unwrap() == old(self.nodes.get(id).and_then(|node| node.from.first().copied())).unwrap()),
1765 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1766 ensures(ret.is_some() || old(self.active.clone()) == self.active),
1767 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1768 ensures(old(self.roots.clone()) == self.roots),
1769 invariant(self.validate())
1770 ))]
1771 fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1772 if let Some(mut node) = self.nodes.remove(id) {
1773 if node.from.len() != 1 {
1774 self.nodes.insert(node.id, node);
1775 return None;
1776 }
1777
1778 if let Some(mut parent) = node.from.first().and_then(|id| self.nodes.remove(id)) {
1779 if parent.to.len() > 1 {
1780 self.nodes.insert(parent.id, parent);
1781 self.nodes.insert(node.id, node);
1782 return None;
1783 }
1784
1785 match parent.contents.merge(node.contents) {
1786 DiscreteContentResult::Two(left, right) => {
1787 parent.contents = left;
1788 node.contents = right;
1789 self.nodes.insert(parent.id, parent);
1790 self.nodes.insert(node.id, node);
1791 None
1792 }
1793 DiscreteContentResult::One(content) => {
1794 parent.contents = content;
1795 parent.to = node.to;
1796
1797 for child in &parent.to {
1798 let child = self.nodes.get_mut(child).unwrap();
1799
1800 if let Some(index) = child.from.get_index_of(&node.id) {
1801 assert!(
1802 child.from.replace_index(index, parent.id).is_ok(),
1803 "Should be unreachable"
1804 );
1805 } else {
1806 child.from.insert(parent.id);
1807 }
1808 }
1809
1810 let parent_id = parent.id;
1811
1812 if node.bookmarked && !parent.bookmarked {
1813 parent.bookmarked = true;
1814 assert!(
1815 self.bookmarked
1816 .replace_index(
1817 self.bookmarked.get_index_of(&node.id).unwrap(),
1818 parent.id,
1819 )
1820 .is_ok(),
1821 "Should be unreachable"
1822 );
1823 } else {
1824 self.bookmarked.shift_remove(&node.id);
1825 }
1826
1827 self.nodes.insert(parent.id, parent);
1828 self.active.remove(&node.id);
1829
1830 Some(parent_id)
1831 }
1832 }
1833 } else {
1834 self.nodes.insert(node.id, node);
1835 None
1836 }
1837 } else {
1838 None
1839 }
1840 }
1841}
1842
1843impl<K, T, M, S> SemiIndependentWeave<K, IndependentNode<K, T, S>, T>
1844 for IndependentWeave<K, T, M, S>
1845where
1846 K: Hash + Copy + Eq + Ord,
1847 T: IndependentContents,
1848 S: BuildHasher + Default + Clone,
1849{
1850 #[cfg_attr(debug_assertions, contract(
1851 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1852 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1853 ensures(old(self.roots.clone()) == self.roots),
1854 ensures(old(self.active.clone()) == self.active),
1855 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1856 invariant(self.validate())
1857 ))]
1858 #[inline]
1859 fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1860 self.nodes
1861 .get_mut(id)
1862 .map(|node| callback(&mut node.contents))
1863 }
1864}
1865
1866impl<K, T, M, S> crate::IndependentWeave<K, IndependentNode<K, T, S>, T>
1867 for IndependentWeave<K, T, M, S>
1868where
1869 K: Hash + Copy + Eq + Ord,
1870 T: IndependentContents,
1871 S: BuildHasher + Default + Clone,
1872{
1873 #[cfg_attr(debug_assertions, contract(
1874 ensures(!ret || self.nodes[id].from.iter().copied().collect::<HashSet<_>>() == new_parents.iter().copied().collect::<HashSet<_>>()),
1875 ensures(ret || old(self.nodes.get(id).map(|node| node.from.clone())).as_ref() == self.nodes.get(id).map(|node| &node.from)),
1876 ensures(ret || old(self.roots.clone()) == self.roots),
1877 ensures(ret || old(self.active.clone()) == self.active),
1878 ensures(old(self.nodes.get(id).map(|node| node.to.clone())).as_ref() == self.nodes.get(id).map(|node| &node.to)),
1879 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1880 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1881 ensures(old(self.active.contains(id)) == self.active.contains(id)),
1882 invariant(self.validate())
1883 ))]
1884 fn move_to(&mut self, id: &K, new_parents: &[K]) -> bool {
1885 if new_parents
1886 .iter()
1887 .any(|new_parent| !self.nodes.contains_key(new_parent))
1888 {
1889 return false;
1890 }
1891
1892 if let Some(node) = self.nodes.get(id)
1893 && !node.to.is_empty()
1894 && !new_parents.is_empty()
1895 {
1896 for child in node.to.iter().copied() {
1897 descendant_subgraph(
1898 &self.nodes,
1899 child,
1900 &mut self.scratchpad_stack,
1901 &mut self.scratchpad_set,
1902 );
1903 }
1904
1905 if new_parents
1906 .iter()
1907 .any(|new_parent| self.scratchpad_set.contains(new_parent))
1908 {
1909 self.scratchpad_set.clear();
1910 return false;
1911 }
1912
1913 self.scratchpad_set.clear();
1914 }
1915
1916 let new_parents: IndexSet<K, S> = new_parents.iter().copied().collect();
1917
1918 if new_parents.contains(id) {
1919 return false;
1920 }
1921
1922 if let Some(node) = self.nodes.get_mut(id) {
1923 for child in &node.to {
1924 if new_parents.contains(child) {
1925 return false;
1926 }
1927 }
1928
1929 let old_parents = mem::take(&mut node.from);
1930
1931 for old_parent in &old_parents {
1932 if !new_parents.contains(old_parent)
1933 && let Some(old_parent) = self.nodes.get_mut(old_parent)
1934 {
1935 old_parent.to.shift_remove(id);
1936 }
1937 }
1938
1939 for new_parent in &new_parents {
1940 if !old_parents.contains(new_parent)
1941 && let Some(new_parent) = self.nodes.get_mut(new_parent)
1942 {
1943 new_parent.to.insert(*id);
1944 }
1945 }
1946 } else {
1947 return false;
1948 }
1949
1950 let node = self.nodes.get_mut(id).unwrap();
1951 node.from = new_parents;
1952
1953 if node.from.is_empty() {
1954 self.roots.insert(node.id);
1955 } else {
1956 self.roots.shift_remove(&node.id);
1957 }
1958
1959 if node.active {
1960 node.active = false;
1961 self.update_node_activity_in_place(id, true);
1962 }
1963
1964 true
1965 }
1966}
1967
1968#[cfg(feature = "rkyv")]
1969impl<K, T, S> ArchivedIndependentNode<K, T, S>
1970where
1971 K: Archive + Hash + Copy + Eq + Ord,
1972 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1973 T: Archive + IndependentContents,
1974 S: BuildHasher + Default + Clone,
1975{
1976 #[inline]
1977 fn validate(&self) -> bool {
1978 (if self.from.len() <= self.to.len() {
1979 self.from.iter().all(|v| !self.to.contains(v))
1980 } else {
1981 self.to.iter().all(|v| !self.from.contains(v))
1982 }) && !self.from.contains(&self.id)
1983 && !self.to.contains(&self.id)
1984 }
1985}
1986
1987#[cfg(feature = "rkyv")]
1988impl<K, T, S> Node<K::Archived, T::Archived> for ArchivedIndependentNode<K, T, S>
1989where
1990 K: Archive + Hash + Copy + Eq + Ord,
1991 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1992 T: Archive + IndependentContents,
1993 S: BuildHasher + Default + Clone,
1994{
1995 type From = ArchivedIndexSet<K::Archived>;
1996 type To = ArchivedIndexSet<K::Archived>;
1997
1998 #[inline]
1999 fn id(&self) -> K::Archived {
2000 self.id
2001 }
2002 #[inline]
2003 fn from(&self) -> &Self::From {
2004 &self.from
2005 }
2006 #[inline]
2007 fn to(&self) -> &Self::To {
2008 &self.to
2009 }
2010 #[inline]
2011 fn is_active(&self) -> bool {
2012 self.active
2013 }
2014 #[inline]
2015 fn contents(&self) -> &T::Archived {
2016 &self.contents
2017 }
2018}
2019
2020#[cfg(feature = "rkyv")]
2021impl<K, T, M, S> ArchivedIndependentWeave<K, T, M, S>
2022where
2023 K: Archive + Hash + Copy + Eq + Ord,
2024 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2025 T: Archive + IndependentContents,
2026 M: Archive,
2027 S: BuildHasher + Default + Clone,
2028{
2029 fn validate(&self) -> bool {
2030 let mut scratchpad = Vec::with_capacity(self.nodes.len());
2031 let mut scratchpad_map = HashMap::with_capacity(self.nodes.len());
2032
2033 self.roots
2034 .iter()
2035 .all(move |value| self.nodes.contains_key(value))
2036 && self
2037 .active
2038 .iter()
2039 .all(move |value| self.nodes.contains_key(value))
2040 && self
2041 .bookmarked
2042 .iter()
2043 .all(move |value| self.nodes.contains_key(value))
2044 && self.nodes.iter().all(|(key, value)| {
2045 value.validate()
2046 && value.id == *key
2047 && value
2048 .from
2049 .iter()
2050 .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
2051 && value
2052 .to
2053 .iter()
2054 .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
2055 && value.from.is_empty() == self.roots.contains(key)
2056 && value.active == self.active.contains(key)
2057 && value.bookmarked == self.bookmarked.contains(key)
2058 })
2059 && !archived_detect_cycles(
2060 &self.nodes,
2061 self.roots.iter().copied(),
2062 &mut scratchpad,
2063 &mut scratchpad_map,
2064 )
2065 && archived_active_path_is_valid(&self.nodes, self.roots.iter(), &self.active)
2066 }
2067}
2068
2069#[cfg(feature = "rkyv")]
2070unsafe impl<K, T, M, S, C> Verify<C> for ArchivedIndependentWeave<K, T, M, S>
2073where
2074 K: Archive + Hash + Copy + Eq + Ord,
2075 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2076 T: Archive + IndependentContents,
2077 M: Archive,
2078 S: BuildHasher + Default + Clone,
2079 C: Fallible + ?Sized,
2080 C::Error: Source,
2081{
2082 fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
2083 if !self.validate() {
2084 fail!(ValidationError)
2085 }
2086
2087 Ok(())
2088 }
2089}
2090
2091#[cfg(feature = "rkyv")]
2092impl<K, T, M, S> ImmutableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2093 for ArchivedIndependentWeave<K, T, M, S>
2094where
2095 K: Archive + Hash + Copy + Eq + Ord,
2096 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2097 T: Archive + IndependentContents,
2098 M: Archive,
2099 S: BuildHasher + Default + Clone,
2100{
2101 type Nodes = ArchivedHashMap<K::Archived, ArchivedIndependentNode<K, T, S>>;
2102 type Roots = ArchivedIndexSet<K::Archived>;
2103
2104 #[inline]
2105 fn len(&self) -> usize {
2106 self.nodes.len()
2107 }
2108 #[inline]
2109 fn is_empty(&self) -> bool {
2110 self.nodes.is_empty()
2111 }
2112 #[inline]
2113 fn nodes(&self) -> &Self::Nodes {
2114 &self.nodes
2115 }
2116 #[inline]
2117 fn roots(&self) -> &Self::Roots {
2118 &self.roots
2119 }
2120 #[inline]
2121 fn contains(&self, id: &K::Archived) -> bool {
2122 self.nodes.contains_key(id)
2123 }
2124 #[inline]
2125 fn contains_active(&self, id: &K::Archived) -> bool {
2126 self.active.contains(id)
2127 }
2128 #[inline]
2129 fn get(&self, id: &K::Archived) -> Option<&ArchivedIndependentNode<K, T, S>> {
2130 self.nodes.get(id)
2131 }
2132 #[inline]
2133 fn get_parents(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
2134 self.nodes.get(id).map(|node| &node.from)
2135 }
2136 #[inline]
2137 fn get_children(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
2138 self.nodes.get(id).map(|node| &node.to)
2139 }
2140 #[inline]
2141 fn get_contents(&self, id: &K::Archived) -> Option<&T::Archived> {
2142 self.nodes.get(id).map(|node| &node.contents)
2143 }
2144 fn get_ordered_identifiers(&self, output: &mut Vec<K::Archived>) {
2145 output.clear();
2146 let mut scratchpad = Vec::with_capacity(self.len());
2147 let mut scratchpad_2 = Vec::with_capacity(self.len());
2148 let mut identifier_set = HashSet::with_capacity(self.len());
2149 let mut scratchpad_map = HashMap::with_capacity(self.len());
2150
2151 for root in self.roots.iter() {
2152 archived_topological_sort(
2153 &self.nodes,
2154 root,
2155 &mut scratchpad,
2156 &mut scratchpad_2,
2157 output,
2158 &mut identifier_set,
2159 &mut scratchpad_map,
2160 );
2161 }
2162 }
2163 fn get_ordered_identifiers_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2164 output.clear();
2165
2166 if self.nodes.contains_key(id) {
2167 let mut scratchpad = Vec::with_capacity(self.len());
2168 let mut scratchpad_2 = Vec::with_capacity(self.len());
2169 let mut scratchpad_set = HashSet::with_capacity(self.len());
2170 let mut scratchpad_set_2 = HashSet::with_capacity(self.len());
2171 let mut scratchpad_map = HashMap::with_capacity(self.len());
2172
2173 archived_descendant_subgraph(&self.nodes, *id, &mut scratchpad, &mut scratchpad_set);
2174
2175 archived_topological_sort_subgraph(
2176 &self.nodes,
2177 &|id| scratchpad_set.contains(id),
2178 id,
2179 &mut scratchpad,
2180 &mut scratchpad_2,
2181 output,
2182 &mut scratchpad_set_2,
2183 &mut scratchpad_map,
2184 );
2185 }
2186 }
2187 fn get_active_path(&self, output: &mut Vec<K::Archived>) {
2188 output.clear();
2189 let mut scratchpad_list = Vec::with_capacity(self.len());
2190 let mut scratchpad_list_2 = Vec::with_capacity(self.len());
2191 let mut scratchpad_list_3 = Vec::with_capacity(self.len());
2192 let mut scratchpad_set = HashSet::with_capacity(self.len());
2193 let mut scratchpad_map = HashMap::with_capacity(self.len());
2194
2195 for root in self.roots.iter() {
2196 archived_topological_sort_subgraph(
2197 &self.nodes,
2198 &|id| self.active.contains(id),
2199 root,
2200 &mut scratchpad_list,
2201 &mut scratchpad_list_2,
2202 &mut scratchpad_list_3,
2203 &mut scratchpad_set,
2204 &mut scratchpad_map,
2205 );
2206 }
2207
2208 scratchpad_map.clear();
2209
2210 archived_longest_candidate_path_to_root(
2211 &self.nodes,
2212 &scratchpad_list_3,
2213 &|id| self.active.contains(id),
2214 &mut scratchpad_map,
2215 output,
2216 );
2217 }
2218 fn get_path_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2219 output.clear();
2220
2221 if self.nodes.contains_key(id) {
2222 let mut scratchpad_list = Vec::with_capacity(self.len());
2223 let mut scratchpad_list_2 = Vec::with_capacity(self.len());
2224 let mut scratchpad_stack = Vec::with_capacity(self.len());
2225 let mut scratchpad_queue = VecDeque::with_capacity(self.len());
2226 let mut scratchpad_set = HashSet::with_capacity(self.len());
2227 let mut scratchpad_set_2 = HashSet::with_capacity(self.len());
2228 let mut scratchpad_map = HashMap::with_capacity(self.len());
2229 let mut scratchpad_map_2 = HashMap::with_capacity(self.len());
2230
2231 archived_ancestor_subgraph(
2232 &self.nodes,
2233 *id,
2234 &mut scratchpad_stack,
2235 &mut scratchpad_set,
2236 );
2237
2238 for root in self.roots.iter() {
2239 archived_topological_sort_subgraph(
2240 &self.nodes,
2241 &|id| self.active.contains(id),
2242 root,
2243 &mut scratchpad_stack,
2244 &mut scratchpad_list_2,
2245 &mut scratchpad_list,
2246 &mut scratchpad_set_2,
2247 &mut scratchpad_map,
2248 );
2249 }
2250
2251 scratchpad_map.clear();
2252
2253 archived_longest_candidate_path_to_root(
2254 &self.nodes,
2255 &scratchpad_list,
2256 &|id| self.active.contains(id) && scratchpad_set.contains(id),
2257 &mut scratchpad_map,
2258 &mut scratchpad_list_2,
2259 );
2260
2261 scratchpad_set_2.clear();
2262
2263 if let Some(target) = scratchpad_list_2.first().copied() {
2264 archived_shortest_path_to_ancestor(
2265 &self.nodes,
2266 id,
2267 &|node| node.id == target,
2268 &mut scratchpad_queue,
2269 &mut scratchpad_map_2,
2270 &mut scratchpad_set_2,
2271 output,
2272 );
2273
2274 output.reverse();
2275 output.pop();
2276 output.append(&mut scratchpad_list_2);
2277 } else {
2278 archived_shortest_path_to_ancestor(
2279 &self.nodes,
2280 id,
2281 &|node| node.from.is_empty(),
2282 &mut scratchpad_queue,
2283 &mut scratchpad_map_2,
2284 &mut scratchpad_set_2,
2285 output,
2286 );
2287
2288 output.reverse();
2289 }
2290 }
2291 }
2292}
2293
2294#[cfg(feature = "rkyv")]
2295impl<K, T, M, S>
2296 ImmutableMetadataWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived, M::Archived>
2297 for ArchivedIndependentWeave<K, T, M, S>
2298where
2299 K: Archive + Hash + Copy + Eq + Ord,
2300 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2301 T: Archive + IndependentContents,
2302 M: Archive,
2303 S: BuildHasher + Default + Clone,
2304{
2305 #[inline]
2306 fn metadata(&self) -> &M::Archived {
2307 &self.metadata
2308 }
2309}
2310
2311#[cfg(feature = "rkyv")]
2312impl<K, T, M, S>
2313 ImmutableBookmarkableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2314 for ArchivedIndependentWeave<K, T, M, S>
2315where
2316 K: Archive + Hash + Copy + Eq + Ord,
2317 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2318 T: Archive + IndependentContents,
2319 M: Archive,
2320 S: BuildHasher + Default + Clone,
2321{
2322 type Bookmarks = ArchivedIndexSet<K::Archived>;
2323
2324 #[inline]
2325 fn bookmarks(&self) -> &Self::Bookmarks {
2326 &self.bookmarked
2327 }
2328 #[inline]
2329 fn contains_bookmark(&self, id: &K::Archived) -> bool {
2330 self.bookmarked.contains(id)
2331 }
2332}
2333
2334#[cfg(feature = "rkyv")]
2335impl<K, T, M, S>
2336 ImmutableActivePathWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2337 for ArchivedIndependentWeave<K, T, M, S>
2338where
2339 K: Archive + Hash + Copy + Eq + Ord,
2340 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2341 T: Archive + IndependentContents,
2342 M: Archive,
2343 S: BuildHasher + Default + Clone,
2344{
2345 type Active = ArchivedHashSet<K::Archived>;
2346
2347 #[inline]
2348 fn active(&self) -> &Self::Active {
2349 &self.active
2350 }
2351}
2352
2353#[cfg(feature = "rkyv")]
2354fn archived_topological_sort<'a, K, N, T, S>(
2355 nodes: &'a ArchivedHashMap<K, N>,
2356 id: &'a K,
2357 scratchpad: &mut Vec<K>,
2358 scratchpad_2: &mut Vec<K>,
2359 identifiers: &mut Vec<K>,
2360 identifier_set: &mut HashSet<K, S>,
2361 identifier_map: &mut HashMap<K, usize, S>,
2362) where
2363 K: Hash + Copy + Eq + Ord + 'a,
2364 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2365 S: BuildHasher + Default + Clone,
2366{
2367 scratchpad.push(*id);
2368
2369 while let Some(id) = scratchpad.pop() {
2370 let node = &nodes[&id];
2371
2372 if identifier_set.contains(&id)
2373 || identifier_map
2374 .get(&id)
2375 .copied()
2376 .unwrap_or_else(|| node.from().len())
2377 != 0
2378 {
2379 continue;
2380 }
2381
2382 identifiers.push(id);
2383 identifier_set.insert(id);
2384
2385 for child in node.to().iter().copied() {
2386 let remaining = identifier_map
2387 .entry(child)
2388 .or_insert_with(|| nodes[&child].from().len());
2389 *remaining = remaining.strict_sub(1);
2390
2391 scratchpad_2.push(child);
2392 }
2393
2394 scratchpad_2.reverse();
2395 scratchpad.append(scratchpad_2);
2396 }
2397}
2398
2399#[cfg(feature = "rkyv")]
2400#[allow(clippy::too_many_arguments, reason = "Rkyv limitation")]
2401fn archived_topological_sort_subgraph<'a, K, N, T, S>(
2402 nodes: &'a ArchivedHashMap<K, N>,
2403 filter: &impl Fn(&K) -> bool,
2404 id: &'a K,
2405 scratchpad: &mut Vec<K>,
2406 scratchpad_2: &mut Vec<K>,
2407 identifiers: &mut Vec<K>,
2408 identifier_set: &mut HashSet<K, S>,
2409 identifier_map: &mut HashMap<K, usize, S>,
2410) where
2411 K: Hash + Copy + Eq + Ord + 'a,
2412 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2413 S: BuildHasher + Default + Clone,
2414{
2415 scratchpad.push(*id);
2416
2417 while let Some(id) = scratchpad.pop() {
2418 let node = &nodes[&id];
2419
2420 if !filter(&id)
2421 || identifier_set.contains(&id)
2422 || identifier_map
2423 .get(&id)
2424 .copied()
2425 .unwrap_or_else(|| node.from().iter().filter(|&parent| filter(parent)).count())
2426 != 0
2427 {
2428 continue;
2429 }
2430
2431 identifiers.push(id);
2432 identifier_set.insert(id);
2433
2434 for child in node.to().iter().copied() {
2435 let remaining = identifier_map.entry(child).or_insert_with(|| {
2436 nodes[&child]
2437 .from()
2438 .iter()
2439 .filter(|&parent| filter(parent))
2440 .count()
2441 });
2442 *remaining = remaining.strict_sub(1);
2443
2444 scratchpad_2.push(child);
2445 }
2446
2447 scratchpad_2.reverse();
2448 scratchpad.append(scratchpad_2);
2449 }
2450}
2451
2452#[cfg(feature = "rkyv")]
2453fn archived_detect_cycles<'a, K, N, T, S>(
2454 nodes: &'a ArchivedHashMap<K, N>,
2455 roots: impl Iterator<Item = K>,
2456 scratchpad: &mut Vec<Step<K, K>>,
2457 scratchpad_map: &mut HashMap<K, bool, S>,
2458) -> bool
2459where
2460 K: Hash + Copy + Eq + Ord + 'a,
2461 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2462 S: BuildHasher + Default + Clone,
2463{
2464 for root in roots {
2465 if scratchpad_map.contains_key(&root) {
2466 continue;
2467 }
2468
2469 scratchpad.push(Step::Enter(root));
2470
2471 while let Some(step) = scratchpad.pop() {
2472 match step {
2473 Step::Enter(id) => {
2474 scratchpad.push(Step::Exit(id));
2475
2476 match scratchpad_map.entry(id) {
2477 Entry::Occupied(entry) => {
2478 if !entry.get() {
2479 return true;
2480 }
2481 }
2482 Entry::Vacant(entry) => {
2483 entry.insert_entry(false);
2484
2485 scratchpad.extend(nodes[&id].to().iter().copied().map(Step::Enter));
2486 }
2487 }
2488 }
2489 Step::Exit(id) => {
2490 scratchpad_map.insert(id, true);
2491 }
2492 }
2493 }
2494 }
2495
2496 scratchpad_map.len() != nodes.len()
2497}
2498
2499#[cfg(feature = "rkyv")]
2500#[allow(clippy::too_many_arguments, reason = "Rkyv limitation")]
2501fn archived_shortest_path_to_ancestor<'a, K, N, T, S>(
2502 nodes: &'a ArchivedHashMap<K, N>,
2503 id: &'a K,
2504 target: &impl Fn(&'a N) -> bool,
2505 scratchpad: &mut VecDeque<K>,
2506 scratchpad_map: &mut HashMap<K, K, S>,
2507 scratchpad_set: &mut HashSet<K, S>,
2508 path: &mut Vec<K>,
2509) where
2510 K: Hash + Copy + Eq + Ord + 'a,
2511 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2512 S: BuildHasher + Default + Clone,
2513{
2514 scratchpad.push_front(*id);
2515 scratchpad_set.insert(*id);
2516
2517 while let Some(id) = scratchpad.pop_back() {
2518 let node = &nodes[&id];
2519
2520 if target(node) {
2521 scratchpad.clear();
2522
2523 path.push(id);
2524
2525 while let Some(child) = scratchpad_map.remove(path.last().unwrap()) {
2526 path.push(child);
2527 }
2528
2529 return;
2530 }
2531
2532 for parent in node.from().iter().copied() {
2533 if scratchpad_set.insert(parent) {
2534 scratchpad.push_front(parent);
2535 scratchpad_map.insert(parent, id);
2536 }
2537 }
2538 }
2539}
2540
2541#[cfg(feature = "rkyv")]
2542fn archived_longest_candidate_path_to_root<'a, K, N, T, S>(
2543 nodes: &'a ArchivedHashMap<K, N>,
2544 topological_order: &'a [K],
2545 is_candidate: &impl Fn(&K) -> bool,
2546 scratchpad_map: &mut HashMap<K, usize, S>,
2547 reversed_path: &mut Vec<K>,
2548) where
2549 K: Hash + Copy + Eq + Ord + 'a,
2550 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2551 S: BuildHasher + Default + Clone,
2552{
2553 let mut longest_distance = None;
2554
2555 for id in topological_order {
2556 if !is_candidate(id) {
2557 continue;
2558 }
2559
2560 let node = &nodes[id];
2561 let distance = if node.from().is_empty() {
2562 Some(0)
2563 } else {
2564 node.from()
2565 .iter()
2566 .filter_map(|parent| scratchpad_map.get(parent).copied())
2567 .max()
2568 .map(|l| l.strict_add(1))
2569 };
2570
2571 if let Some(distance) = distance {
2572 scratchpad_map.insert(*id, distance);
2573
2574 if longest_distance.is_none_or(|(value, _)| distance > value) {
2575 longest_distance = Some((distance, id));
2576 }
2577 }
2578 }
2579
2580 let mut current = longest_distance.map(|(_, id)| id);
2581
2582 while let Some(id) = current {
2583 reversed_path.push(*id);
2584
2585 current = nodes[id]
2586 .from()
2587 .iter()
2588 .filter(|id| scratchpad_map.contains_key(*id))
2589 .min_by_key(|id| Reverse(scratchpad_map[*id]));
2590 }
2591}
2592
2593#[cfg(feature = "rkyv")]
2594fn archived_ancestor_subgraph<'a, K, N, T, S>(
2595 nodes: &'a ArchivedHashMap<K, N>,
2596 id: K,
2597 scratchpad: &mut Vec<K>,
2598 identifiers: &mut HashSet<K, S>,
2599) where
2600 K: Hash + Copy + Eq + Ord + 'a,
2601 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2602 S: BuildHasher + Default + Clone,
2603{
2604 scratchpad.push(id);
2605
2606 while let Some(id) = scratchpad.pop() {
2607 if identifiers.insert(id) {
2608 scratchpad.extend(nodes[&id].from().iter().copied());
2609 }
2610 }
2611}
2612
2613#[cfg(feature = "rkyv")]
2614fn archived_descendant_subgraph<'a, K, N, T, S>(
2615 nodes: &'a ArchivedHashMap<K, N>,
2616 id: K,
2617 scratchpad: &mut Vec<K>,
2618 identifiers: &mut HashSet<K, S>,
2619) where
2620 K: Hash + Copy + Eq + Ord + 'a,
2621 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2622 S: BuildHasher + Default + Clone,
2623{
2624 scratchpad.push(id);
2625
2626 while let Some(id) = scratchpad.pop() {
2627 if identifiers.insert(id) {
2628 scratchpad.extend(nodes[&id].to().iter().copied());
2629 }
2630 }
2631}
2632
2633#[cfg(feature = "rkyv")]
2634fn archived_active_path_is_valid<'a, K, N, T>(
2635 nodes: &'a ArchivedHashMap<K, N>,
2636 roots: impl Iterator<Item = &'a K>,
2637 active: &'a ArchivedHashSet<K>,
2638) -> bool
2639where
2640 K: Hash + Copy + Eq + Ord + 'a,
2641 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2642{
2643 let mut scratchpad = Vec::with_capacity(nodes.len());
2644 let mut scratchpad_list = Vec::with_capacity(nodes.len());
2645 let mut scratchpad_list_2 = Vec::with_capacity(nodes.len());
2646 let mut scratchpad_set = HashSet::with_capacity(nodes.len());
2647 let mut scratchpad_map = HashMap::with_capacity(nodes.len());
2648
2649 for root in roots {
2650 archived_topological_sort(
2651 nodes,
2652 root,
2653 &mut scratchpad,
2654 &mut scratchpad_list_2,
2655 &mut scratchpad_list,
2656 &mut scratchpad_set,
2657 &mut scratchpad_map,
2658 );
2659 }
2660
2661 scratchpad_list_2.clear();
2662 scratchpad_set.clear();
2663 scratchpad_map.clear();
2664
2665 archived_longest_candidate_path_to_root(
2666 nodes,
2667 &scratchpad_list,
2668 &|id| active.contains(id),
2669 &mut scratchpad_map,
2670 &mut scratchpad_list_2,
2671 );
2672
2673 scratchpad_set.extend(scratchpad_list_2);
2674
2675 scratchpad_set.len() == active.len()
2676 && scratchpad_set.into_iter().all(|id| active.contains(&id))
2677}