Skip to main content

universal_weave/dependent/
mod.rs

1//! [`DependentWeave`] is a tree-based [`Weave`] where each [`Node`] depends on the contents of the previous Node.
2
3use alloc::vec::Vec;
4use core::{
5    cmp::Ordering,
6    hash::{BuildHasher, Hash},
7};
8
9use hashbrown::{HashMap, HashSet};
10use indexmap::IndexSet;
11
12#[cfg(debug_assertions)]
13use contracts::contract;
14
15#[cfg(feature = "rkyv")]
16use rkyv::{
17    Archive, Deserialize, Serialize,
18    bytecheck::Verify,
19    collections::swiss_table::{ArchivedHashMap, ArchivedIndexSet},
20    option::ArchivedOption,
21    rancor::{Fallible, Source, fail},
22    with::Skip,
23};
24
25#[cfg(feature = "serde")]
26use serde::{
27    Deserialize as SerdeDeserialize, Deserializer as SerdeDeserializer,
28    Serialize as SerdeSerialize, de::Error as _,
29};
30
31use crate::{
32    ActiveSingularWeave, BookmarkableWeave, DiscreteContentResult, DiscreteContents, DiscreteWeave,
33    IndependentContents, MetadataWeave, Node, SemiIndependentWeave, SortableBookmarkableWeave,
34    SortableWeave, Weave,
35};
36
37#[cfg(debug_assertions)]
38use crate::contract::{lacks_duplicates, valid_path, valid_topological_sort};
39
40#[cfg(feature = "rkyv")]
41use crate::{
42    ImmutableActiveSingularWeave, ImmutableBookmarkableWeave, ImmutableMetadataWeave,
43    ImmutableWeave,
44};
45
46#[cfg(any(feature = "serde", feature = "rkyv"))]
47use crate::contract::ValidationError;
48
49#[cfg(feature = "loro")]
50pub mod loro;
51
52#[cfg(feature = "legacy")]
53#[deprecated]
54pub mod legacy_dependent;
55
56#[derive(Default, Debug, Clone)]
57#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
58#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
59/// A [`Node`] in a [`DependentWeave`] document.
60#[must_use]
61pub struct DependentNode<K, T, S>
62where
63    K: Hash + Copy + Eq + Ord,
64    S: BuildHasher + Default + Clone,
65{
66    /// The node's unique identifier.
67    pub id: K,
68    /// The identifier corresponding to the node's parent.
69    pub from: Option<K>,
70    /// The identifiers corresponding to the node's children.
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 to: IndexSet<K, S>,
79    /// If the node should be considered active.
80    ///
81    /// [`DependentWeave`] only considers the node at the start of an active path to be active.
82    pub active: bool,
83    /// If the node is bookmarked.
84    pub bookmarked: bool,
85    /// The node's contents.
86    pub contents: T,
87}
88
89#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
90impl<K, T, S> PartialEq for DependentNode<K, T, S>
91where
92    K: Hash + Copy + Eq + Ord,
93    T: PartialEq,
94    S: BuildHasher + Default + Clone,
95{
96    #[inline]
97    fn eq(&self, other: &Self) -> bool {
98        self.id == other.id
99            && self.from == other.from
100            && self.to.len() == other.to.len()
101            && self.to.iter().zip(other.to.iter()).all(|(a, b)| a == b)
102            && self.active == other.active
103            && self.bookmarked == other.bookmarked
104            && self.contents == other.contents
105    }
106}
107
108#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
109impl<K, T, S> Eq for DependentNode<K, T, S>
110where
111    K: Hash + Copy + Eq + Ord,
112    T: Eq,
113    S: BuildHasher + Default + Clone,
114{
115}
116
117impl<K, T, S> DependentNode<K, T, S>
118where
119    K: Hash + Copy + Eq + Ord,
120    S: BuildHasher + Default + Clone,
121{
122    #[inline]
123    fn validate(&self) -> bool {
124        self.from.is_none_or(|from| !self.to.contains(&from))
125            && self.from != Some(self.id)
126            && !self.to.contains(&self.id)
127    }
128}
129
130impl<K, T, S> Node<K, T> for DependentNode<K, T, S>
131where
132    K: Hash + Copy + Eq + Ord,
133    S: BuildHasher + Default + Clone,
134{
135    type From = Option<K>;
136    type To = IndexSet<K, S>;
137
138    #[inline]
139    fn id(&self) -> K {
140        self.id
141    }
142    #[inline]
143    fn from(&self) -> &Self::From {
144        &self.from
145    }
146    #[inline]
147    fn to(&self) -> &Self::To {
148        &self.to
149    }
150    #[inline]
151    fn is_active(&self) -> bool {
152        self.active
153    }
154    #[inline]
155    fn contents(&self) -> &T {
156        &self.contents
157    }
158}
159
160/// A tree-based [`Weave`] where each [`Node`] depends on the contents of the previous Node.
161#[derive(Default, Debug, Clone)]
162#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
163#[cfg_attr(feature = "serde", derive(SerdeSerialize))]
164#[cfg_attr(feature = "rkyv", rkyv(bytecheck(verify)))]
165#[must_use]
166pub struct DependentWeave<K, T, M, S>
167where
168    K: Hash + Copy + Eq + Ord,
169    S: BuildHasher + Default + Clone,
170{
171    #[cfg_attr(
172        feature = "serde",
173        serde(bound(
174            serialize = "HashMap<K, DependentNode<K, T, S>, S>: SerdeSerialize",
175            deserialize = "HashMap<K, DependentNode<K, T, S>, S>: SerdeDeserialize<'de>"
176        ))
177    )]
178    pub(super) nodes: HashMap<K, DependentNode<K, T, S>, S>,
179    #[cfg_attr(
180        feature = "serde",
181        serde(bound(
182            serialize = "IndexSet<K, S>: SerdeSerialize",
183            deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
184        ))
185    )]
186    pub(super) roots: IndexSet<K, S>,
187    pub(super) active: Option<K>,
188    #[cfg_attr(
189        feature = "serde",
190        serde(bound(
191            serialize = "IndexSet<K, S>: SerdeSerialize",
192            deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
193        ))
194    )]
195    pub(super) bookmarked: IndexSet<K, S>,
196
197    #[cfg_attr(feature = "rkyv", rkyv(with = Skip))]
198    #[cfg_attr(feature = "serde", serde(skip))]
199    pub(super) scratchpad: Vec<K>,
200
201    /// The metadata associated with the weave.
202    pub metadata: M,
203}
204
205#[cfg(feature = "serde")]
206#[derive(SerdeDeserialize)]
207#[serde(rename = "DependentWeave")]
208struct ProxyDependentWeave<K, T, M, S>
209where
210    K: Hash + Copy + Eq + Ord,
211    S: BuildHasher + Default + Clone,
212{
213    #[serde(bound(
214        serialize = "HashMap<K, DependentNode<K, T, S>, S>: SerdeSerialize",
215        deserialize = "HashMap<K, DependentNode<K, T, S>, S>: SerdeDeserialize<'de>"
216    ))]
217    nodes: HashMap<K, DependentNode<K, T, S>, S>,
218    #[serde(bound(
219        serialize = "IndexSet<K, S>: SerdeSerialize",
220        deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
221    ))]
222    roots: IndexSet<K, S>,
223    active: Option<K>,
224    #[serde(bound(
225        serialize = "IndexSet<K, S>: SerdeSerialize",
226        deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
227    ))]
228    bookmarked: IndexSet<K, S>,
229    metadata: M,
230}
231
232#[cfg(feature = "serde")]
233#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
234impl<'de, K, T, M, S> SerdeDeserialize<'de> for DependentWeave<K, T, M, S>
235where
236    K: Hash + Copy + Eq + Ord + SerdeDeserialize<'de>,
237    T: SerdeDeserialize<'de>,
238    M: SerdeDeserialize<'de>,
239    S: BuildHasher + Default + Clone,
240{
241    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
242    where
243        D: SerdeDeserializer<'de>,
244    {
245        let proxy = ProxyDependentWeave::deserialize(deserializer)?;
246        let weave = Self {
247            scratchpad: Vec::default(),
248            nodes: proxy.nodes,
249            roots: proxy.roots,
250            active: proxy.active,
251            bookmarked: proxy.bookmarked,
252            metadata: proxy.metadata,
253        };
254
255        if weave.validate() {
256            Ok(weave)
257        } else {
258            Err(D::Error::custom(ValidationError))
259        }
260    }
261}
262
263#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
264impl<K, T, M, S> PartialEq for DependentWeave<K, T, M, S>
265where
266    K: Hash + Copy + Eq + Ord,
267    T: PartialEq,
268    M: PartialEq,
269    S: BuildHasher + Default + Clone,
270{
271    #[inline]
272    fn eq(&self, other: &Self) -> bool {
273        self.roots.len() == other.roots.len()
274            && self.bookmarked.len() == other.bookmarked.len()
275            && self.active == other.active
276            && self
277                .roots
278                .iter()
279                .zip(other.roots.iter())
280                .all(|(a, b)| a == b)
281            && self
282                .bookmarked
283                .iter()
284                .zip(other.bookmarked.iter())
285                .all(|(a, b)| a == b)
286            && self.nodes == other.nodes
287            && self.metadata == other.metadata
288    }
289}
290
291#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
292impl<K, T, M, S> Eq for DependentWeave<K, T, M, S>
293where
294    K: Hash + Copy + Eq + Ord,
295    T: Eq,
296    M: Eq,
297    S: BuildHasher + Default + Clone,
298{
299}
300
301impl<K, T, M, S> DependentWeave<K, T, M, S>
302where
303    K: Hash + Copy + Eq + Ord,
304    S: BuildHasher + Default + Clone,
305{
306    /// Creates a new, empty [`DependentWeave`] with at least the specified capacity.
307    #[cfg_attr(debug_assertions, contract(
308        ensures(ret.nodes.is_empty()),
309        ensures(ret.validate())
310    ))]
311    pub fn with_capacity(capacity: usize, metadata: M) -> Self {
312        Self {
313            nodes: HashMap::with_capacity_and_hasher(capacity, S::default()),
314            roots: IndexSet::with_capacity_and_hasher(capacity, S::default()),
315            active: None,
316            bookmarked: IndexSet::with_capacity_and_hasher(capacity, S::default()),
317            scratchpad: Vec::with_capacity(capacity),
318            metadata,
319        }
320    }
321    /// Returns the number of nodes the weave can hold without reallocating.
322    #[inline]
323    pub fn capacity(&self) -> usize {
324        self.nodes.capacity()
325    }
326    /// Reserves capacity for at least `additional` more nodes.
327    #[cfg_attr(debug_assertions, contract(
328        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
329        ensures(old(self.roots.clone()) == self.roots),
330        ensures(old(self.active) == self.active),
331        ensures(old(self.bookmarked.clone()) == self.bookmarked),
332        invariant(self.validate())
333    ))]
334    pub fn reserve(&mut self, additional: usize) {
335        self.nodes.reserve(additional);
336        self.roots
337            .reserve(self.nodes.capacity().saturating_sub(self.roots.len()));
338        self.bookmarked
339            .reserve(self.nodes.capacity().saturating_sub(self.bookmarked.len()));
340        self.scratchpad
341            .reserve(self.nodes.capacity().saturating_sub(self.scratchpad.len()));
342    }
343    /// Shrinks the capacity of the weave with a lower limit.
344    #[cfg_attr(debug_assertions, contract(
345        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
346        ensures(old(self.roots.clone()) == self.roots),
347        ensures(old(self.active) == self.active),
348        ensures(old(self.bookmarked.clone()) == self.bookmarked),
349        invariant(self.validate())
350    ))]
351    pub fn shrink_to(&mut self, min_capacity: usize) {
352        self.nodes.shrink_to(min_capacity);
353        self.roots.shrink_to(min_capacity);
354        self.bookmarked.shrink_to(min_capacity);
355        self.scratchpad.shrink_to(min_capacity);
356    }
357}
358
359impl<K, T, M, S> Weave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
360where
361    K: Hash + Copy + Eq + Ord,
362    S: BuildHasher + Default + Clone,
363{
364    type Nodes = HashMap<K, DependentNode<K, T, S>, S>;
365    type Roots = IndexSet<K, S>;
366
367    #[inline]
368    fn len(&self) -> usize {
369        self.nodes.len()
370    }
371    #[inline]
372    fn is_empty(&self) -> bool {
373        self.nodes.is_empty()
374    }
375    #[inline]
376    fn nodes(&self) -> &Self::Nodes {
377        &self.nodes
378    }
379    #[inline]
380    fn roots(&self) -> &Self::Roots {
381        &self.roots
382    }
383    #[inline]
384    fn contains(&self, id: &K) -> bool {
385        self.nodes.contains_key(id)
386    }
387    #[inline]
388    fn contains_active(&self, id: &K) -> bool {
389        self.active == Some(*id)
390    }
391    #[inline]
392    fn get_node(&self, id: &K) -> Option<&DependentNode<K, T, S>> {
393        self.nodes.get(id)
394    }
395    #[inline]
396    fn get_node_parents(&self, id: &K) -> Option<&Option<K>> {
397        self.nodes.get(id).map(|node| &node.from)
398    }
399    #[inline]
400    fn get_node_children(&self, id: &K) -> Option<&IndexSet<K, S>> {
401        self.nodes.get(id).map(|node| &node.to)
402    }
403    #[cfg_attr(debug_assertions, contract(
404        ensures(output.len() == self.nodes.len()),
405        ensures(valid_topological_sort(&self.nodes, output)),
406        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
407        ensures(old(self.roots.clone()) == self.roots),
408        ensures(old(self.active) == self.active),
409        ensures(old(self.bookmarked.clone()) == self.bookmarked),
410        invariant(self.validate())
411    ))]
412    fn get_ordered_node_identifiers(&mut self, output: &mut Vec<K>) {
413        output.clear();
414
415        for root in &self.roots {
416            topological_sort(&self.nodes, *root, &mut self.scratchpad, output);
417        }
418    }
419    #[cfg_attr(debug_assertions, contract(
420        ensures(lacks_duplicates(output)),
421        ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
422        ensures(self.nodes.contains_key(id) || output.is_empty()),
423        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
424        ensures(old(self.roots.clone()) == self.roots),
425        ensures(old(self.active) == self.active),
426        ensures(old(self.bookmarked.clone()) == self.bookmarked),
427        invariant(self.validate())
428    ))]
429    fn get_ordered_node_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
430        output.clear();
431
432        if self.nodes.contains_key(id) {
433            topological_sort(&self.nodes, *id, &mut self.scratchpad, output);
434        }
435    }
436    #[cfg_attr(debug_assertions, contract(
437        ensures(self.active == output.first().copied()),
438        ensures(lacks_duplicates(output)),
439        ensures(valid_path(&self.nodes, output)),
440        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
441        ensures(old(self.roots.clone()) == self.roots),
442        ensures(old(self.active) == self.active),
443        ensures(old(self.bookmarked.clone()) == self.bookmarked),
444        invariant(self.validate())
445    ))]
446    fn get_active_path(&mut self, output: &mut Vec<K>) {
447        output.clear();
448
449        if let Some(active) = self.active {
450            path_to_root(&self.nodes, active, output);
451        }
452    }
453    #[cfg_attr(debug_assertions, contract(
454        ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
455        ensures(self.nodes.contains_key(id) || output.is_empty()),
456        ensures(lacks_duplicates(output)),
457        ensures(valid_path(&self.nodes, output)),
458        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
459        ensures(old(self.roots.clone()) == self.roots),
460        ensures(old(self.active) == self.active),
461        ensures(old(self.bookmarked.clone()) == self.bookmarked),
462        invariant(self.validate())
463    ))]
464    fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
465        output.clear();
466
467        if self.nodes.contains_key(id) {
468            path_to_root(&self.nodes, *id, output);
469        }
470    }
471    #[cfg_attr(debug_assertions, contract(
472        ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
473        ensures(!ret || old(!self.nodes.contains_key(&node.id))),
474        ensures(!ret || self.nodes.contains_key(&old(node.id))),
475        ensures(!ret || old(node.active) == (self.active == Some(old(node.id)))),
476        ensures(!ret || old(node.bookmarked) == self.bookmarked.contains(&old(node.id))),
477        ensures(!ret || old(node.from.is_some()) || self.roots.contains(&old(node.id))),
478        ensures(!ret || old(node.from.is_none()) || old(self.roots.clone()) == self.roots),
479        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
480        ensures(ret || old(self.roots.clone()) == self.roots),
481        ensures(ret || old(self.active) == self.active),
482        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
483        invariant(self.validate())
484    ))]
485    fn add_node(&mut self, node: DependentNode<K, T, S>) -> bool {
486        if self.nodes.contains_key(&node.id) || !node.validate() || !node.to.is_empty() {
487            return false;
488        }
489
490        if let Some(from) = &node.from {
491            match self.nodes.get_mut(from) {
492                Some(parent) => {
493                    parent.to.insert(node.id);
494                }
495                None => return false,
496            }
497        } else {
498            self.roots.insert(node.id);
499        }
500
501        if node.active {
502            if let Some(active) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
503                active.active = false;
504            }
505
506            self.active = Some(node.id);
507        }
508
509        if node.bookmarked {
510            self.bookmarked.insert(node.id);
511        }
512
513        self.nodes.insert(node.id, node);
514
515        true
516    }
517    #[cfg_attr(debug_assertions, contract(
518        ensures(!ret || value == self.contains_active(id)),
519        ensures(ret || old(self.active) == self.active),
520        ensures(ret == self.nodes.contains_key(id)),
521        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
522        ensures(old(self.roots.clone()) == self.roots),
523        ensures(old(self.bookmarked.clone()) == self.bookmarked),
524        invariant(self.validate())
525    ))]
526    fn set_node_active_status(&mut self, id: &K, value: bool) -> bool {
527        match self.nodes.get_mut(id) {
528            Some(node) => {
529                node.active = value;
530
531                if value {
532                    if self.active != Some(node.id)
533                        && let Some(active) = self.active.and_then(|id| self.nodes.get_mut(&id))
534                    {
535                        active.active = false;
536                    }
537
538                    self.active = Some(*id);
539                } else if self.active == Some(node.id) {
540                    self.active = None;
541                }
542
543                true
544            }
545            None => false,
546        }
547    }
548    #[cfg_attr(debug_assertions, contract(
549        ensures(!self.nodes.contains_key(id)),
550        ensures(ret.is_some() == old(self.nodes.contains_key(id))),
551        ensures(ret.as_ref().is_none_or(|node| &node.id == id)),
552        ensures(ret.is_none() || old(self.nodes.len()) > self.nodes.len()),
553        ensures(ret.is_none() || old(self.bookmarked.len()) >= self.bookmarked.len()),
554        ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
555        ensures(ret.is_some() || old(self.roots.clone()) == self.roots),
556        ensures(ret.is_some() || old(self.active) == self.active),
557        ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
558        invariant(self.validate())
559    ))]
560    fn remove_node(&mut self, id: &K) -> Option<DependentNode<K, T, S>> {
561        let mut removed_node = None;
562        let mut removed_active = false;
563
564        self.scratchpad.push(*id);
565
566        while let Some(id) = self.scratchpad.pop() {
567            if let Some(node) = self.nodes.remove(&id) {
568                if node.from.is_none() {
569                    self.roots.shift_remove(&id);
570                }
571                if node.bookmarked {
572                    self.bookmarked.shift_remove(&id);
573                }
574                if node.active {
575                    self.active = None;
576                    removed_active = true;
577                }
578
579                if let Some(parent) = node.from.and_then(|id| self.nodes.get_mut(&id)) {
580                    parent.to.shift_remove(&id);
581                }
582                self.scratchpad.extend(node.to.iter().rev().copied());
583
584                if removed_node.is_none() {
585                    removed_node = Some(node);
586                }
587            }
588        }
589
590        if let Some(removed) = removed_node {
591            if removed_active {
592                self.active = removed.from;
593
594                if let Some(node) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
595                    node.active = true;
596                }
597            }
598            Some(removed)
599        } else {
600            None
601        }
602    }
603    #[cfg_attr(debug_assertions, contract(
604        ensures(!self.nodes.contains_key(id)),
605        ensures(ret == old(self.nodes.contains_key(id))),
606        ensures(!ret || old(self.nodes.len()) > self.nodes.len()),
607        ensures(!ret || old(self.bookmarked.len()) >= self.bookmarked.len()),
608        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
609        ensures(ret || old(self.roots.clone()) == self.roots),
610        ensures(ret || old(self.active) == self.active),
611        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
612        invariant(self.validate())
613    ))]
614    fn remove_node_tracked(
615        &mut self,
616        id: &K,
617        mut on_removal: impl FnMut(DependentNode<K, T, S>),
618    ) -> bool {
619        let removed_node_parent = self.nodes.get(id).map(|node| node.from);
620        let mut removed_active = false;
621
622        self.scratchpad.push(*id);
623
624        while let Some(id) = self.scratchpad.pop() {
625            if let Some(node) = self.nodes.remove(&id) {
626                if node.from.is_none() {
627                    self.roots.shift_remove(&id);
628                }
629                if node.bookmarked {
630                    self.bookmarked.shift_remove(&id);
631                }
632                if node.active {
633                    self.active = None;
634                    removed_active = true;
635                }
636
637                if let Some(parent) = node.from.and_then(|id| self.nodes.get_mut(&id)) {
638                    parent.to.shift_remove(&id);
639                }
640                self.scratchpad.extend(node.to.iter().rev().copied());
641
642                on_removal(node);
643            }
644        }
645
646        if let Some(parent) = removed_node_parent {
647            if removed_active {
648                self.active = parent;
649
650                if let Some(node) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
651                    node.active = true;
652                }
653            }
654            true
655        } else {
656            false
657        }
658    }
659    #[cfg_attr(debug_assertions, contract(
660        ensures(self.nodes.is_empty()),
661        ensures(self.validate())
662    ))]
663    fn remove_all_nodes(&mut self) {
664        self.nodes.clear();
665        self.roots.clear();
666        self.active = None;
667        self.bookmarked.clear();
668    }
669}
670
671impl<K, T, M, S> DependentWeave<K, T, M, S>
672where
673    K: Hash + Copy + Eq + Ord,
674    S: BuildHasher + Default + Clone,
675{
676    /// Validates that the weave is internally consistent.
677    pub fn validate(&self) -> bool {
678        let mut scratchpad = Vec::with_capacity(self.nodes.len());
679        let mut scratchpad_set = HashSet::with_capacity_and_hasher(self.nodes.len(), S::default());
680
681        self.scratchpad.is_empty()
682            && self
683                .roots
684                .iter()
685                .all(move |value| self.nodes.contains_key(value))
686            && self
687                .active
688                .as_ref()
689                .is_none_or(|active| self.nodes.contains_key(active))
690            && self
691                .bookmarked
692                .iter()
693                .all(move |value| self.nodes.contains_key(value))
694            && self.nodes.iter().all(|(key, value)| {
695                value.validate()
696                    && value.id == *key
697                    && value
698                        .from
699                        .as_ref()
700                        .is_none_or(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
701                    && value.to.iter().all(|v| {
702                        self.nodes
703                            .get(v)
704                            .is_some_and(|p| p.from.as_ref() == Some(key))
705                    })
706                    && value.from.is_none() == self.roots.contains(key)
707                    && value.active == (self.active == Some(*key))
708                    && value.bookmarked == self.bookmarked.contains(key)
709            })
710            && !detect_cycles(
711                &self.nodes,
712                self.roots.iter().copied(),
713                &mut scratchpad,
714                &mut scratchpad_set,
715            )
716    }
717}
718
719impl<K, T, M, S> MetadataWeave<K, DependentNode<K, T, S>, T, M> for DependentWeave<K, T, M, S>
720where
721    K: Hash + Copy + Eq + Ord,
722    S: BuildHasher + Default + Clone,
723{
724    #[inline]
725    fn metadata(&self) -> &M {
726        &self.metadata
727    }
728    #[cfg_attr(debug_assertions, contract(
729        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
730        ensures(old(self.roots.clone()) == self.roots),
731        ensures(old(self.active) == self.active),
732        ensures(old(self.bookmarked.clone()) == self.bookmarked),
733        invariant(self.validate())
734    ))]
735    #[inline]
736    fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
737        callback(&mut self.metadata)
738    }
739}
740
741impl<K, T, M, S> BookmarkableWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
742where
743    K: Hash + Copy + Eq + Ord,
744    S: BuildHasher + Default + Clone,
745{
746    type Bookmarks = IndexSet<K, S>;
747
748    #[inline]
749    fn bookmarks(&self) -> &Self::Bookmarks {
750        &self.bookmarked
751    }
752    #[inline]
753    fn contains_bookmark(&self, id: &K) -> bool {
754        self.bookmarked.contains(id)
755    }
756    #[cfg_attr(debug_assertions, contract(
757        ensures(!ret || value == self.bookmarked.contains(id)),
758        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
759        ensures(ret == self.nodes.contains_key(id)),
760        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
761        ensures(old(self.roots.clone()) == self.roots),
762        ensures(old(self.active) == self.active),
763        invariant(self.validate())
764    ))]
765    fn set_node_bookmarked_status(&mut self, id: &K, value: bool) -> bool {
766        match self.nodes.get_mut(id) {
767            Some(node) => {
768                node.bookmarked = value;
769                if value {
770                    self.bookmarked.insert(node.id);
771                } else {
772                    self.bookmarked.shift_remove(id);
773                }
774
775                true
776            }
777            None => false,
778        }
779    }
780}
781
782impl<K, T, M, S> SortableWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
783where
784    K: Hash + Copy + Eq + Ord,
785    S: BuildHasher + Default + Clone,
786{
787    #[cfg_attr(debug_assertions, contract(
788        ensures(ret == self.nodes.contains_key(id)),
789        ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
790        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
791        ensures(old(self.roots.clone()) == self.roots),
792        ensures(old(self.active) == self.active),
793        ensures(old(self.bookmarked.clone()) == self.bookmarked),
794        invariant(self.validate())
795    ))]
796    fn sort_node_children_by(
797        &mut self,
798        id: &K,
799        mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
800    ) -> bool {
801        if let Some(mut node) = self.nodes.remove(id) {
802            node.to.sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
803            self.nodes.insert(node.id, node);
804
805            true
806        } else {
807            false
808        }
809    }
810    #[cfg_attr(debug_assertions, contract(
811        ensures(ret == self.nodes.contains_key(id)),
812        ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
813        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
814        ensures(old(self.roots.clone()) == self.roots),
815        ensures(old(self.active) == self.active),
816        ensures(old(self.bookmarked.clone()) == self.bookmarked),
817        invariant(self.validate())
818    ))]
819    fn sort_node_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
820        if let Some(node) = self.nodes.get_mut(id) {
821            node.to.sort_by(cmp);
822
823            true
824        } else {
825            false
826        }
827    }
828    #[cfg_attr(debug_assertions, contract(
829        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
830        ensures(old(self.roots.clone()) == self.roots),
831        ensures(old(self.active) == self.active),
832        ensures(old(self.bookmarked.clone()) == self.bookmarked),
833        invariant(self.validate())
834    ))]
835    fn sort_roots_by(
836        &mut self,
837        mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
838    ) {
839        self.roots
840            .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
841    }
842    #[cfg_attr(debug_assertions, contract(
843        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
844        ensures(old(self.roots.clone()) == self.roots),
845        ensures(old(self.active) == self.active),
846        ensures(old(self.bookmarked.clone()) == self.bookmarked),
847        invariant(self.validate())
848    ))]
849    fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
850        self.roots.sort_by(cmp);
851    }
852}
853
854impl<K, T, M, S> SortableBookmarkableWeave<K, DependentNode<K, T, S>, T>
855    for DependentWeave<K, T, M, S>
856where
857    K: Hash + Copy + Eq + Ord,
858    S: BuildHasher + Default + Clone,
859{
860    #[cfg_attr(debug_assertions, contract(
861        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
862        ensures(old(self.roots.clone()) == self.roots),
863        ensures(old(self.active) == self.active),
864        ensures(old(self.bookmarked.clone()) == self.bookmarked),
865        invariant(self.validate())
866    ))]
867    fn sort_bookmarks_by(
868        &mut self,
869        mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
870    ) {
871        self.bookmarked
872            .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
873    }
874    #[cfg_attr(debug_assertions, contract(
875        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
876        ensures(old(self.roots.clone()) == self.roots),
877        ensures(old(self.active) == self.active),
878        ensures(old(self.bookmarked.clone()) == self.bookmarked),
879        invariant(self.validate())
880    ))]
881    fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
882        self.bookmarked.sort_by(cmp);
883    }
884}
885
886impl<K, T, M, S> ActiveSingularWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
887where
888    K: Hash + Copy + Eq + Ord,
889    S: BuildHasher + Default + Clone,
890{
891    #[inline]
892    fn active(&self) -> Option<K> {
893        self.active
894    }
895}
896
897impl<K, T, M, S> DiscreteWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
898where
899    K: Hash + Copy + Eq + Ord,
900    T: DiscreteContents,
901    S: BuildHasher + Default + Clone,
902{
903    #[cfg_attr(debug_assertions, contract(
904        ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
905        ensures(!ret || self.nodes.contains_key(id)),
906        ensures(!ret || self.nodes.contains_key(&new_id)),
907        ensures(!ret || old(!self.nodes.contains_key(&new_id))),
908        ensures(!ret || self.nodes[id].to.contains(&new_id) && self.nodes[id].to.len() == 1),
909        ensures(!ret || self.nodes[&new_id].from == Some(*id)),
910        ensures(!ret || old(self.nodes.get(id).map(|n| n.to.clone())).unwrap() == self.nodes[&new_id].to),
911        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
912        ensures(old(self.roots.clone()) == self.roots),
913        ensures(old(self.active) == self.active),
914        ensures(old(self.bookmarked.clone()) == self.bookmarked),
915        invariant(self.validate())
916    ))]
917    fn split_node(&mut self, id: &K, at: usize, new_id: K) -> bool {
918        if self.nodes.contains_key(&new_id) || *id == new_id {
919            return false;
920        }
921
922        if let Some(mut node) = self.nodes.remove(id) {
923            match node.contents.split(at) {
924                DiscreteContentResult::Two(left, right) => {
925                    let left_node = DependentNode {
926                        id: node.id,
927                        from: node.from,
928                        to: IndexSet::from_iter([new_id]),
929                        active: node.active,
930                        bookmarked: node.bookmarked,
931                        contents: left,
932                    };
933
934                    node.from = Some(node.id);
935                    node.id = new_id;
936                    node.contents = right;
937                    node.active = false;
938                    node.bookmarked = false;
939
940                    for child in &node.to {
941                        let child = self.nodes.get_mut(child).unwrap();
942                        child.from = Some(node.id);
943                    }
944
945                    self.nodes.insert(left_node.id, left_node);
946                    self.nodes.insert(node.id, node);
947
948                    true
949                }
950                DiscreteContentResult::One(content) => {
951                    node.contents = content;
952                    self.nodes.insert(node.id, node);
953                    false
954                }
955            }
956        } else {
957            false
958        }
959    }
960    #[cfg_attr(debug_assertions, contract(
961        ensures(ret.is_none() || old(self.nodes.len()) - 1 == self.nodes.len()),
962        ensures(ret.is_none() || !self.nodes.contains_key(id)),
963        ensures(ret.is_none() || old(self.nodes.contains_key(id))),
964        ensures(ret.is_none() || !old(self.contains_active(id)) || old(self.contains_active(id)) && self.contains_active(&ret.unwrap())),
965        ensures(ret.is_none() || old(self.contains_active(id)) || old(self.nodes.get(id).and_then(|n| n.from).and_then(|p| self.nodes.get(&p)).map(|p| p.active)).unwrap() == self.nodes[&ret.unwrap()].active),
966        ensures(ret.is_none() || old(self.nodes.get(id).and_then(|n| n.from).and_then(|p| self.nodes.get(&p)).map(|p| p.from)).unwrap() == self.nodes[&ret.unwrap()].from),
967        ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.to.clone())).unwrap() == self.nodes[&ret.unwrap()].to),
968        ensures(ret.is_none() || ret.unwrap() == old(self.nodes.get(id).and_then(|node| node.from)).unwrap()),
969        ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
970        ensures(ret.is_some() || old(self.active) == self.active),
971        ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
972        ensures(old(self.roots.clone()) == self.roots),
973        invariant(self.validate())
974    ))]
975    fn merge_with_parent(&mut self, id: &K) -> Option<K> {
976        if let Some(mut node) = self.nodes.remove(id) {
977            if let Some(mut parent) = node.from.as_ref().and_then(|id| self.nodes.remove(id)) {
978                if parent.to.len() > 1 {
979                    self.nodes.insert(parent.id, parent);
980                    self.nodes.insert(node.id, node);
981                    return None;
982                }
983
984                match parent.contents.merge(node.contents) {
985                    DiscreteContentResult::Two(left, right) => {
986                        parent.contents = left;
987                        node.contents = right;
988                        self.nodes.insert(parent.id, parent);
989                        self.nodes.insert(node.id, node);
990                        None
991                    }
992                    DiscreteContentResult::One(content) => {
993                        parent.contents = content;
994                        parent.to = node.to;
995
996                        for child in &parent.to {
997                            let child = self.nodes.get_mut(child).unwrap();
998                            child.from = Some(parent.id);
999                        }
1000
1001                        if node.active {
1002                            parent.active = true;
1003                            self.active = Some(parent.id);
1004                        }
1005
1006                        let parent_id = parent.id;
1007
1008                        if node.bookmarked && !parent.bookmarked {
1009                            parent.bookmarked = true;
1010                            assert!(
1011                                self.bookmarked
1012                                    .replace_index(
1013                                        self.bookmarked.get_index_of(&node.id).unwrap(),
1014                                        parent.id,
1015                                    )
1016                                    .is_ok(),
1017                                "Should be unreachable"
1018                            );
1019                        } else {
1020                            self.bookmarked.shift_remove(&node.id);
1021                        }
1022
1023                        self.nodes.insert(parent.id, parent);
1024
1025                        Some(parent_id)
1026                    }
1027                }
1028            } else {
1029                self.nodes.insert(node.id, node);
1030                None
1031            }
1032        } else {
1033            None
1034        }
1035    }
1036}
1037
1038impl<K, T, M, S> SemiIndependentWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
1039where
1040    K: Hash + Copy + Eq + Ord,
1041    T: IndependentContents,
1042    S: BuildHasher + Default + Clone,
1043{
1044    #[cfg_attr(debug_assertions, contract(
1045        ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1046        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1047        ensures(old(self.roots.clone()) == self.roots),
1048        ensures(old(self.active) == self.active),
1049        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1050        invariant(self.validate())
1051    ))]
1052    #[inline]
1053    fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1054        self.nodes
1055            .get_mut(id)
1056            .map(|node| callback(&mut node.contents))
1057    }
1058}
1059
1060#[cfg(feature = "rkyv")]
1061impl<K, T, S> ArchivedDependentNode<K, T, S>
1062where
1063    K: Archive + Hash + Copy + Eq + Ord,
1064    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1065    T: Archive,
1066    S: BuildHasher + Default + Clone,
1067{
1068    #[inline]
1069    fn validate(&self) -> bool {
1070        (if let ArchivedOption::Some(from) = &self.from {
1071            !self.to.contains(from)
1072        } else {
1073            true
1074        }) && self.from != Some(self.id)
1075            && !self.to.contains(&self.id)
1076    }
1077}
1078
1079#[cfg(feature = "rkyv")]
1080impl<K, T, S> Node<K::Archived, T::Archived> for ArchivedDependentNode<K, T, S>
1081where
1082    K: Archive + Hash + Copy + Eq + Ord,
1083    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1084    T: Archive,
1085    S: BuildHasher + Default + Clone,
1086{
1087    type From = ArchivedOption<K::Archived>;
1088    type To = ArchivedIndexSet<K::Archived>;
1089
1090    #[inline]
1091    fn id(&self) -> K::Archived {
1092        self.id
1093    }
1094    #[inline]
1095    fn from(&self) -> &Self::From {
1096        &self.from
1097    }
1098    #[inline]
1099    fn to(&self) -> &Self::To {
1100        &self.to
1101    }
1102    #[inline]
1103    fn is_active(&self) -> bool {
1104        self.active
1105    }
1106    #[inline]
1107    fn contents(&self) -> &T::Archived {
1108        &self.contents
1109    }
1110}
1111
1112#[cfg(feature = "rkyv")]
1113impl<K, T, M, S> ArchivedDependentWeave<K, T, M, S>
1114where
1115    K: Archive + Hash + Copy + Eq + Ord,
1116    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1117    T: Archive,
1118    M: Archive,
1119    S: BuildHasher + Default + Clone,
1120{
1121    fn validate(&self) -> bool {
1122        let mut scratchpad = Vec::with_capacity(self.nodes.len());
1123        let mut scratchpad_set = HashSet::with_capacity(self.nodes.len());
1124
1125        self.roots
1126            .iter()
1127            .all(move |value| self.nodes.contains_key(value))
1128            && self
1129                .active
1130                .as_ref()
1131                .is_none_or(|active| self.nodes.contains_key(active))
1132            && self
1133                .bookmarked
1134                .iter()
1135                .all(move |value| self.nodes.contains_key(value))
1136            && self.nodes.iter().all(|(key, value)| {
1137                value.validate()
1138                    && value.id == *key
1139                    && value
1140                        .from
1141                        .as_ref()
1142                        .is_none_or(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
1143                    && value.to.iter().all(|v| {
1144                        self.nodes
1145                            .get(v)
1146                            .is_some_and(|p| p.from.as_ref() == Some(key))
1147                    })
1148                    && value.from.is_none() == self.roots.contains(key)
1149                    && value.active == (self.active == Some(*key))
1150                    && value.bookmarked == self.bookmarked.contains(key)
1151            })
1152            && !archived_detect_cycles(
1153                &self.nodes,
1154                self.roots.iter().copied(),
1155                &mut scratchpad,
1156                &mut scratchpad_set,
1157            )
1158    }
1159}
1160
1161#[cfg(feature = "rkyv")]
1162// SAFETY:
1163// All fields are safe to access and no unsafe functions are called
1164unsafe impl<K, T, M, S, C> Verify<C> for ArchivedDependentWeave<K, T, M, S>
1165where
1166    K: Archive + Hash + Copy + Eq + Ord,
1167    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1168    T: Archive,
1169    M: Archive,
1170    S: BuildHasher + Default + Clone,
1171    C: Fallible + ?Sized,
1172    C::Error: Source,
1173{
1174    fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
1175        if !self.validate() {
1176            fail!(ValidationError)
1177        }
1178
1179        Ok(())
1180    }
1181}
1182
1183#[cfg(feature = "rkyv")]
1184impl<K, T, M, S> ImmutableWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1185    for ArchivedDependentWeave<K, T, M, S>
1186where
1187    K: Archive + Hash + Copy + Eq + Ord,
1188    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1189    T: Archive,
1190    M: Archive,
1191    S: BuildHasher + Default + Clone,
1192{
1193    type Nodes = ArchivedHashMap<K::Archived, ArchivedDependentNode<K, T, S>>;
1194    type Roots = ArchivedIndexSet<K::Archived>;
1195
1196    #[inline]
1197    fn len(&self) -> usize {
1198        self.nodes.len()
1199    }
1200    #[inline]
1201    fn is_empty(&self) -> bool {
1202        self.nodes.is_empty()
1203    }
1204    #[inline]
1205    fn nodes(&self) -> &Self::Nodes {
1206        &self.nodes
1207    }
1208    #[inline]
1209    fn roots(&self) -> &Self::Roots {
1210        &self.roots
1211    }
1212    #[inline]
1213    fn contains(&self, id: &K::Archived) -> bool {
1214        self.nodes.contains_key(id)
1215    }
1216    #[inline]
1217    fn contains_active(&self, id: &K::Archived) -> bool {
1218        self.active == Some(*id)
1219    }
1220    #[inline]
1221    fn get_node(&self, id: &K::Archived) -> Option<&ArchivedDependentNode<K, T, S>> {
1222        self.nodes.get(id)
1223    }
1224    #[inline]
1225    fn get_node_parents(&self, id: &K::Archived) -> Option<&ArchivedOption<K::Archived>> {
1226        self.nodes.get(id).map(|node| &node.from)
1227    }
1228    #[inline]
1229    fn get_node_children(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
1230        self.nodes.get(id).map(|node| &node.to)
1231    }
1232    fn get_ordered_node_identifiers(&self, output: &mut Vec<K::Archived>) {
1233        output.clear();
1234
1235        let mut scratchpad = Vec::with_capacity(self.len());
1236        let mut scratchpad_2 = Vec::with_capacity(self.len());
1237
1238        for root in self.roots.iter() {
1239            archived_topological_sort(
1240                &self.nodes,
1241                *root,
1242                &mut scratchpad,
1243                &mut scratchpad_2,
1244                output,
1245            );
1246        }
1247    }
1248    fn get_ordered_node_identifiers_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
1249        output.clear();
1250
1251        if self.nodes.contains_key(id) {
1252            let mut scratchpad = Vec::with_capacity(self.len());
1253            let mut scratchpad_2 = Vec::with_capacity(self.len());
1254
1255            archived_topological_sort(&self.nodes, *id, &mut scratchpad, &mut scratchpad_2, output);
1256        }
1257    }
1258    fn get_active_path(&self, output: &mut Vec<K::Archived>) {
1259        output.clear();
1260
1261        if let ArchivedOption::Some(active) = self.active {
1262            archived_path_to_root(&self.nodes, active, output);
1263        }
1264    }
1265    fn get_path_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
1266        output.clear();
1267
1268        if self.nodes.contains_key(id) {
1269            archived_path_to_root(&self.nodes, *id, output);
1270        }
1271    }
1272}
1273
1274#[cfg(feature = "rkyv")]
1275impl<K, T, M, S>
1276    ImmutableMetadataWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived, M::Archived>
1277    for ArchivedDependentWeave<K, T, M, S>
1278where
1279    K: Archive + Hash + Copy + Eq + Ord,
1280    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1281    T: Archive,
1282    M: Archive,
1283    S: BuildHasher + Default + Clone,
1284{
1285    #[inline]
1286    fn metadata(&self) -> &M::Archived {
1287        &self.metadata
1288    }
1289}
1290
1291#[cfg(feature = "rkyv")]
1292impl<K, T, M, S>
1293    ImmutableBookmarkableWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1294    for ArchivedDependentWeave<K, T, M, S>
1295where
1296    K: Archive + Hash + Copy + Eq + Ord,
1297    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1298    T: Archive,
1299    M: Archive,
1300    S: BuildHasher + Default + Clone,
1301{
1302    type Bookmarks = ArchivedIndexSet<K::Archived>;
1303
1304    #[inline]
1305    fn bookmarks(&self) -> &Self::Bookmarks {
1306        &self.bookmarked
1307    }
1308    #[inline]
1309    fn contains_bookmark(&self, id: &K::Archived) -> bool {
1310        self.bookmarked.contains(id)
1311    }
1312}
1313
1314#[cfg(feature = "rkyv")]
1315impl<K, T, M, S>
1316    ImmutableActiveSingularWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1317    for ArchivedDependentWeave<K, T, M, S>
1318where
1319    K: Archive + Hash + Copy + Eq + Ord,
1320    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1321    T: Archive,
1322    M: Archive,
1323    S: BuildHasher + Default + Clone,
1324{
1325    #[inline]
1326    fn active(&self) -> Option<K::Archived> {
1327        match self.active {
1328            ArchivedOption::Some(active) => Some(active),
1329            ArchivedOption::None => None,
1330        }
1331    }
1332}
1333
1334fn path_to_root<K, T, S>(
1335    nodes: &HashMap<K, DependentNode<K, T, S>, S>,
1336    mut id: K,
1337    thread: &mut Vec<K>,
1338) where
1339    K: Hash + Copy + Eq + Ord,
1340    S: BuildHasher + Default + Clone,
1341{
1342    thread.push(id);
1343
1344    while let Some(parent) = nodes[&id].from {
1345        thread.push(parent);
1346        id = parent;
1347    }
1348}
1349
1350fn topological_sort<K, N, T, S>(
1351    nodes: &HashMap<K, N, S>,
1352    id: K,
1353    scratchpad: &mut Vec<K>,
1354    identifiers: &mut Vec<K>,
1355) where
1356    K: Hash + Copy + Eq + Ord,
1357    N: Node<K, T, From = Option<K>, To = IndexSet<K, S>>,
1358    S: BuildHasher + Default + Clone,
1359{
1360    scratchpad.push(id);
1361
1362    while let Some(id) = scratchpad.pop() {
1363        identifiers.push(id);
1364        scratchpad.extend(nodes[&id].to().into_iter().rev().copied());
1365    }
1366}
1367fn detect_cycles<K, N, T, S>(
1368    nodes: &HashMap<K, N, S>,
1369    roots: impl Iterator<Item = K>,
1370    scratchpad: &mut Vec<K>,
1371    scratchpad_set: &mut HashSet<K, S>,
1372) -> bool
1373where
1374    K: Hash + Copy + Eq + Ord,
1375    N: Node<K, T, From = Option<K>, To = IndexSet<K, S>>,
1376    S: BuildHasher + Default + Clone,
1377{
1378    scratchpad.extend(roots);
1379
1380    while let Some(id) = scratchpad.pop() {
1381        if !scratchpad_set.insert(id) {
1382            return true;
1383        }
1384        scratchpad.extend(nodes[&id].to().into_iter().rev().copied());
1385    }
1386
1387    scratchpad_set.len() != nodes.len()
1388}
1389
1390#[cfg(feature = "rkyv")]
1391fn archived_path_to_root<K, T, S>(
1392    nodes: &ArchivedHashMap<K::Archived, ArchivedDependentNode<K, T, S>>,
1393    mut id: K::Archived,
1394    thread: &mut Vec<K::Archived>,
1395) where
1396    K: Archive + Hash + Copy + Eq + Ord,
1397    <K as Archive>::Archived: Hash + Copy + Eq + Ord,
1398    T: Archive,
1399    S: BuildHasher + Default + Clone,
1400{
1401    thread.push(id);
1402
1403    while let ArchivedOption::Some(parent) = nodes[&id].from {
1404        thread.push(parent);
1405        id = parent;
1406    }
1407}
1408
1409#[cfg(feature = "rkyv")]
1410fn archived_topological_sort<K, N, T>(
1411    nodes: &ArchivedHashMap<K, N>,
1412    id: K,
1413    scratchpad: &mut Vec<K>,
1414    scratchpad_2: &mut Vec<K>,
1415    identifiers: &mut Vec<K>,
1416) where
1417    K: Hash + Copy + Eq + Ord,
1418    N: Node<K, T, From = ArchivedOption<K>, To = ArchivedIndexSet<K>>,
1419{
1420    scratchpad.push(id);
1421
1422    while let Some(id) = scratchpad.pop() {
1423        identifiers.push(id);
1424        scratchpad_2.extend(nodes[&id].to().iter().copied());
1425        scratchpad_2.reverse();
1426        scratchpad.append(scratchpad_2);
1427    }
1428}
1429
1430#[cfg(feature = "rkyv")]
1431fn archived_detect_cycles<K, N, T, S>(
1432    nodes: &ArchivedHashMap<K, N>,
1433    roots: impl Iterator<Item = K>,
1434    scratchpad: &mut Vec<K>,
1435    scratchpad_set: &mut HashSet<K, S>,
1436) -> bool
1437where
1438    K: Hash + Copy + Eq + Ord,
1439    N: Node<K, T, From = ArchivedOption<K>, To = ArchivedIndexSet<K>>,
1440    S: BuildHasher + Default + Clone,
1441{
1442    scratchpad.extend(roots);
1443
1444    while let Some(id) = scratchpad.pop() {
1445        if !scratchpad_set.insert(id) {
1446            return true;
1447        }
1448        scratchpad.extend(nodes[&id].to().iter().copied());
1449    }
1450
1451    scratchpad_set.len() != nodes.len()
1452}