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