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