Skip to main content

universal_weave/dependent/
mod.rs

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