Skip to main content

universal_weave/dependent/
mod.rs

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