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