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