Skip to main content

universal_weave/independent/
mod.rs

1//! [`IndependentWeave`] is a DAG-based [`Weave`] where each [`Node`] does *not* depend on the contents of the previous Node.
2
3use 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/// A [`Node`] in a [`IndependentWeave`] document.
53#[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    /// The node's unique identifier.
61    pub id: K,
62    /// The identifiers corresponding to the node's parents.
63    #[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    /// The identifiers corresponding to the node's children.
72    #[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    /// If the node should be considered active.
81    ///
82    /// Unlike [`DependentWeave`], [`IndependentWeave`] considers all nodes within an active path to be active.
83    pub active: bool,
84    /// If the node is bookmarked.
85    pub bookmarked: bool,
86    /// The node's contents.
87    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/// A DAG-based [`Weave`] where each [`Node`] does *not* depend on the contents of the previous Node.
208///
209/// However, this additional flexibility results in worse performance and memory usage characteristics overall.
210#[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    /// The metadata associated with the weave.
295    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    /// Creates a new, empty [`IndependentWeave`] with at least the specified capacity.
343    #[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    /// Returns the number of nodes the weave can hold without reallocating.
366    #[inline]
367    pub fn capacity(&self) -> usize {
368        self.nodes.capacity()
369    }
370    /// Reserves capacity for at least `additional` more nodes.
371    #[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    /// Shrinks the capacity of the weave with a lower limit.
433    #[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, // topological order
511                    &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])) // score: (connectors, active)
524                    .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); // predecessors
540                }
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])) // score: (connectors, active)
562                    .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); // successors
578                }
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    /// Sets the active status of a node with the specified identifier, using identical activation behavior to [`DependentWeave`].
672    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, // topological order
695                    &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])) // score: (connectors, active)
708                    .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); // predecessors
724                }
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    /// Validates that the weave is internally consistent.
1317    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")]
2028// SAFETY:
2029// All fields are safe to access and no unsafe functions are called
2030unsafe 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}