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