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