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(&self, id: &K) -> Option<&DependentNode<K, T, S>> {
393        self.nodes.get(id)
394    }
395    #[inline]
396    fn get_parents(&self, id: &K) -> Option<&Option<K>> {
397        self.nodes.get(id).map(|node| &node.from)
398    }
399    #[inline]
400    fn get_children(&self, id: &K) -> Option<&IndexSet<K, S>> {
401        self.nodes.get(id).map(|node| &node.to)
402    }
403    #[inline]
404    fn get_contents(&self, id: &K) -> Option<&T> {
405        self.nodes.get(id).map(|node| &node.contents)
406    }
407    #[cfg_attr(debug_assertions, contract(
408        ensures(output.len() == self.nodes.len()),
409        ensures(valid_topological_sort(&self.nodes, output)),
410        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
411        ensures(old(self.roots.clone()) == self.roots),
412        ensures(old(self.active) == self.active),
413        ensures(old(self.bookmarked.clone()) == self.bookmarked),
414        invariant(self.validate())
415    ))]
416    fn get_ordered_identifiers(&mut self, output: &mut Vec<K>) {
417        output.clear();
418
419        for root in &self.roots {
420            topological_sort(&self.nodes, *root, &mut self.scratchpad, output);
421        }
422    }
423    #[cfg_attr(debug_assertions, contract(
424        ensures(lacks_duplicates(output)),
425        ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
426        ensures(self.nodes.contains_key(id) || output.is_empty()),
427        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
428        ensures(old(self.roots.clone()) == self.roots),
429        ensures(old(self.active) == self.active),
430        ensures(old(self.bookmarked.clone()) == self.bookmarked),
431        invariant(self.validate())
432    ))]
433    fn get_ordered_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
434        output.clear();
435
436        if self.nodes.contains_key(id) {
437            topological_sort(&self.nodes, *id, &mut self.scratchpad, output);
438        }
439    }
440    #[cfg_attr(debug_assertions, contract(
441        ensures(self.active == output.first().copied()),
442        ensures(lacks_duplicates(output)),
443        ensures(valid_path(&self.nodes, output)),
444        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
445        ensures(old(self.roots.clone()) == self.roots),
446        ensures(old(self.active) == self.active),
447        ensures(old(self.bookmarked.clone()) == self.bookmarked),
448        invariant(self.validate())
449    ))]
450    fn get_active_path(&mut self, output: &mut Vec<K>) {
451        output.clear();
452
453        if let Some(active) = self.active {
454            path_to_root(&self.nodes, active, output);
455        }
456    }
457    #[cfg_attr(debug_assertions, contract(
458        ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
459        ensures(self.nodes.contains_key(id) || output.is_empty()),
460        ensures(lacks_duplicates(output)),
461        ensures(valid_path(&self.nodes, output)),
462        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
463        ensures(old(self.roots.clone()) == self.roots),
464        ensures(old(self.active) == self.active),
465        ensures(old(self.bookmarked.clone()) == self.bookmarked),
466        invariant(self.validate())
467    ))]
468    fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
469        output.clear();
470
471        if self.nodes.contains_key(id) {
472            path_to_root(&self.nodes, *id, output);
473        }
474    }
475    #[cfg_attr(debug_assertions, contract(
476        ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
477        ensures(!ret || old(!self.nodes.contains_key(&node.id))),
478        ensures(!ret || self.nodes.contains_key(&old(node.id))),
479        ensures(!ret || old(node.active) == (self.active == Some(old(node.id)))),
480        ensures(!ret || old(node.bookmarked) == self.bookmarked.contains(&old(node.id))),
481        ensures(!ret || old(node.from.is_some()) || self.roots.contains(&old(node.id))),
482        ensures(!ret || old(node.from.is_none()) || old(self.roots.clone()) == self.roots),
483        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
484        ensures(ret || old(self.roots.clone()) == self.roots),
485        ensures(ret || old(self.active) == self.active),
486        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
487        invariant(self.validate())
488    ))]
489    fn insert(&mut self, node: DependentNode<K, T, S>) -> bool {
490        if self.nodes.contains_key(&node.id) || !node.validate() || !node.to.is_empty() {
491            return false;
492        }
493
494        if let Some(from) = &node.from {
495            match self.nodes.get_mut(from) {
496                Some(parent) => {
497                    parent.to.insert(node.id);
498                }
499                None => return false,
500            }
501        } else {
502            self.roots.insert(node.id);
503        }
504
505        if node.active {
506            if let Some(active) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
507                active.active = false;
508            }
509
510            self.active = Some(node.id);
511        }
512
513        if node.bookmarked {
514            self.bookmarked.insert(node.id);
515        }
516
517        self.nodes.insert(node.id, node);
518
519        true
520    }
521    #[cfg_attr(debug_assertions, contract(
522        ensures(!ret || value == self.contains_active(id)),
523        ensures(ret || old(self.active) == self.active),
524        ensures(ret == self.nodes.contains_key(id)),
525        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
526        ensures(old(self.roots.clone()) == self.roots),
527        ensures(old(self.bookmarked.clone()) == self.bookmarked),
528        invariant(self.validate())
529    ))]
530    fn set_active(&mut self, id: &K, value: bool) -> bool {
531        match self.nodes.get_mut(id) {
532            Some(node) => {
533                node.active = value;
534
535                if value {
536                    if self.active != Some(node.id)
537                        && let Some(active) = self.active.and_then(|id| self.nodes.get_mut(&id))
538                    {
539                        active.active = false;
540                    }
541
542                    self.active = Some(*id);
543                } else if self.active == Some(node.id) {
544                    self.active = node.from;
545
546                    if let Some(active) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
547                        active.active = true;
548                    }
549                }
550
551                true
552            }
553            None => false,
554        }
555    }
556    #[cfg_attr(debug_assertions, contract(
557        ensures(!self.nodes.contains_key(id)),
558        ensures(ret.is_some() == old(self.nodes.contains_key(id))),
559        ensures(ret.as_ref().is_none_or(|node| &node.id == id)),
560        ensures(ret.is_none() || old(self.nodes.len()) > self.nodes.len()),
561        ensures(ret.is_none() || old(self.bookmarked.len()) >= self.bookmarked.len()),
562        ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
563        ensures(ret.is_some() || old(self.roots.clone()) == self.roots),
564        ensures(ret.is_some() || old(self.active) == self.active),
565        ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
566        invariant(self.validate())
567    ))]
568    fn remove(&mut self, id: &K) -> Option<DependentNode<K, T, S>> {
569        let mut removed_node = None;
570        let mut removed_active = false;
571
572        self.scratchpad.push(*id);
573
574        while let Some(id) = self.scratchpad.pop() {
575            if let Some(node) = self.nodes.remove(&id) {
576                if node.from.is_none() {
577                    self.roots.shift_remove(&id);
578                }
579                if node.bookmarked {
580                    self.bookmarked.shift_remove(&id);
581                }
582                if node.active {
583                    self.active = None;
584                    removed_active = true;
585                }
586
587                if let Some(parent) = node.from.and_then(|id| self.nodes.get_mut(&id)) {
588                    parent.to.shift_remove(&id);
589                }
590                self.scratchpad.extend(node.to.iter().rev().copied());
591
592                if removed_node.is_none() {
593                    removed_node = Some(node);
594                }
595            }
596        }
597
598        if let Some(removed) = removed_node {
599            if removed_active {
600                self.active = removed.from;
601
602                if let Some(node) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
603                    node.active = true;
604                }
605            }
606            Some(removed)
607        } else {
608            None
609        }
610    }
611    #[cfg_attr(debug_assertions, contract(
612        ensures(!self.nodes.contains_key(id)),
613        ensures(ret == old(self.nodes.contains_key(id))),
614        ensures(!ret || old(self.nodes.len()) > self.nodes.len()),
615        ensures(!ret || old(self.bookmarked.len()) >= self.bookmarked.len()),
616        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
617        ensures(ret || old(self.roots.clone()) == self.roots),
618        ensures(ret || old(self.active) == self.active),
619        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
620        invariant(self.validate())
621    ))]
622    fn remove_tracked(
623        &mut self,
624        id: &K,
625        mut on_removal: impl FnMut(DependentNode<K, T, S>),
626    ) -> bool {
627        let removed_node_parent = self.nodes.get(id).map(|node| node.from);
628        let mut removed_active = false;
629
630        self.scratchpad.push(*id);
631
632        while let Some(id) = self.scratchpad.pop() {
633            if let Some(node) = self.nodes.remove(&id) {
634                if node.from.is_none() {
635                    self.roots.shift_remove(&id);
636                }
637                if node.bookmarked {
638                    self.bookmarked.shift_remove(&id);
639                }
640                if node.active {
641                    self.active = None;
642                    removed_active = true;
643                }
644
645                if let Some(parent) = node.from.and_then(|id| self.nodes.get_mut(&id)) {
646                    parent.to.shift_remove(&id);
647                }
648                self.scratchpad.extend(node.to.iter().rev().copied());
649
650                on_removal(node);
651            }
652        }
653
654        if let Some(parent) = removed_node_parent {
655            if removed_active {
656                self.active = parent;
657
658                if let Some(node) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
659                    node.active = true;
660                }
661            }
662            true
663        } else {
664            false
665        }
666    }
667    #[cfg_attr(debug_assertions, contract(
668        ensures(self.nodes.is_empty()),
669        ensures(self.validate())
670    ))]
671    fn clear(&mut self) {
672        self.nodes.clear();
673        self.roots.clear();
674        self.active = None;
675        self.bookmarked.clear();
676    }
677}
678
679impl<K, T, M, S> DependentWeave<K, T, M, S>
680where
681    K: Hash + Copy + Eq + Ord,
682    S: BuildHasher + Default + Clone,
683{
684    /// Validates that the weave is internally consistent.
685    pub fn validate(&self) -> bool {
686        let mut scratchpad = Vec::with_capacity(self.nodes.len());
687        let mut scratchpad_set = HashSet::with_capacity_and_hasher(self.nodes.len(), S::default());
688
689        self.scratchpad.is_empty()
690            && self
691                .roots
692                .iter()
693                .all(move |value| self.nodes.contains_key(value))
694            && self
695                .active
696                .as_ref()
697                .is_none_or(|active| self.nodes.contains_key(active))
698            && self
699                .bookmarked
700                .iter()
701                .all(move |value| self.nodes.contains_key(value))
702            && self.nodes.iter().all(|(key, value)| {
703                value.validate()
704                    && value.id == *key
705                    && value
706                        .from
707                        .as_ref()
708                        .is_none_or(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
709                    && value.to.iter().all(|v| {
710                        self.nodes
711                            .get(v)
712                            .is_some_and(|p| p.from.as_ref() == Some(key))
713                    })
714                    && value.from.is_none() == self.roots.contains(key)
715                    && value.active == (self.active == Some(*key))
716                    && value.bookmarked == self.bookmarked.contains(key)
717            })
718            && !detect_cycles(
719                &self.nodes,
720                self.roots.iter().copied(),
721                &mut scratchpad,
722                &mut scratchpad_set,
723            )
724    }
725}
726
727impl<K, T, M, S> MetadataWeave<K, DependentNode<K, T, S>, T, M> for DependentWeave<K, T, M, S>
728where
729    K: Hash + Copy + Eq + Ord,
730    S: BuildHasher + Default + Clone,
731{
732    #[inline]
733    fn metadata(&self) -> &M {
734        &self.metadata
735    }
736    #[cfg_attr(debug_assertions, contract(
737        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
738        ensures(old(self.roots.clone()) == self.roots),
739        ensures(old(self.active) == self.active),
740        ensures(old(self.bookmarked.clone()) == self.bookmarked),
741        invariant(self.validate())
742    ))]
743    #[inline]
744    fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
745        callback(&mut self.metadata)
746    }
747}
748
749impl<K, T, M, S> BookmarkableWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
750where
751    K: Hash + Copy + Eq + Ord,
752    S: BuildHasher + Default + Clone,
753{
754    type Bookmarks = IndexSet<K, S>;
755
756    #[inline]
757    fn bookmarks(&self) -> &Self::Bookmarks {
758        &self.bookmarked
759    }
760    #[inline]
761    fn contains_bookmark(&self, id: &K) -> bool {
762        self.bookmarked.contains(id)
763    }
764    #[cfg_attr(debug_assertions, contract(
765        ensures(!ret || value == self.bookmarked.contains(id)),
766        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
767        ensures(ret == self.nodes.contains_key(id)),
768        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
769        ensures(old(self.roots.clone()) == self.roots),
770        ensures(old(self.active) == self.active),
771        invariant(self.validate())
772    ))]
773    fn set_bookmarked(&mut self, id: &K, value: bool) -> bool {
774        match self.nodes.get_mut(id) {
775            Some(node) => {
776                node.bookmarked = value;
777                if value {
778                    self.bookmarked.insert(node.id);
779                } else {
780                    self.bookmarked.shift_remove(id);
781                }
782
783                true
784            }
785            None => false,
786        }
787    }
788}
789
790impl<K, T, M, S> SortableWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
791where
792    K: Hash + Copy + Eq + Ord,
793    S: BuildHasher + Default + Clone,
794{
795    #[cfg_attr(debug_assertions, contract(
796        ensures(ret == self.nodes.contains_key(id)),
797        ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
798        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
799        ensures(old(self.roots.clone()) == self.roots),
800        ensures(old(self.active) == self.active),
801        ensures(old(self.bookmarked.clone()) == self.bookmarked),
802        invariant(self.validate())
803    ))]
804    fn sort_children_by(
805        &mut self,
806        id: &K,
807        mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
808    ) -> bool {
809        if let Some(mut node) = self.nodes.remove(id) {
810            node.to.sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
811            self.nodes.insert(node.id, node);
812
813            true
814        } else {
815            false
816        }
817    }
818    #[cfg_attr(debug_assertions, contract(
819        ensures(ret == self.nodes.contains_key(id)),
820        ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
821        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
822        ensures(old(self.roots.clone()) == self.roots),
823        ensures(old(self.active) == self.active),
824        ensures(old(self.bookmarked.clone()) == self.bookmarked),
825        invariant(self.validate())
826    ))]
827    fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
828        if let Some(node) = self.nodes.get_mut(id) {
829            node.to.sort_by(cmp);
830
831            true
832        } else {
833            false
834        }
835    }
836    #[cfg_attr(debug_assertions, contract(
837        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
838        ensures(old(self.roots.clone()) == self.roots),
839        ensures(old(self.active) == self.active),
840        ensures(old(self.bookmarked.clone()) == self.bookmarked),
841        invariant(self.validate())
842    ))]
843    fn sort_roots_by(
844        &mut self,
845        mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
846    ) {
847        self.roots
848            .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
849    }
850    #[cfg_attr(debug_assertions, contract(
851        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
852        ensures(old(self.roots.clone()) == self.roots),
853        ensures(old(self.active) == self.active),
854        ensures(old(self.bookmarked.clone()) == self.bookmarked),
855        invariant(self.validate())
856    ))]
857    fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
858        self.roots.sort_by(cmp);
859    }
860}
861
862impl<K, T, M, S> SortableBookmarkableWeave<K, DependentNode<K, T, S>, T>
863    for DependentWeave<K, T, M, S>
864where
865    K: Hash + Copy + Eq + Ord,
866    S: BuildHasher + Default + Clone,
867{
868    #[cfg_attr(debug_assertions, contract(
869        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
870        ensures(old(self.roots.clone()) == self.roots),
871        ensures(old(self.active) == self.active),
872        ensures(old(self.bookmarked.clone()) == self.bookmarked),
873        invariant(self.validate())
874    ))]
875    fn sort_bookmarks_by(
876        &mut self,
877        mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
878    ) {
879        self.bookmarked
880            .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
881    }
882    #[cfg_attr(debug_assertions, contract(
883        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
884        ensures(old(self.roots.clone()) == self.roots),
885        ensures(old(self.active) == self.active),
886        ensures(old(self.bookmarked.clone()) == self.bookmarked),
887        invariant(self.validate())
888    ))]
889    fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
890        self.bookmarked.sort_by(cmp);
891    }
892}
893
894impl<K, T, M, S> ActiveSingularWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
895where
896    K: Hash + Copy + Eq + Ord,
897    S: BuildHasher + Default + Clone,
898{
899    #[inline]
900    fn active(&self) -> Option<K> {
901        self.active
902    }
903}
904
905impl<K, T, M, S> DiscreteWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
906where
907    K: Hash + Copy + Eq + Ord,
908    T: DiscreteContents,
909    S: BuildHasher + Default + Clone,
910{
911    #[cfg_attr(debug_assertions, contract(
912        ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
913        ensures(!ret || self.nodes.contains_key(id)),
914        ensures(!ret || self.nodes.contains_key(&new_id)),
915        ensures(!ret || old(!self.nodes.contains_key(&new_id))),
916        ensures(!ret || self.nodes[id].to.contains(&new_id) && self.nodes[id].to.len() == 1),
917        ensures(!ret || self.nodes[&new_id].from == Some(*id)),
918        ensures(!ret || old(self.nodes.get(id).map(|n| n.to.clone())).unwrap() == self.nodes[&new_id].to),
919        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
920        ensures(old(self.roots.clone()) == self.roots),
921        ensures(old(self.active) == self.active),
922        ensures(old(self.bookmarked.clone()) == self.bookmarked),
923        invariant(self.validate())
924    ))]
925    fn split(&mut self, id: &K, at: usize, new_id: K) -> bool {
926        if self.nodes.contains_key(&new_id) || *id == new_id {
927            return false;
928        }
929
930        if let Some(mut node) = self.nodes.remove(id) {
931            match node.contents.split(at) {
932                DiscreteContentResult::Two(left, right) => {
933                    let left_node = DependentNode {
934                        id: node.id,
935                        from: node.from,
936                        to: IndexSet::from_iter([new_id]),
937                        active: node.active,
938                        bookmarked: node.bookmarked,
939                        contents: left,
940                    };
941
942                    node.from = Some(node.id);
943                    node.id = new_id;
944                    node.contents = right;
945                    node.active = false;
946                    node.bookmarked = false;
947
948                    for child in &node.to {
949                        let child = self.nodes.get_mut(child).unwrap();
950                        child.from = Some(node.id);
951                    }
952
953                    self.nodes.insert(left_node.id, left_node);
954                    self.nodes.insert(node.id, node);
955
956                    true
957                }
958                DiscreteContentResult::One(content) => {
959                    node.contents = content;
960                    self.nodes.insert(node.id, node);
961                    false
962                }
963            }
964        } else {
965            false
966        }
967    }
968    #[cfg_attr(debug_assertions, contract(
969        ensures(ret.is_none() || old(self.nodes.len()) - 1 == self.nodes.len()),
970        ensures(ret.is_none() || !self.nodes.contains_key(id)),
971        ensures(ret.is_none() || old(self.nodes.contains_key(id))),
972        ensures(ret.is_none() || !old(self.contains_active(id)) || old(self.contains_active(id)) && self.contains_active(&ret.unwrap())),
973        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),
974        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),
975        ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.to.clone())).unwrap() == self.nodes[&ret.unwrap()].to),
976        ensures(ret.is_none() || ret.unwrap() == old(self.nodes.get(id).and_then(|node| node.from)).unwrap()),
977        ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
978        ensures(ret.is_some() || old(self.active) == self.active),
979        ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
980        ensures(old(self.roots.clone()) == self.roots),
981        invariant(self.validate())
982    ))]
983    fn merge_with_parent(&mut self, id: &K) -> Option<K> {
984        if let Some(mut node) = self.nodes.remove(id) {
985            if let Some(mut parent) = node.from.as_ref().and_then(|id| self.nodes.remove(id)) {
986                if parent.to.len() > 1 {
987                    self.nodes.insert(parent.id, parent);
988                    self.nodes.insert(node.id, node);
989                    return None;
990                }
991
992                match parent.contents.merge(node.contents) {
993                    DiscreteContentResult::Two(left, right) => {
994                        parent.contents = left;
995                        node.contents = right;
996                        self.nodes.insert(parent.id, parent);
997                        self.nodes.insert(node.id, node);
998                        None
999                    }
1000                    DiscreteContentResult::One(content) => {
1001                        parent.contents = content;
1002                        parent.to = node.to;
1003
1004                        for child in &parent.to {
1005                            let child = self.nodes.get_mut(child).unwrap();
1006                            child.from = Some(parent.id);
1007                        }
1008
1009                        if node.active {
1010                            parent.active = true;
1011                            self.active = Some(parent.id);
1012                        }
1013
1014                        let parent_id = parent.id;
1015
1016                        if node.bookmarked && !parent.bookmarked {
1017                            parent.bookmarked = true;
1018                            assert!(
1019                                self.bookmarked
1020                                    .replace_index(
1021                                        self.bookmarked.get_index_of(&node.id).unwrap(),
1022                                        parent.id,
1023                                    )
1024                                    .is_ok(),
1025                                "Should be unreachable"
1026                            );
1027                        } else {
1028                            self.bookmarked.shift_remove(&node.id);
1029                        }
1030
1031                        self.nodes.insert(parent.id, parent);
1032
1033                        Some(parent_id)
1034                    }
1035                }
1036            } else {
1037                self.nodes.insert(node.id, node);
1038                None
1039            }
1040        } else {
1041            None
1042        }
1043    }
1044}
1045
1046impl<K, T, M, S> SemiIndependentWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
1047where
1048    K: Hash + Copy + Eq + Ord,
1049    T: IndependentContents,
1050    S: BuildHasher + Default + Clone,
1051{
1052    #[cfg_attr(debug_assertions, contract(
1053        ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1054        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1055        ensures(old(self.roots.clone()) == self.roots),
1056        ensures(old(self.active) == self.active),
1057        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1058        invariant(self.validate())
1059    ))]
1060    #[inline]
1061    fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1062        self.nodes
1063            .get_mut(id)
1064            .map(|node| callback(&mut node.contents))
1065    }
1066}
1067
1068#[cfg(feature = "rkyv")]
1069impl<K, T, S> ArchivedDependentNode<K, T, S>
1070where
1071    K: Archive + Hash + Copy + Eq + Ord,
1072    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1073    T: Archive,
1074    S: BuildHasher + Default + Clone,
1075{
1076    #[inline]
1077    fn validate(&self) -> bool {
1078        (if let ArchivedOption::Some(from) = &self.from {
1079            !self.to.contains(from)
1080        } else {
1081            true
1082        }) && self.from != Some(self.id)
1083            && !self.to.contains(&self.id)
1084    }
1085}
1086
1087#[cfg(feature = "rkyv")]
1088impl<K, T, S> Node<K::Archived, T::Archived> for ArchivedDependentNode<K, T, S>
1089where
1090    K: Archive + Hash + Copy + Eq + Ord,
1091    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1092    T: Archive,
1093    S: BuildHasher + Default + Clone,
1094{
1095    type From = ArchivedOption<K::Archived>;
1096    type To = ArchivedIndexSet<K::Archived>;
1097
1098    #[inline]
1099    fn id(&self) -> K::Archived {
1100        self.id
1101    }
1102    #[inline]
1103    fn from(&self) -> &Self::From {
1104        &self.from
1105    }
1106    #[inline]
1107    fn to(&self) -> &Self::To {
1108        &self.to
1109    }
1110    #[inline]
1111    fn is_active(&self) -> bool {
1112        self.active
1113    }
1114    #[inline]
1115    fn contents(&self) -> &T::Archived {
1116        &self.contents
1117    }
1118}
1119
1120#[cfg(feature = "rkyv")]
1121impl<K, T, M, S> ArchivedDependentWeave<K, T, M, S>
1122where
1123    K: Archive + Hash + Copy + Eq + Ord,
1124    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1125    T: Archive,
1126    M: Archive,
1127    S: BuildHasher + Default + Clone,
1128{
1129    fn validate(&self) -> bool {
1130        let mut scratchpad = Vec::with_capacity(self.nodes.len());
1131        let mut scratchpad_set = HashSet::with_capacity(self.nodes.len());
1132
1133        self.roots
1134            .iter()
1135            .all(move |value| self.nodes.contains_key(value))
1136            && self
1137                .active
1138                .as_ref()
1139                .is_none_or(|active| self.nodes.contains_key(active))
1140            && self
1141                .bookmarked
1142                .iter()
1143                .all(move |value| self.nodes.contains_key(value))
1144            && self.nodes.iter().all(|(key, value)| {
1145                value.validate()
1146                    && value.id == *key
1147                    && value
1148                        .from
1149                        .as_ref()
1150                        .is_none_or(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
1151                    && value.to.iter().all(|v| {
1152                        self.nodes
1153                            .get(v)
1154                            .is_some_and(|p| p.from.as_ref() == Some(key))
1155                    })
1156                    && value.from.is_none() == self.roots.contains(key)
1157                    && value.active == (self.active == Some(*key))
1158                    && value.bookmarked == self.bookmarked.contains(key)
1159            })
1160            && !archived_detect_cycles(
1161                &self.nodes,
1162                self.roots.iter().copied(),
1163                &mut scratchpad,
1164                &mut scratchpad_set,
1165            )
1166    }
1167}
1168
1169#[cfg(feature = "rkyv")]
1170// SAFETY:
1171// All fields are safe to access and no unsafe functions are called
1172unsafe impl<K, T, M, S, C> Verify<C> for ArchivedDependentWeave<K, T, M, S>
1173where
1174    K: Archive + Hash + Copy + Eq + Ord,
1175    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1176    T: Archive,
1177    M: Archive,
1178    S: BuildHasher + Default + Clone,
1179    C: Fallible + ?Sized,
1180    C::Error: Source,
1181{
1182    fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
1183        if !self.validate() {
1184            fail!(ValidationError)
1185        }
1186
1187        Ok(())
1188    }
1189}
1190
1191#[cfg(feature = "rkyv")]
1192impl<K, T, M, S> ImmutableWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1193    for ArchivedDependentWeave<K, T, M, S>
1194where
1195    K: Archive + Hash + Copy + Eq + Ord,
1196    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1197    T: Archive,
1198    M: Archive,
1199    S: BuildHasher + Default + Clone,
1200{
1201    type Nodes = ArchivedHashMap<K::Archived, ArchivedDependentNode<K, T, S>>;
1202    type Roots = ArchivedIndexSet<K::Archived>;
1203
1204    #[inline]
1205    fn len(&self) -> usize {
1206        self.nodes.len()
1207    }
1208    #[inline]
1209    fn is_empty(&self) -> bool {
1210        self.nodes.is_empty()
1211    }
1212    #[inline]
1213    fn nodes(&self) -> &Self::Nodes {
1214        &self.nodes
1215    }
1216    #[inline]
1217    fn roots(&self) -> &Self::Roots {
1218        &self.roots
1219    }
1220    #[inline]
1221    fn contains(&self, id: &K::Archived) -> bool {
1222        self.nodes.contains_key(id)
1223    }
1224    #[inline]
1225    fn contains_active(&self, id: &K::Archived) -> bool {
1226        self.active == Some(*id)
1227    }
1228    #[inline]
1229    fn get(&self, id: &K::Archived) -> Option<&ArchivedDependentNode<K, T, S>> {
1230        self.nodes.get(id)
1231    }
1232    #[inline]
1233    fn get_parents(&self, id: &K::Archived) -> Option<&ArchivedOption<K::Archived>> {
1234        self.nodes.get(id).map(|node| &node.from)
1235    }
1236    #[inline]
1237    fn get_children(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
1238        self.nodes.get(id).map(|node| &node.to)
1239    }
1240    #[inline]
1241    fn get_contents(&self, id: &K::Archived) -> Option<&T::Archived> {
1242        self.nodes.get(id).map(|node| &node.contents)
1243    }
1244    fn get_ordered_identifiers(&self, output: &mut Vec<K::Archived>) {
1245        output.clear();
1246
1247        let mut scratchpad = Vec::with_capacity(self.len());
1248        let mut scratchpad_2 = Vec::with_capacity(self.len());
1249
1250        for root in self.roots.iter() {
1251            archived_topological_sort(
1252                &self.nodes,
1253                *root,
1254                &mut scratchpad,
1255                &mut scratchpad_2,
1256                output,
1257            );
1258        }
1259    }
1260    fn get_ordered_identifiers_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
1261        output.clear();
1262
1263        if self.nodes.contains_key(id) {
1264            let mut scratchpad = Vec::with_capacity(self.len());
1265            let mut scratchpad_2 = Vec::with_capacity(self.len());
1266
1267            archived_topological_sort(&self.nodes, *id, &mut scratchpad, &mut scratchpad_2, output);
1268        }
1269    }
1270    fn get_active_path(&self, output: &mut Vec<K::Archived>) {
1271        output.clear();
1272
1273        if let ArchivedOption::Some(active) = self.active {
1274            archived_path_to_root(&self.nodes, active, output);
1275        }
1276    }
1277    fn get_path_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
1278        output.clear();
1279
1280        if self.nodes.contains_key(id) {
1281            archived_path_to_root(&self.nodes, *id, output);
1282        }
1283    }
1284}
1285
1286#[cfg(feature = "rkyv")]
1287impl<K, T, M, S>
1288    ImmutableMetadataWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived, M::Archived>
1289    for ArchivedDependentWeave<K, T, M, S>
1290where
1291    K: Archive + Hash + Copy + Eq + Ord,
1292    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1293    T: Archive,
1294    M: Archive,
1295    S: BuildHasher + Default + Clone,
1296{
1297    #[inline]
1298    fn metadata(&self) -> &M::Archived {
1299        &self.metadata
1300    }
1301}
1302
1303#[cfg(feature = "rkyv")]
1304impl<K, T, M, S>
1305    ImmutableBookmarkableWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1306    for ArchivedDependentWeave<K, T, M, S>
1307where
1308    K: Archive + Hash + Copy + Eq + Ord,
1309    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1310    T: Archive,
1311    M: Archive,
1312    S: BuildHasher + Default + Clone,
1313{
1314    type Bookmarks = ArchivedIndexSet<K::Archived>;
1315
1316    #[inline]
1317    fn bookmarks(&self) -> &Self::Bookmarks {
1318        &self.bookmarked
1319    }
1320    #[inline]
1321    fn contains_bookmark(&self, id: &K::Archived) -> bool {
1322        self.bookmarked.contains(id)
1323    }
1324}
1325
1326#[cfg(feature = "rkyv")]
1327impl<K, T, M, S>
1328    ImmutableActiveSingularWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1329    for ArchivedDependentWeave<K, T, M, S>
1330where
1331    K: Archive + Hash + Copy + Eq + Ord,
1332    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1333    T: Archive,
1334    M: Archive,
1335    S: BuildHasher + Default + Clone,
1336{
1337    #[inline]
1338    fn active(&self) -> Option<K::Archived> {
1339        match self.active {
1340            ArchivedOption::Some(active) => Some(active),
1341            ArchivedOption::None => None,
1342        }
1343    }
1344}
1345
1346fn path_to_root<K, T, S>(
1347    nodes: &HashMap<K, DependentNode<K, T, S>, S>,
1348    mut id: K,
1349    thread: &mut Vec<K>,
1350) where
1351    K: Hash + Copy + Eq + Ord,
1352    S: BuildHasher + Default + Clone,
1353{
1354    thread.push(id);
1355
1356    while let Some(parent) = nodes[&id].from {
1357        thread.push(parent);
1358        id = parent;
1359    }
1360}
1361
1362fn topological_sort<K, N, T, S>(
1363    nodes: &HashMap<K, N, S>,
1364    id: K,
1365    scratchpad: &mut Vec<K>,
1366    identifiers: &mut Vec<K>,
1367) where
1368    K: Hash + Copy + Eq + Ord,
1369    N: Node<K, T, From = Option<K>, To = IndexSet<K, S>>,
1370    S: BuildHasher + Default + Clone,
1371{
1372    scratchpad.push(id);
1373
1374    while let Some(id) = scratchpad.pop() {
1375        identifiers.push(id);
1376        scratchpad.extend(nodes[&id].to().into_iter().rev().copied());
1377    }
1378}
1379fn detect_cycles<K, N, T, S>(
1380    nodes: &HashMap<K, N, S>,
1381    roots: impl Iterator<Item = K>,
1382    scratchpad: &mut Vec<K>,
1383    scratchpad_set: &mut HashSet<K, S>,
1384) -> bool
1385where
1386    K: Hash + Copy + Eq + Ord,
1387    N: Node<K, T, From = Option<K>, To = IndexSet<K, S>>,
1388    S: BuildHasher + Default + Clone,
1389{
1390    scratchpad.extend(roots);
1391
1392    while let Some(id) = scratchpad.pop() {
1393        if !scratchpad_set.insert(id) {
1394            return true;
1395        }
1396        scratchpad.extend(nodes[&id].to().into_iter().rev().copied());
1397    }
1398
1399    scratchpad_set.len() != nodes.len()
1400}
1401
1402#[cfg(feature = "rkyv")]
1403fn archived_path_to_root<K, T, S>(
1404    nodes: &ArchivedHashMap<K::Archived, ArchivedDependentNode<K, T, S>>,
1405    mut id: K::Archived,
1406    thread: &mut Vec<K::Archived>,
1407) where
1408    K: Archive + Hash + Copy + Eq + Ord,
1409    <K as Archive>::Archived: Hash + Copy + Eq + Ord,
1410    T: Archive,
1411    S: BuildHasher + Default + Clone,
1412{
1413    thread.push(id);
1414
1415    while let ArchivedOption::Some(parent) = nodes[&id].from {
1416        thread.push(parent);
1417        id = parent;
1418    }
1419}
1420
1421#[cfg(feature = "rkyv")]
1422fn archived_topological_sort<K, N, T>(
1423    nodes: &ArchivedHashMap<K, N>,
1424    id: K,
1425    scratchpad: &mut Vec<K>,
1426    scratchpad_2: &mut Vec<K>,
1427    identifiers: &mut Vec<K>,
1428) where
1429    K: Hash + Copy + Eq + Ord,
1430    N: Node<K, T, From = ArchivedOption<K>, To = ArchivedIndexSet<K>>,
1431{
1432    scratchpad.push(id);
1433
1434    while let Some(id) = scratchpad.pop() {
1435        identifiers.push(id);
1436        scratchpad_2.extend(nodes[&id].to().iter().copied());
1437        scratchpad_2.reverse();
1438        scratchpad.append(scratchpad_2);
1439    }
1440}
1441
1442#[cfg(feature = "rkyv")]
1443fn archived_detect_cycles<K, N, T, S>(
1444    nodes: &ArchivedHashMap<K, N>,
1445    roots: impl Iterator<Item = K>,
1446    scratchpad: &mut Vec<K>,
1447    scratchpad_set: &mut HashSet<K, S>,
1448) -> bool
1449where
1450    K: Hash + Copy + Eq + Ord,
1451    N: Node<K, T, From = ArchivedOption<K>, To = ArchivedIndexSet<K>>,
1452    S: BuildHasher + Default + Clone,
1453{
1454    scratchpad.extend(roots);
1455
1456    while let Some(id) = scratchpad.pop() {
1457        if !scratchpad_set.insert(id) {
1458            return true;
1459        }
1460        scratchpad.extend(nodes[&id].to().iter().copied());
1461    }
1462
1463    scratchpad_set.len() != nodes.len()
1464}