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