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