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