Skip to main content

universal_weave/independent/
mod.rs

1//! [`IndependentWeave`] is a DAG-based [`Weave`] where each [`Node`] does *not* depend on the contents of the previous Node.
2
3use alloc::vec::Vec;
4use core::{
5    cmp::Ordering,
6    hash::{BuildHasher, Hash},
7    mem,
8};
9
10use hashbrown::{HashMap, HashSet};
11use indexmap::IndexSet;
12use scratchpads::{Scratchpad, ScratchpadMap};
13
14#[cfg(debug_assertions)]
15use contracts::contract;
16
17#[cfg(feature = "rkyv")]
18use rkyv::{
19    Archive, Deserialize, Serialize,
20    bytecheck::Verify,
21    collections::swiss_table::{ArchivedHashMap, ArchivedHashSet, ArchivedIndexSet},
22    rancor::{Fallible, Source, fail},
23    with::Skip,
24};
25
26#[cfg(feature = "serde")]
27use serde::{
28    Deserialize as SerdeDeserialize, Deserializer as SerdeDeserializer,
29    Serialize as SerdeSerialize, de::Error as _,
30};
31
32use crate::{
33    ActivePathWeave, BookmarkableWeave, DiscreteContentResult, DiscreteContents, DiscreteWeave,
34    IndependentContents, MetadataWeave, Node, SemiIndependentWeave, SortableBookmarkableWeave,
35    SortableWeave, Weave, ancestor_subgraph, ancestor_subgraph_reaches,
36    contract::valid_topology,
37    dependent::{DependentNode, DependentWeave},
38    descendant_subgraph, descendant_subgraph_reaches, longest_candidate_path_to_root,
39    shortest_path_to_ancestor, topological_sort, topological_sort_subgraph,
40};
41
42#[cfg(debug_assertions)]
43use crate::contract::{lacks_duplicates, valid_path, valid_topological_sort};
44
45#[cfg(feature = "rkyv")]
46use crate::{
47    ImmutableActivePathWeave, ImmutableBookmarkableWeave, ImmutableMetadataWeave, ImmutableWeave,
48    archived_ancestor_subgraph, archived_descendant_subgraph,
49    archived_longest_candidate_path_to_root, archived_shortest_path_to_ancestor,
50    archived_topological_sort, archived_topological_sort_subgraph,
51    contract::archived_valid_topology,
52};
53
54#[cfg(any(feature = "serde", feature = "rkyv"))]
55use crate::contract::ValidationError;
56
57#[derive(Default, Debug, Clone)]
58#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
59#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
60/// A [`Node`] in a [`IndependentWeave`] document.
61#[must_use]
62pub struct IndependentNode<K, T, S>
63where
64    K: Hash + Copy + Eq + Ord,
65    T: IndependentContents,
66    S: BuildHasher + Default + Clone,
67{
68    /// The node's unique identifier.
69    pub id: K,
70    /// The identifiers corresponding to the node's parents.
71    #[cfg_attr(
72        feature = "serde",
73        serde(bound(
74            serialize = "IndexSet<K, S>: SerdeSerialize",
75            deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
76        ))
77    )]
78    pub from: IndexSet<K, S>,
79    /// The identifiers corresponding to the node's children.
80    #[cfg_attr(
81        feature = "serde",
82        serde(bound(
83            serialize = "IndexSet<K, S>: SerdeSerialize",
84            deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
85        ))
86    )]
87    pub to: IndexSet<K, S>,
88    /// If the node should be considered active.
89    ///
90    /// Unlike [`DependentWeave`], [`IndependentWeave`] considers all nodes within an active path to be active.
91    pub active: bool,
92    /// If the node is bookmarked.
93    pub bookmarked: bool,
94    /// The node's contents.
95    pub contents: T,
96}
97
98#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
99impl<K, T, S> PartialEq for IndependentNode<K, T, S>
100where
101    K: Hash + Copy + Eq + Ord,
102    T: IndependentContents + PartialEq,
103    S: BuildHasher + Default + Clone,
104{
105    #[inline]
106    fn eq(&self, other: &Self) -> bool {
107        self.id == other.id
108            && self.from.len() == other.from.len()
109            && self.to.len() == other.to.len()
110            && self.active == other.active
111            && self.bookmarked == other.bookmarked
112            && self.from.iter().zip(other.from.iter()).all(|(a, b)| a == b)
113            && self.to.iter().zip(other.to.iter()).all(|(a, b)| a == b)
114            && self.contents == other.contents
115    }
116}
117
118#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
119impl<K, T, S> Eq for IndependentNode<K, T, S>
120where
121    K: Hash + Copy + Eq + Ord,
122    T: IndependentContents + Eq,
123    S: BuildHasher + Default + Clone,
124{
125}
126
127impl<K, T, S> IndependentNode<K, T, S>
128where
129    K: Hash + Copy + Eq + Ord,
130    T: IndependentContents,
131    S: BuildHasher + Default + Clone,
132{
133    fn validate(&self) -> bool {
134        self.from.is_disjoint(&self.to)
135            && !self.from.contains(&self.id)
136            && !self.to.contains(&self.id)
137    }
138}
139
140impl<K, T, S> Node<K, T> for IndependentNode<K, T, S>
141where
142    K: Hash + Copy + Eq + Ord,
143    T: IndependentContents,
144    S: BuildHasher + Default + Clone,
145{
146    type From = IndexSet<K, S>;
147    type To = IndexSet<K, S>;
148
149    #[inline]
150    fn id(&self) -> K {
151        self.id
152    }
153    #[inline]
154    fn from(&self) -> &Self::From {
155        &self.from
156    }
157    #[inline]
158    fn to(&self) -> &Self::To {
159        &self.to
160    }
161    #[inline]
162    fn is_active(&self) -> bool {
163        self.active
164    }
165    #[inline]
166    fn contents(&self) -> &T {
167        &self.contents
168    }
169}
170
171impl<K, T, S> From<DependentNode<K, T, S>> for IndependentNode<K, T, S>
172where
173    K: Hash + Copy + Eq + Ord,
174    T: IndependentContents,
175    S: BuildHasher + Default + Clone,
176{
177    #[inline]
178    fn from(value: DependentNode<K, T, S>) -> Self {
179        Self {
180            id: value.id,
181            from: IndexSet::from_iter(value.from),
182            to: value.to,
183            active: value.active,
184            bookmarked: value.bookmarked,
185            contents: value.contents,
186        }
187    }
188}
189
190impl<K, T, S> TryFrom<IndependentNode<K, T, S>> for DependentNode<K, T, S>
191where
192    K: Hash + Copy + Eq + Ord,
193    T: IndependentContents,
194    S: BuildHasher + Default + Clone,
195{
196    type Error = IndependentNode<K, T, S>;
197
198    #[inline]
199    fn try_from(value: IndependentNode<K, T, S>) -> Result<Self, Self::Error> {
200        if value.from.len() < 2 {
201            Ok(Self {
202                id: value.id,
203                from: value.from.into_iter().next(),
204                to: value.to,
205                active: value.active,
206                bookmarked: value.bookmarked,
207                contents: value.contents,
208            })
209        } else {
210            Err(value)
211        }
212    }
213}
214
215/// A DAG-based [`Weave`] where each [`Node`] does *not* depend on the contents of the previous Node.
216///
217/// However, this additional flexibility results in worse performance and memory usage characteristics:
218/// - Memory overhead is approximately doubled.
219/// - Updating node activation has a worst-case time complexity of O(V + E) rather than [`DependentWeave`]'s O(1), so bulk operations must be done carefully to prevent accidentally quadratic behavior.
220///
221/// 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.
222#[derive(Default, Debug, Clone)]
223#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
224#[cfg_attr(feature = "serde", derive(SerdeSerialize))]
225#[cfg_attr(feature = "rkyv", rkyv(bytecheck(verify)))]
226#[must_use]
227pub struct IndependentWeave<K, T, M, S>
228where
229    K: Hash + Copy + Eq + Ord,
230    T: IndependentContents,
231    S: BuildHasher + Default + Clone,
232{
233    #[cfg_attr(
234        feature = "serde",
235        serde(bound(
236            serialize = "HashMap<K, IndependentNode<K, T, S>, S>: SerdeSerialize",
237            deserialize = "HashMap<K, IndependentNode<K, T, S>, S>: SerdeDeserialize<'de>"
238        ))
239    )]
240    nodes: HashMap<K, IndependentNode<K, T, S>, S>,
241    #[cfg_attr(
242        feature = "serde",
243        serde(bound(
244            serialize = "IndexSet<K, S>: SerdeSerialize",
245            deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
246        ))
247    )]
248    roots: IndexSet<K, S>,
249    #[cfg_attr(
250        feature = "serde",
251        serde(bound(
252            serialize = "HashSet<K, S>: SerdeSerialize",
253            deserialize = "HashSet<K, S>: SerdeDeserialize<'de>"
254        ))
255    )]
256    active: HashSet<K, S>,
257    #[cfg_attr(
258        feature = "serde",
259        serde(bound(
260            serialize = "IndexSet<K, S>: SerdeSerialize",
261            deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
262        ))
263    )]
264    bookmarked: IndexSet<K, S>,
265
266    #[cfg_attr(feature = "rkyv", rkyv(with = Skip))]
267    #[cfg_attr(feature = "serde", serde(skip))]
268    scratchpad: Scratchpad,
269
270    /// The metadata associated with the weave.
271    pub metadata: M,
272}
273
274#[cfg(feature = "serde")]
275#[derive(SerdeDeserialize)]
276#[serde(rename = "IndependentWeave")]
277struct ProxyIndependentWeave<K, T, M, S>
278where
279    K: Hash + Copy + Eq + Ord,
280    T: IndependentContents,
281    S: BuildHasher + Default + Clone,
282{
283    #[serde(bound(
284        serialize = "HashMap<K, IndependentNode<K, T, S>, S>: SerdeSerialize",
285        deserialize = "HashMap<K, IndependentNode<K, T, S>, S>: SerdeDeserialize<'de>"
286    ))]
287    nodes: HashMap<K, IndependentNode<K, T, S>, S>,
288    #[serde(bound(
289        serialize = "IndexSet<K, S>: SerdeSerialize",
290        deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
291    ))]
292    roots: IndexSet<K, S>,
293    #[serde(bound(
294        serialize = "HashSet<K, S>: SerdeSerialize",
295        deserialize = "HashSet<K, S>: SerdeDeserialize<'de>"
296    ))]
297    active: HashSet<K, S>,
298    #[serde(bound(
299        serialize = "IndexSet<K, S>: SerdeSerialize",
300        deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
301    ))]
302    bookmarked: IndexSet<K, S>,
303    metadata: M,
304}
305
306#[cfg(feature = "serde")]
307#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
308impl<'de, K, T, M, S> SerdeDeserialize<'de> for IndependentWeave<K, T, M, S>
309where
310    K: Hash + Copy + Eq + Ord + SerdeDeserialize<'de>,
311    T: IndependentContents + SerdeDeserialize<'de>,
312    M: SerdeDeserialize<'de>,
313    S: BuildHasher + Default + Clone,
314{
315    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
316    where
317        D: SerdeDeserializer<'de>,
318    {
319        let proxy = ProxyIndependentWeave::deserialize(deserializer)?;
320        let weave = Self {
321            nodes: proxy.nodes,
322            roots: proxy.roots,
323            active: proxy.active,
324            bookmarked: proxy.bookmarked,
325            scratchpad: Scratchpad::new(),
326            metadata: proxy.metadata,
327        };
328
329        if weave.validate() {
330            Ok(weave)
331        } else {
332            Err(D::Error::custom(ValidationError))
333        }
334    }
335}
336
337#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
338impl<K, T, M, S> PartialEq for IndependentWeave<K, T, M, S>
339where
340    K: Hash + Copy + Eq + Ord,
341    T: IndependentContents + PartialEq,
342    M: PartialEq,
343    S: BuildHasher + Default + Clone,
344{
345    #[inline]
346    fn eq(&self, other: &Self) -> bool {
347        self.roots.len() == other.roots.len()
348            && self.bookmarked.len() == other.bookmarked.len()
349            && self.nodes.len() == other.nodes.len()
350            && self.active == other.active
351            && self
352                .roots
353                .iter()
354                .zip(other.roots.iter())
355                .all(|(a, b)| a == b)
356            && self
357                .bookmarked
358                .iter()
359                .zip(other.bookmarked.iter())
360                .all(|(a, b)| a == b)
361            && self.nodes == other.nodes
362            && self.metadata == other.metadata
363    }
364}
365
366#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
367impl<K, T, M, S> Eq for IndependentWeave<K, T, M, S>
368where
369    K: Hash + Copy + Eq + Ord,
370    T: IndependentContents + Eq,
371    M: Eq,
372    S: BuildHasher + Default + Clone,
373{
374}
375
376impl<K, T, M, S> IndependentWeave<K, T, M, S>
377where
378    K: Hash + Copy + Eq + Ord,
379    T: IndependentContents,
380    S: BuildHasher + Default + Clone,
381{
382    /// Creates a new, empty [`IndependentWeave`] with at least the specified capacity.
383    #[cfg_attr(debug_assertions, contract(
384        ensures(ret.nodes.is_empty()),
385        ensures(ret.validate())
386    ))]
387    pub fn with_capacity(capacity: usize, metadata: M) -> Self {
388        let nodes = HashMap::with_capacity_and_hasher(capacity, S::default());
389        let capacity = nodes.capacity();
390
391        Self {
392            nodes,
393            roots: IndexSet::with_capacity_and_hasher(capacity, S::default()),
394            active: HashSet::with_capacity_and_hasher(capacity, S::default()),
395            bookmarked: IndexSet::with_capacity_and_hasher(capacity, S::default()),
396            scratchpad: Scratchpad::new(),
397            metadata,
398        }
399    }
400    /// Returns the worst-case number of nodes that the weave can hold without reallocating.
401    ///
402    /// May be lower than `self.len()`.
403    #[inline]
404    pub fn capacity(&self) -> usize {
405        self.nodes
406            .capacity()
407            .min(self.roots.capacity())
408            .min(self.active.capacity())
409            .min(self.bookmarked.capacity())
410    }
411    /// Reserves capacity for at least `additional` more nodes.
412    #[cfg_attr(debug_assertions, contract(
413        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
414        ensures(old(self.roots.clone()) == self.roots),
415        ensures(old(self.active.clone()) == self.active),
416        ensures(old(self.bookmarked.clone()) == self.bookmarked),
417        invariant(self.validate())
418    ))]
419    pub fn reserve(&mut self, additional: usize) {
420        self.nodes.reserve(additional);
421        self.roots
422            .reserve(self.nodes.capacity().saturating_sub(self.roots.len()));
423        self.active
424            .reserve(self.nodes.capacity().saturating_sub(self.active.len()));
425        self.bookmarked
426            .reserve(self.nodes.capacity().saturating_sub(self.bookmarked.len()));
427    }
428    /// Shrinks the capacity of the weave with a lower limit.
429    #[cfg_attr(debug_assertions, contract(
430        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
431        ensures(old(self.roots.clone()) == self.roots),
432        ensures(old(self.active.clone()) == self.active),
433        ensures(old(self.bookmarked.clone()) == self.bookmarked),
434        invariant(self.validate())
435    ))]
436    pub fn shrink_to(&mut self, min_capacity: usize) {
437        self.nodes.shrink_to(min_capacity);
438        self.roots.shrink_to(min_capacity);
439        self.active.shrink_to(min_capacity);
440        self.bookmarked.shrink_to(min_capacity);
441    }
442    #[allow(
443        clippy::too_many_lines,
444        reason = "Cannot be split into smaller functions"
445    )]
446    #[cfg_attr(debug_assertions, contract(
447        ensures(ret == self.nodes.contains_key(id)),
448        ensures(!ret || value == self.active.contains(id)),
449        ensures(self.validate())
450    ))]
451    fn update_node_activity_in_place(&mut self, id: &K, value: bool) -> bool {
452        let at_end = if let Some(node) = self.nodes.get(id) {
453            if node.active == value {
454                return true;
455            }
456
457            if value {
458                (node.from.is_empty() && self.active.is_empty())
459                    || node.from.iter().any(|parent| {
460                        self.active.contains(parent)
461                            && self.nodes[parent]
462                                .to
463                                .iter()
464                                .all(|child| !self.active.contains(child))
465                    })
466            } else {
467                node.to.iter().all(|child| !self.active.contains(child))
468            }
469        } else {
470            return false;
471        };
472
473        let node = self.nodes.get_mut(id).unwrap();
474        node.active = value;
475        if value {
476            self.active.insert(node.id);
477        } else {
478            self.active.remove(id);
479        }
480
481        if at_end {
482            return true;
483        }
484
485        if value {
486            let has_descendants = !node.to.is_empty();
487
488            let guard = self.scratchpad.guard();
489
490            let mut stack = guard.vec();
491            let mut closure = guard.set(S::default());
492            let mut closure_roots = guard.vec();
493
494            ancestor_subgraph(&self.nodes, *id, &mut stack, &mut closure, |id| {
495                closure_roots.push(id);
496            });
497
498            let mut topological = guard.vec_with_capacity(closure.len());
499            let mut scratchpad_map = guard.map_with_capacity(closure.len(), S::default());
500            let mut scratchpad_map_2: ScratchpadMap<'_, K, ((usize, usize), Option<K>), S> =
501                guard.map_with_capacity(closure.len(), S::default());
502            let mut scratchpad_set = guard.set(S::default());
503
504            for root in closure_roots.drain(..) {
505                topological_sort_subgraph(
506                    &self.nodes,
507                    |id| closure.contains(id),
508                    root,
509                    &mut stack,
510                    |id| topological.push(id),
511                    &mut scratchpad_map,
512                );
513            }
514
515            for id in topological.iter().copied() {
516                let node = &self.nodes[&id];
517
518                let best_parent = node
519                    .from
520                    .iter()
521                    .map(|id| (id, scratchpad_map_2[id].0)) // score: (connectors, active)
522                    .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
523
524                let (parent, score) = if let Some((parent, mut score)) = best_parent {
525                    if node.active {
526                        score.1 = score.1.strict_add(1);
527                    } else {
528                        score.0 = score.0.strict_add(1);
529                    }
530
531                    (Some(parent), score)
532                } else {
533                    (None, if node.active { (0, 1) } else { (1, 0) })
534                };
535
536                scratchpad_map_2.insert(id, (score, parent.copied()));
537            }
538
539            let mut current = Some(id);
540
541            while let Some(id) = current {
542                scratchpad_set.insert(*id);
543                current = scratchpad_map_2
544                    .get(id)
545                    .and_then(|(_, parent)| parent.as_ref());
546            }
547
548            closure.clear();
549            topological.clear();
550            scratchpad_map.clear();
551            scratchpad_map_2.clear();
552
553            if self.active.len() != 1 && has_descendants {
554                descendant_subgraph(&self.nodes, *id, &mut stack, &mut closure);
555
556                let has_active_descendant = if closure.len() >= self.active.len() {
557                    self.active.iter().any(|a| a != id && closure.contains(a))
558                } else {
559                    closure.iter().any(|d| d != id && self.active.contains(d))
560                };
561
562                if has_active_descendant {
563                    topological_sort_subgraph(
564                        &self.nodes,
565                        |id| closure.contains(id),
566                        *id,
567                        &mut stack,
568                        |id| topological.push(id),
569                        &mut scratchpad_map,
570                    );
571
572                    for id in topological.drain(..).rev() {
573                        let node = &self.nodes[&id];
574
575                        let best_child = node
576                            .to
577                            .iter()
578                            .map(|id| (id, scratchpad_map_2[id].0)) // score: (connectors, active)
579                            .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
580
581                        let (child, score) = if let Some((child, mut score)) = best_child {
582                            if node.active {
583                                score.1 = score.1.strict_add(1);
584                            } else {
585                                score.0 = score.0.strict_add(1);
586                            }
587
588                            (Some(child), score)
589                        } else {
590                            (None, if node.active { (0, 1) } else { (1, 0) })
591                        };
592
593                        scratchpad_map_2.insert(id, (score, child.copied()));
594                    }
595
596                    let mut current = Some(id);
597
598                    while let Some(id) = current {
599                        scratchpad_set.insert(*id);
600
601                        let (score, successor) = &scratchpad_map_2[id];
602                        current = if score.1 > usize::from(self.nodes[id].active) {
603                            successor.as_ref()
604                        } else {
605                            None
606                        };
607                    }
608                }
609            }
610
611            let mut disjoint = topological;
612
613            disjoint.extend(
614                self.active
615                    .iter()
616                    .filter(|id| !scratchpad_set.contains(*id))
617                    .copied(),
618            );
619
620            for id in disjoint.drain(..) {
621                self.nodes.get_mut(&id).unwrap().active = false;
622                self.active.remove(&id);
623            }
624
625            disjoint.extend(
626                scratchpad_set
627                    .iter()
628                    .filter(|id| !self.active.contains(*id))
629                    .copied(),
630            );
631
632            for id in disjoint.drain(..) {
633                self.nodes.get_mut(&id).unwrap().active = true;
634                self.active.insert(id);
635            }
636        } else {
637            self.fix_orphaned_activations();
638        }
639
640        true
641    }
642    #[cfg_attr(debug_assertions, contract(
643        ensures(self.validate())
644    ))]
645    fn fix_orphaned_activations(&mut self) {
646        if self.active.is_empty() {
647            return;
648        }
649
650        let guard = self.scratchpad.guard();
651
652        let mut stack = guard.vec();
653        let mut closure = guard.set_with_capacity(self.active.len(), S::default());
654
655        for id in self.active.iter().copied() {
656            ancestor_subgraph(&self.nodes, id, &mut stack, &mut closure, |_| {});
657        }
658
659        let mut topological = guard.vec_with_capacity(closure.len());
660        let mut scratchpad_map = guard.map_with_capacity(closure.len(), S::default());
661
662        for root in self
663            .roots
664            .iter()
665            .filter(|id| closure.contains(*id))
666            .copied()
667        {
668            topological_sort_subgraph(
669                &self.nodes,
670                |id| closure.contains(id),
671                root,
672                &mut stack,
673                |id| topological.push(id),
674                &mut scratchpad_map,
675            );
676        }
677
678        scratchpad_map.clear();
679
680        let mut candidate_path = guard.vec_with_capacity(self.active.len());
681
682        longest_candidate_path_to_root(
683            &self.nodes,
684            &topological,
685            |id| self.active.contains(id),
686            &mut scratchpad_map,
687            |id| candidate_path.push(id),
688        );
689
690        topological.clear();
691        let mut disjoint = topological;
692
693        closure.clear();
694        let mut candidate_path_set = closure;
695
696        candidate_path_set.extend(candidate_path.drain(..));
697
698        disjoint.extend(
699            self.active
700                .iter()
701                .filter(|id| !candidate_path_set.contains(*id))
702                .copied(),
703        );
704
705        for orphan in disjoint.drain(..) {
706            self.active.remove(&orphan);
707            if let Some(node) = self.nodes.get_mut(&orphan) {
708                node.active = false;
709            }
710        }
711    }
712    #[cfg_attr(debug_assertions, contract(
713        ensures(!ret || value || !self.active.contains(id) || (old(self.active.clone()) == self.active && self.nodes[id].to.iter().any(|id| self.contains_active(id)))),
714        ensures(!ret || !value || self.contains_active(id) && !self.nodes[id].to.iter().any(|id| self.active.contains(id))),
715        ensures(ret || old(self.active.clone()) == self.active),
716        ensures(ret == self.nodes.contains_key(id)),
717        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
718        ensures(old(self.roots.clone()) == self.roots),
719        ensures(old(self.bookmarked.clone()) == self.bookmarked),
720        invariant(self.validate())
721    ))]
722    #[allow(
723        clippy::too_many_lines,
724        reason = "Cannot be split into smaller functions"
725    )]
726    #[allow(clippy::missing_panics_doc, reason = "Should never panic")]
727    /// Sets the active status of a node with the specified identifier, using identical activation behavior to [`DependentWeave`].
728    pub fn set_active_dependent_semantics(&mut self, id: &K, value: bool) -> bool {
729        if value {
730            if let Some(node) = self.nodes.get(id) {
731                if node.active && !node.to.iter().any(|id| self.active.contains(id)) {
732                    return true;
733                }
734
735                if !node.active
736                    && ((node.from.is_empty() && self.active.is_empty())
737                        || node.from.iter().any(|parent| {
738                            self.active.contains(parent)
739                                && self.nodes[parent]
740                                    .to
741                                    .iter()
742                                    .all(|child| !self.active.contains(child))
743                        }))
744                {
745                    self.nodes.get_mut(id).unwrap().active = true;
746                    self.active.insert(*id);
747                    return true;
748                }
749            } else {
750                return false;
751            }
752
753            let guard = self.scratchpad.guard();
754
755            let mut stack = guard.vec();
756            let mut closure = guard.set(S::default());
757            let mut closure_roots = guard.vec();
758
759            ancestor_subgraph(&self.nodes, *id, &mut stack, &mut closure, |id| {
760                closure_roots.push(id);
761            });
762
763            let mut topological = guard.vec_with_capacity(closure.len());
764            let mut scratchpad_map = guard.map_with_capacity(closure.len(), S::default());
765            let mut scratchpad_map_2: ScratchpadMap<'_, K, ((usize, usize), Option<K>), S> =
766                guard.map_with_capacity(closure.len(), S::default());
767
768            for root in closure_roots.drain(..) {
769                topological_sort_subgraph(
770                    &self.nodes,
771                    |id| closure.contains(id),
772                    root,
773                    &mut stack,
774                    |id| topological.push(id), // topological order
775                    &mut scratchpad_map,
776                );
777            }
778
779            for id in topological.drain(..) {
780                let node = &self.nodes[&id];
781
782                let best_parent = node
783                    .from
784                    .iter()
785                    .map(|id| (id, scratchpad_map_2[id].0)) // score: (connectors, active)
786                    .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
787
788                let (parent, score) = if let Some((parent, mut score)) = best_parent {
789                    if node.active {
790                        score.1 = score.1.strict_add(1);
791                    } else {
792                        score.0 = score.0.strict_add(1);
793                    }
794
795                    (Some(parent), score)
796                } else {
797                    (None, if node.active { (0, 1) } else { (1, 0) })
798                };
799
800                scratchpad_map_2.insert(id, (score, parent.copied()));
801            }
802
803            closure.clear();
804            let mut scratchpad_set = closure;
805
806            let mut disjoint = topological;
807
808            let mut current = Some(id);
809
810            while let Some(id) = current {
811                scratchpad_set.insert(*id);
812                current = scratchpad_map_2
813                    .get(id)
814                    .and_then(|(_, parent)| parent.as_ref());
815            }
816
817            disjoint.extend(
818                self.active
819                    .iter()
820                    .filter(|id| !scratchpad_set.contains(*id))
821                    .copied(),
822            );
823
824            for id in disjoint.drain(..) {
825                self.nodes.get_mut(&id).unwrap().active = false;
826                self.active.remove(&id);
827            }
828
829            disjoint.extend(
830                scratchpad_set
831                    .iter()
832                    .filter(|id| !self.active.contains(*id))
833                    .copied(),
834            );
835
836            for id in disjoint.drain(..) {
837                self.nodes.get_mut(&id).unwrap().active = true;
838                self.active.insert(id);
839            }
840        } else if let Some(node) = self.nodes.get_mut(id) {
841            if !node.active || node.to.iter().any(|id| self.active.contains(id)) {
842                return true;
843            }
844
845            node.active = false;
846            self.active.remove(&node.id);
847        } else {
848            return false;
849        }
850
851        true
852    }
853}
854
855impl<K, T, M, S> From<DependentWeave<K, T, M, S>> for IndependentWeave<K, T, M, S>
856where
857    K: Hash + Copy + Eq + Ord,
858    T: IndependentContents,
859    S: BuildHasher + Default + Clone,
860{
861    fn from(value: DependentWeave<K, T, M, S>) -> Self {
862        let mut output = Self {
863            active: HashSet::with_capacity_and_hasher(value.nodes.capacity(), S::default()),
864            nodes: {
865                let mut map =
866                    HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default());
867                map.extend(value.nodes.into_iter().map(|(id, mut node)| {
868                    node.active = false;
869                    (id, node.into())
870                }));
871
872                map
873            },
874            roots: value.roots,
875            bookmarked: value.bookmarked,
876            scratchpad: value.scratchpad,
877            metadata: value.metadata,
878        };
879
880        if let Some(active) = value.active {
881            output.set_active(&active, true);
882        }
883
884        debug_assert!(output.validate(), "Converted weave is malformed");
885
886        output
887    }
888}
889
890#[allow(clippy::panic_in_result_fn, reason = "Should never panic")]
891#[allow(clippy::unreachable, reason = "Should never panic")]
892impl<K, T, M, S> TryFrom<IndependentWeave<K, T, M, S>> for DependentWeave<K, T, M, S>
893where
894    K: Hash + Copy + Eq + Ord,
895    T: IndependentContents,
896    S: BuildHasher + Default + Clone,
897{
898    type Error = IndependentWeave<K, T, M, S>;
899
900    fn try_from(value: IndependentWeave<K, T, M, S>) -> Result<Self, Self::Error> {
901        if value.nodes.iter().all(|(_, node)| node.from.len() < 2) {
902            let mut active = None;
903
904            let output = Self {
905                nodes: {
906                    let mut map =
907                        HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default());
908                    map.extend(value.nodes.into_iter().map(|(id, mut node)| {
909                        node.active =
910                            node.active && !node.to.iter().any(|id| value.active.contains(id));
911                        if node.active {
912                            active = Some(id);
913                        }
914
915                        node.try_into()
916                            .map_or_else(|_| unreachable!(), |node| (id, node))
917                    }));
918
919                    map
920                },
921                roots: value.roots,
922                active,
923                bookmarked: value.bookmarked,
924                scratchpad: value.scratchpad,
925                metadata: value.metadata,
926            };
927
928            debug_assert!(output.validate(), "Converted weave is malformed");
929
930            Ok(output)
931        } else {
932            Err(value)
933        }
934    }
935}
936
937impl<K, T, M, S> Weave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
938where
939    K: Hash + Copy + Eq + Ord,
940    T: IndependentContents,
941    S: BuildHasher + Default + Clone,
942{
943    type Nodes = HashMap<K, IndependentNode<K, T, S>, S>;
944    type Roots = IndexSet<K, S>;
945
946    #[inline]
947    fn len(&self) -> usize {
948        self.nodes.len()
949    }
950    #[inline]
951    fn is_empty(&self) -> bool {
952        self.nodes.is_empty()
953    }
954    #[inline]
955    fn nodes(&self) -> &Self::Nodes {
956        &self.nodes
957    }
958    #[inline]
959    fn roots(&self) -> &Self::Roots {
960        &self.roots
961    }
962    #[inline]
963    fn contains(&self, id: &K) -> bool {
964        self.nodes.contains_key(id)
965    }
966    #[inline]
967    fn contains_active(&self, id: &K) -> bool {
968        self.active.contains(id)
969    }
970    #[inline]
971    fn get(&self, id: &K) -> Option<&IndependentNode<K, T, S>> {
972        self.nodes.get(id)
973    }
974    #[inline]
975    fn get_parents(&self, id: &K) -> Option<&IndexSet<K, S>> {
976        self.nodes.get(id).map(|node| &node.from)
977    }
978    #[inline]
979    fn get_children(&self, id: &K) -> Option<&IndexSet<K, S>> {
980        self.nodes.get(id).map(|node| &node.to)
981    }
982    #[inline]
983    fn get_contents(&self, id: &K) -> Option<&T> {
984        self.nodes.get(id).map(|node| &node.contents)
985    }
986    #[cfg_attr(debug_assertions, contract(
987        ensures(output.len() == self.nodes.len()),
988        ensures(valid_topological_sort(&self.nodes, output)),
989        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
990        ensures(old(self.roots.clone()) == self.roots),
991        ensures(old(self.active.clone()) == self.active),
992        ensures(old(self.bookmarked.clone()) == self.bookmarked),
993        invariant(self.validate())
994    ))]
995    fn get_ordered_identifiers(&mut self, output: &mut Vec<K>) {
996        output.clear();
997        output.reserve(self.nodes.len());
998
999        let guard = self.scratchpad.guard();
1000
1001        topological_sort(
1002            &self.nodes,
1003            self.roots.iter().copied(),
1004            &mut guard.vec_with_capacity(self.roots.len()),
1005            |id| output.push(id),
1006            &mut guard
1007                .map_with_capacity(self.nodes.len().strict_sub(self.roots.len()), S::default()),
1008        );
1009    }
1010    #[cfg_attr(debug_assertions, contract(
1011        ensures(lacks_duplicates(output)),
1012        ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1013        ensures(self.nodes.contains_key(id) || output.is_empty()),
1014        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1015        ensures(old(self.roots.clone()) == self.roots),
1016        ensures(old(self.active.clone()) == self.active),
1017        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1018        invariant(self.validate())
1019    ))]
1020    fn get_ordered_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
1021        output.clear();
1022
1023        if self.nodes.contains_key(id) {
1024            let guard = self.scratchpad.guard();
1025
1026            let mut stack = guard.vec();
1027            let mut descendants = guard.set(S::default());
1028
1029            descendant_subgraph(&self.nodes, *id, &mut stack, &mut descendants);
1030
1031            output.reserve(descendants.len());
1032
1033            topological_sort_subgraph(
1034                &self.nodes,
1035                |id| descendants.contains(id),
1036                *id,
1037                &mut stack,
1038                |id| output.push(id),
1039                &mut guard.map_with_capacity(descendants.len(), S::default()),
1040            );
1041        }
1042    }
1043    #[cfg_attr(debug_assertions, contract(
1044        ensures(output.len() == self.active.len()),
1045        ensures(output.iter().all(|i| self.active.contains(i))),
1046        ensures(lacks_duplicates(output)),
1047        ensures(valid_path(&self.nodes, output)),
1048        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1049        ensures(old(self.roots.clone()) == self.roots),
1050        ensures(old(self.active.clone()) == self.active),
1051        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1052        invariant(self.validate())
1053    ))]
1054    fn get_active_path(&mut self, output: &mut Vec<K>) {
1055        output.clear();
1056
1057        if self.active.is_empty() {
1058            return;
1059        }
1060
1061        output.reserve(self.active.len());
1062
1063        let guard = self.scratchpad.guard();
1064
1065        let mut stack = guard.vec();
1066        let mut topological_subgraph = guard.vec_with_capacity(self.active.len());
1067        let mut scratchpad_map = guard.map_with_capacity(self.active.len(), S::default());
1068
1069        for root in self
1070            .roots
1071            .iter()
1072            .filter(|id| self.active.contains(*id))
1073            .copied()
1074        {
1075            topological_sort_subgraph(
1076                &self.nodes,
1077                |id| self.active.contains(id),
1078                root,
1079                &mut stack,
1080                |id| topological_subgraph.push(id),
1081                &mut scratchpad_map,
1082            );
1083        }
1084
1085        scratchpad_map.clear();
1086
1087        longest_candidate_path_to_root(
1088            &self.nodes,
1089            &topological_subgraph,
1090            |id| self.active.contains(id),
1091            &mut scratchpad_map,
1092            |id| output.push(id),
1093        );
1094    }
1095    #[cfg_attr(debug_assertions, contract(
1096        ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1097        ensures(self.nodes.contains_key(id) || output.is_empty()),
1098        ensures(lacks_duplicates(output)),
1099        ensures(valid_path(&self.nodes, output)),
1100        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1101        ensures(old(self.roots.clone()) == self.roots),
1102        ensures(old(self.active.clone()) == self.active),
1103        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1104        invariant(self.validate())
1105    ))]
1106    fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
1107        output.clear();
1108        if !self.nodes.contains_key(id) {
1109            return;
1110        }
1111
1112        let guard = self.scratchpad.guard();
1113        let mut stack = guard.vec();
1114        let mut ancestors = guard.set(S::default());
1115        let mut root_ancestors = guard.vec();
1116
1117        ancestor_subgraph(&self.nodes, *id, &mut stack, &mut ancestors, |id| {
1118            root_ancestors.push(id);
1119        });
1120
1121        let mut active_topological_subgraph =
1122            guard.vec_with_capacity(self.active.len().min(ancestors.len()));
1123        let mut scratchpad_map =
1124            guard.map_with_capacity(self.active.len().min(ancestors.len()), S::default());
1125
1126        for root in root_ancestors
1127            .drain(..)
1128            .filter(|id| self.active.contains(id))
1129        {
1130            topological_sort_subgraph(
1131                &self.nodes,
1132                |id| self.active.contains(id) && ancestors.contains(id),
1133                root,
1134                &mut stack,
1135                |id| active_topological_subgraph.push(id),
1136                &mut scratchpad_map,
1137            );
1138        }
1139
1140        scratchpad_map.clear();
1141
1142        let mut reversed_path = guard.vec();
1143
1144        longest_candidate_path_to_root(
1145            &self.nodes,
1146            &active_topological_subgraph,
1147            |id| self.active.contains(id) && ancestors.contains(id),
1148            &mut scratchpad_map,
1149            |id| reversed_path.push(id),
1150        );
1151
1152        let mut scratchpad_map_2 = guard.map_with_capacity(ancestors.len(), S::default());
1153
1154        ancestors.clear();
1155        let mut scratchpad_set = ancestors;
1156
1157        if let Some(target) = reversed_path.first().copied() {
1158            shortest_path_to_ancestor(
1159                &self.nodes,
1160                id,
1161                |node| node.id == target,
1162                &mut stack,
1163                &mut scratchpad_map_2,
1164                &mut scratchpad_set,
1165                output,
1166            );
1167
1168            output.reverse();
1169            output.pop();
1170            output.extend_from_slice(&reversed_path);
1171        } else {
1172            shortest_path_to_ancestor(
1173                &self.nodes,
1174                id,
1175                |node| node.from.is_empty(),
1176                &mut stack,
1177                &mut scratchpad_map_2,
1178                &mut scratchpad_set,
1179                output,
1180            );
1181
1182            output.reverse();
1183        }
1184    }
1185    #[cfg_attr(debug_assertions, contract(
1186        ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1187        ensures(!ret || old(!self.nodes.contains_key(&node.id))),
1188        ensures(!ret || self.nodes.contains_key(&old(node.id))),
1189        ensures(!ret || old(node.active) == self.active.contains(&old(node.id)) || (!old(node.active) && self.active.contains(&old(node.id)) && old(node.to.iter().any(|c| self.active.contains(c))))),
1190        ensures(!ret || old(node.bookmarked) == self.bookmarked.contains(&old(node.id))),
1191        ensures(!ret || old(!node.from.is_empty()) || self.roots.contains(&old(node.id))),
1192        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1193        ensures(ret || old(self.roots.clone()) == self.roots),
1194        ensures(ret || old(self.active.clone()) == self.active),
1195        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1196        invariant(self.validate())
1197    ))]
1198    fn insert(&mut self, mut node: IndependentNode<K, T, S>) -> bool {
1199        if self.nodes.contains_key(&node.id)
1200            || !node.validate()
1201            || !node.from.iter().all(|id| self.nodes.contains_key(id))
1202            || !node.to.iter().all(|id| self.nodes.contains_key(id))
1203        {
1204            return false;
1205        }
1206
1207        if !node.to.is_empty() && !node.from.is_empty() {
1208            let guard = self.scratchpad.guard();
1209
1210            if ancestor_subgraph_reaches(
1211                &self.nodes,
1212                node.from.iter().copied(),
1213                |id| node.to.contains(id),
1214                &mut guard.vec_with_capacity(node.from.len()),
1215                &mut guard.set_with_capacity(node.from.len(), S::default()),
1216            ) {
1217                return false;
1218            }
1219        }
1220
1221        let root_index = if node.from.is_empty() {
1222            node.to
1223                .iter()
1224                .filter_map(|child| self.roots.get_index_of(child))
1225                .min()
1226        } else {
1227            None
1228        };
1229
1230        let mut detached_root = false;
1231
1232        for child in &node.to {
1233            let child = self.nodes.get_mut(child).unwrap();
1234
1235            if child.from.is_empty() {
1236                node.active |= child.active;
1237                detached_root = true;
1238            }
1239
1240            child.from.insert(node.id);
1241        }
1242
1243        if detached_root {
1244            self.roots.retain(|id| !node.to.contains(id));
1245        }
1246
1247        let extends_active = node.active
1248            && node.to.is_empty()
1249            && node.from.iter().map(|id| &self.nodes[id]).any(|parent| {
1250                parent.active && parent.to.iter().all(|child| !self.active.contains(child))
1251            });
1252
1253        if node.from.is_empty() {
1254            if let Some(index) = root_index {
1255                self.roots.shift_insert(index, node.id);
1256            } else {
1257                self.roots.insert(node.id);
1258            }
1259        } else {
1260            for parent in &node.from {
1261                let parent = self.nodes.get_mut(parent).unwrap();
1262                parent.to.insert(node.id);
1263            }
1264        }
1265
1266        if node.bookmarked {
1267            self.bookmarked.insert(node.id);
1268        }
1269
1270        let id = node.id;
1271        let active = node.active;
1272
1273        if !extends_active {
1274            node.active = false;
1275        }
1276
1277        self.nodes.insert(node.id, node);
1278
1279        if extends_active {
1280            self.active.insert(id);
1281        } else if active {
1282            self.update_node_activity_in_place(&id, true);
1283        }
1284
1285        true
1286    }
1287    #[cfg_attr(debug_assertions, contract(
1288        ensures(!ret || value == self.contains_active(id)),
1289        ensures(ret || old(self.active.clone()) == self.active),
1290        ensures(ret == self.nodes.contains_key(id)),
1291        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1292        ensures(old(self.roots.clone()) == self.roots),
1293        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1294        invariant(self.validate())
1295    ))]
1296    fn set_active(&mut self, id: &K, value: bool) -> bool {
1297        self.update_node_activity_in_place(id, value)
1298    }
1299    #[cfg_attr(debug_assertions, contract(
1300        ensures(!self.nodes.contains_key(id)),
1301        ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1302        ensures(ret.as_ref().is_none_or(|node| &node.id == id)),
1303        ensures(ret.is_none() || old(self.nodes.len()) > self.nodes.len()),
1304        ensures(ret.is_none() || old(self.active.len()) >= self.active.len()),
1305        ensures(ret.is_none() || old(self.bookmarked.len()) >= self.bookmarked.len()),
1306        ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1307        ensures(ret.is_some() || old(self.roots.clone()) == self.roots),
1308        ensures(ret.is_some() || old(self.active.clone()) == self.active),
1309        ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1310        invariant(self.validate())
1311    ))]
1312    fn remove(&mut self, id: &K) -> Option<IndependentNode<K, T, S>> {
1313        let node = self.nodes.remove(id)?;
1314
1315        if node.from.is_empty() {
1316            self.roots.shift_remove(id);
1317        } else {
1318            for parent in &node.from {
1319                if let Some(parent) = self.nodes.get_mut(parent) {
1320                    parent.to.shift_remove(id);
1321                }
1322            }
1323        }
1324
1325        let mut removed_active = node.active;
1326        let mut removed_bookmark = node.bookmarked;
1327
1328        if removed_active {
1329            self.active.remove(id);
1330        }
1331
1332        if node.to.is_empty() {
1333            if removed_bookmark {
1334                self.bookmarked.shift_remove(id);
1335            }
1336            return Some(node);
1337        }
1338
1339        {
1340            let guard = self.scratchpad.guard();
1341            let mut stack = guard.vec();
1342            let mut removed = guard.vec_with_capacity(node.to.len().strict_add(1));
1343            let mut remaining_parents = guard.map_with_capacity(node.to.len(), S::default());
1344
1345            removed.push(*id);
1346
1347            for child in node.to.iter().rev().copied() {
1348                let remaining = remaining_parents
1349                    .entry(child)
1350                    .or_insert_with(|| self.nodes[&child].from.len());
1351                *remaining = remaining.strict_sub(1);
1352
1353                if *remaining == 0 {
1354                    stack.push(child);
1355                }
1356            }
1357
1358            while let Some(id) = stack.pop() {
1359                let node = self.nodes.remove(&id).unwrap();
1360                removed.push(id);
1361
1362                removed_bookmark |= node.bookmarked;
1363                if node.active {
1364                    self.active.remove(&id);
1365                    removed_active = true;
1366                }
1367
1368                for child in node.to.iter().rev().copied() {
1369                    let remaining = remaining_parents
1370                        .entry(child)
1371                        .or_insert_with(|| self.nodes[&child].from.len());
1372                    *remaining = remaining.strict_sub(1);
1373
1374                    if *remaining == 0 {
1375                        stack.push(child);
1376                    }
1377                }
1378            }
1379
1380            if removed_active
1381                && !remaining_parents
1382                    .iter()
1383                    .any(|(child, remaining)| *remaining > 0 && self.active.contains(child))
1384            {
1385                removed_active = false;
1386            }
1387
1388            if removed.len() == 1 {
1389                for (child, _) in remaining_parents {
1390                    if let Some(child) = self.nodes.get_mut(&child) {
1391                        child.from.shift_remove(id);
1392                    }
1393                }
1394                if removed_bookmark {
1395                    self.bookmarked.shift_remove(id);
1396                }
1397            } else {
1398                let mut removed_set = guard.set_with_capacity(removed.len(), S::default());
1399                removed_set.extend(removed);
1400
1401                for (child, remaining) in remaining_parents {
1402                    if remaining > 0
1403                        && let Some(child) = self.nodes.get_mut(&child)
1404                    {
1405                        child.from.retain(|parent| !removed_set.contains(parent));
1406                    }
1407                }
1408
1409                if removed_bookmark {
1410                    self.bookmarked.retain(|id| !removed_set.contains(id));
1411                }
1412            }
1413        }
1414
1415        if removed_active {
1416            self.fix_orphaned_activations();
1417        }
1418
1419        Some(node)
1420    }
1421    #[cfg_attr(debug_assertions, contract(
1422        ensures(!self.nodes.contains_key(id)),
1423        ensures(ret == old(self.nodes.contains_key(id))),
1424        ensures(!ret || old(self.nodes.len()) > self.nodes.len()),
1425        ensures(!ret || old(self.active.len()) >= self.active.len()),
1426        ensures(!ret || old(self.bookmarked.len()) >= self.bookmarked.len()),
1427        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1428        ensures(ret || old(self.roots.clone()) == self.roots),
1429        ensures(ret || old(self.active.clone()) == self.active),
1430        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1431        invariant(self.validate())
1432    ))]
1433    fn remove_tracked(
1434        &mut self,
1435        id: &K,
1436        mut on_removal: impl FnMut(IndependentNode<K, T, S>),
1437    ) -> bool {
1438        let Some(node) = self.nodes.remove(id) else {
1439            return false;
1440        };
1441
1442        if node.from.is_empty() {
1443            self.roots.shift_remove(id);
1444        } else {
1445            for parent in &node.from {
1446                if let Some(parent) = self.nodes.get_mut(parent) {
1447                    parent.to.shift_remove(id);
1448                }
1449            }
1450        }
1451
1452        let mut removed_active = node.active;
1453        let mut removed_bookmark = node.bookmarked;
1454
1455        if removed_active {
1456            self.active.remove(id);
1457        }
1458
1459        if node.to.is_empty() {
1460            if removed_bookmark {
1461                self.bookmarked.shift_remove(id);
1462            }
1463            on_removal(node);
1464            return true;
1465        }
1466
1467        {
1468            let guard = self.scratchpad.guard();
1469            let mut stack = guard.vec();
1470            let mut removed = guard.vec_with_capacity(node.to.len().strict_add(1));
1471            let mut remaining_parents = guard.map_with_capacity(node.to.len(), S::default());
1472
1473            removed.push(*id);
1474
1475            for child in node.to.iter().rev().copied() {
1476                let remaining = remaining_parents
1477                    .entry(child)
1478                    .or_insert_with(|| self.nodes[&child].from.len());
1479                *remaining = remaining.strict_sub(1);
1480
1481                if *remaining == 0 {
1482                    stack.push(child);
1483                }
1484            }
1485
1486            on_removal(node);
1487
1488            while let Some(id) = stack.pop() {
1489                let node = self.nodes.remove(&id).unwrap();
1490                removed.push(id);
1491
1492                removed_bookmark |= node.bookmarked;
1493                if node.active {
1494                    self.active.remove(&id);
1495                    removed_active = true;
1496                }
1497
1498                for child in node.to.iter().rev().copied() {
1499                    let remaining = remaining_parents
1500                        .entry(child)
1501                        .or_insert_with(|| self.nodes[&child].from.len());
1502                    *remaining = remaining.strict_sub(1);
1503
1504                    if *remaining == 0 {
1505                        stack.push(child);
1506                    }
1507                }
1508
1509                on_removal(node);
1510            }
1511
1512            if removed_active
1513                && !remaining_parents
1514                    .iter()
1515                    .any(|(child, remaining)| *remaining > 0 && self.active.contains(child))
1516            {
1517                removed_active = false;
1518            }
1519
1520            if removed.len() == 1 {
1521                for (child, _) in remaining_parents {
1522                    if let Some(child) = self.nodes.get_mut(&child) {
1523                        child.from.shift_remove(id);
1524                    }
1525                }
1526                if removed_bookmark {
1527                    self.bookmarked.shift_remove(id);
1528                }
1529            } else {
1530                let mut removed_set = guard.set_with_capacity(removed.len(), S::default());
1531                removed_set.extend(removed);
1532
1533                for (child, remaining) in remaining_parents {
1534                    if remaining > 0
1535                        && let Some(child) = self.nodes.get_mut(&child)
1536                    {
1537                        child.from.retain(|parent| !removed_set.contains(parent));
1538                    }
1539                }
1540
1541                if removed_bookmark {
1542                    self.bookmarked.retain(|id| !removed_set.contains(id));
1543                }
1544            }
1545        }
1546
1547        if removed_active {
1548            self.fix_orphaned_activations();
1549        }
1550
1551        true
1552    }
1553    #[cfg_attr(debug_assertions, contract(
1554        ensures(self.nodes.is_empty()),
1555        ensures(self.validate())
1556    ))]
1557    fn clear(&mut self) {
1558        self.nodes.clear();
1559        self.roots.clear();
1560        self.active.clear();
1561        self.bookmarked.clear();
1562    }
1563}
1564
1565impl<K, T, M, S> IndependentWeave<K, T, M, S>
1566where
1567    K: Hash + Copy + Eq + Ord,
1568    T: IndependentContents,
1569    S: BuildHasher + Default + Clone,
1570{
1571    /// Validates that the weave is internally consistent.
1572    pub fn validate(&self) -> bool {
1573        self.roots
1574            .iter()
1575            .all(move |value| self.nodes.contains_key(value))
1576            && self
1577                .active
1578                .iter()
1579                .all(move |value| self.nodes.contains_key(value))
1580            && self
1581                .bookmarked
1582                .iter()
1583                .all(move |value| self.nodes.contains_key(value))
1584            && self.nodes.iter().all(|(key, value)| {
1585                value.validate()
1586                    && value.id == *key
1587                    && value
1588                        .from
1589                        .iter()
1590                        .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
1591                    && value
1592                        .to
1593                        .iter()
1594                        .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
1595                    && value.from.is_empty() == self.roots.contains(key)
1596                    && value.active == self.active.contains(key)
1597                    && value.bookmarked == self.bookmarked.contains(key)
1598            })
1599            && valid_topology(&self.nodes, &self.roots, &self.active)
1600    }
1601}
1602
1603impl<K, T, M, S> MetadataWeave<K, IndependentNode<K, T, S>, T, M> for IndependentWeave<K, T, M, S>
1604where
1605    K: Hash + Copy + Eq + Ord,
1606    T: IndependentContents,
1607    S: BuildHasher + Default + Clone,
1608{
1609    #[inline]
1610    fn metadata(&self) -> &M {
1611        &self.metadata
1612    }
1613    #[cfg_attr(debug_assertions, contract(
1614        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1615        ensures(old(self.roots.clone()) == self.roots),
1616        ensures(old(self.active.clone()) == self.active),
1617        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1618        invariant(self.validate())
1619    ))]
1620    #[inline]
1621    fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
1622        callback(&mut self.metadata)
1623    }
1624}
1625
1626impl<K, T, M, S> BookmarkableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1627where
1628    K: Hash + Copy + Eq + Ord,
1629    T: IndependentContents,
1630    S: BuildHasher + Default + Clone,
1631{
1632    type Bookmarks = IndexSet<K, S>;
1633
1634    #[inline]
1635    fn bookmarks(&self) -> &Self::Bookmarks {
1636        &self.bookmarked
1637    }
1638    #[inline]
1639    fn contains_bookmark(&self, id: &K) -> bool {
1640        self.bookmarked.contains(id)
1641    }
1642    #[cfg_attr(debug_assertions, contract(
1643        ensures(!ret || value == self.bookmarked.contains(id)),
1644        ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1645        ensures(ret == self.nodes.contains_key(id)),
1646        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1647        ensures(old(self.roots.clone()) == self.roots),
1648        ensures(old(self.active.clone()) == self.active),
1649        invariant(self.validate())
1650    ))]
1651    fn set_bookmarked(&mut self, id: &K, value: bool) -> bool {
1652        match self.nodes.get_mut(id) {
1653            Some(node) => {
1654                node.bookmarked = value;
1655                if value {
1656                    self.bookmarked.insert(node.id);
1657                } else {
1658                    self.bookmarked.shift_remove(id);
1659                }
1660
1661                true
1662            }
1663            None => false,
1664        }
1665    }
1666}
1667
1668impl<K, T, M, S> SortableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1669where
1670    K: Hash + Copy + Eq + Ord,
1671    T: IndependentContents,
1672    S: BuildHasher + Default + Clone,
1673{
1674    #[cfg_attr(debug_assertions, contract(
1675        ensures(ret == self.nodes.contains_key(id)),
1676        ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1677        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1678        ensures(old(self.roots.clone()) == self.roots),
1679        ensures(old(self.active.clone()) == self.active),
1680        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1681        invariant(self.validate())
1682    ))]
1683    fn sort_children_by(
1684        &mut self,
1685        id: &K,
1686        mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1687    ) -> bool {
1688        if let Some(node) = self.nodes.get_mut(id) {
1689            let mut set = mem::take(&mut node.to);
1690
1691            if set.len() > 20 {
1692                let guard = self.scratchpad.guard();
1693                let mut nodes = guard
1694                    .arena()
1695                    .alloc_iter_exact(set.drain(..).map(|id| &self.nodes[&id]));
1696                nodes.sort_by(|a, b| cmp(*a, *b));
1697
1698                set.extend(nodes.into_iter().map(|node| node.id));
1699            } else {
1700                set.sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1701            }
1702
1703            self.nodes.get_mut(id).unwrap().to = set;
1704
1705            true
1706        } else {
1707            false
1708        }
1709    }
1710    #[cfg_attr(debug_assertions, contract(
1711        ensures(ret == self.nodes.contains_key(id)),
1712        ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1713        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1714        ensures(old(self.roots.clone()) == self.roots),
1715        ensures(old(self.active.clone()) == self.active),
1716        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1717        invariant(self.validate())
1718    ))]
1719    fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
1720        if let Some(node) = self.nodes.get_mut(id) {
1721            node.to.sort_by(cmp);
1722
1723            true
1724        } else {
1725            false
1726        }
1727    }
1728    #[cfg_attr(debug_assertions, contract(
1729        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1730        ensures(old(self.roots.clone()) == self.roots),
1731        ensures(old(self.active.clone()) == self.active),
1732        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1733        invariant(self.validate())
1734    ))]
1735    fn sort_roots_by(
1736        &mut self,
1737        mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1738    ) {
1739        if self.roots.len() > 20 {
1740            let guard = self.scratchpad.guard();
1741
1742            let mut nodes = guard
1743                .arena()
1744                .alloc_iter_exact(self.roots.iter().map(|id| &self.nodes[id]));
1745            nodes.sort_by(|a, b| cmp(*a, *b));
1746
1747            self.roots.clear();
1748            self.roots.extend(nodes.into_iter().map(|node| node.id));
1749        } else {
1750            self.roots
1751                .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1752        }
1753    }
1754    #[cfg_attr(debug_assertions, contract(
1755        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1756        ensures(old(self.roots.clone()) == self.roots),
1757        ensures(old(self.active.clone()) == self.active),
1758        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1759        invariant(self.validate())
1760    ))]
1761    fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1762        self.roots.sort_by(cmp);
1763    }
1764}
1765
1766impl<K, T, M, S> SortableBookmarkableWeave<K, IndependentNode<K, T, S>, T>
1767    for IndependentWeave<K, T, M, S>
1768where
1769    K: Hash + Copy + Eq + Ord,
1770    T: IndependentContents,
1771    S: BuildHasher + Default + Clone,
1772{
1773    #[cfg_attr(debug_assertions, contract(
1774        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1775        ensures(old(self.roots.clone()) == self.roots),
1776        ensures(old(self.active.clone()) == self.active),
1777        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1778        invariant(self.validate())
1779    ))]
1780    fn sort_bookmarks_by(
1781        &mut self,
1782        mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1783    ) {
1784        if self.bookmarked.len() > 20 {
1785            let guard = self.scratchpad.guard();
1786
1787            let mut nodes = guard
1788                .arena()
1789                .alloc_iter_exact(self.bookmarked.iter().map(|id| &self.nodes[id]));
1790            nodes.sort_by(|a, b| cmp(*a, *b));
1791
1792            self.bookmarked.clear();
1793            self.bookmarked
1794                .extend(nodes.into_iter().map(|node| node.id));
1795        } else {
1796            self.bookmarked
1797                .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1798        }
1799    }
1800    #[cfg_attr(debug_assertions, contract(
1801        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1802        ensures(old(self.roots.clone()) == self.roots),
1803        ensures(old(self.active.clone()) == self.active),
1804        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1805        invariant(self.validate())
1806    ))]
1807    fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1808        self.bookmarked.sort_by(cmp);
1809    }
1810}
1811
1812impl<K, T, M, S> ActivePathWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1813where
1814    K: Hash + Copy + Eq + Ord,
1815    T: IndependentContents,
1816    S: BuildHasher + Default + Clone,
1817{
1818    type Active = HashSet<K, S>;
1819
1820    #[inline]
1821    fn active(&self) -> &Self::Active {
1822        &self.active
1823    }
1824    #[cfg_attr(debug_assertions, contract(
1825        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1826        ensures(old(self.roots.clone()) == self.roots),
1827        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1828        invariant(self.validate())
1829    ))]
1830    fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
1831        self.active.drain().for_each(|active| {
1832            self.nodes.get_mut(&active).unwrap().active = false;
1833        });
1834        self.active
1835            .extend(active.filter(|id| self.nodes.contains_key(id)));
1836        self.active.iter().for_each(|active| {
1837            self.nodes.get_mut(active).unwrap().active = true;
1838        });
1839        self.fix_orphaned_activations();
1840    }
1841}
1842
1843impl<K, T, M, S> DiscreteWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1844where
1845    K: Hash + Copy + Eq + Ord,
1846    T: IndependentContents + DiscreteContents,
1847    S: BuildHasher + Default + Clone,
1848{
1849    #[cfg_attr(debug_assertions, contract(
1850        ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1851        ensures(!ret || self.nodes.contains_key(id)),
1852        ensures(!ret || self.nodes.contains_key(&new_id)),
1853        ensures(!ret || old(!self.nodes.contains_key(&new_id))),
1854        ensures(!ret || self.nodes[id].to.contains(&new_id) && self.nodes[id].to.len() == 1),
1855        ensures(!ret || self.nodes[&new_id].from.contains(id) && self.nodes[&new_id].from.len() == 1),
1856        ensures(!ret || old(self.nodes.get(id).map(|n| n.to.clone())).unwrap() == self.nodes[&new_id].to),
1857        ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1858        ensures(ret || old(self.active.clone()) == self.active),
1859        ensures(old(self.roots.clone()) == self.roots),
1860        ensures(old(self.bookmarked.clone()) == self.bookmarked),
1861        invariant(self.validate())
1862    ))]
1863    fn split(&mut self, id: &K, at: usize, new_id: K) -> bool {
1864        if self.nodes.contains_key(&new_id) || *id == new_id {
1865            return false;
1866        }
1867
1868        if let Some(mut node) = self.nodes.remove(id) {
1869            match node.contents.split(at) {
1870                DiscreteContentResult::Two(left, right) => {
1871                    let left_node = IndependentNode {
1872                        id: node.id,
1873                        from: node.from,
1874                        to: IndexSet::from_iter([new_id]),
1875                        active: node.active,
1876                        bookmarked: node.bookmarked,
1877                        contents: left,
1878                    };
1879
1880                    node.from = IndexSet::from_iter([node.id]);
1881                    node.id = new_id;
1882                    node.contents = right;
1883                    node.active = false;
1884                    node.bookmarked = false;
1885
1886                    let mut child_active = false;
1887
1888                    for child in &node.to {
1889                        let child = self.nodes.get_mut(child).unwrap();
1890                        let index = child.from.get_index_of(&left_node.id).unwrap();
1891
1892                        assert!(
1893                            child.from.replace_index(index, node.id).is_ok(),
1894                            "Should be unreachable"
1895                        );
1896
1897                        child_active |= child.active;
1898                    }
1899
1900                    if left_node.active && child_active {
1901                        node.active = true;
1902                        self.active.insert(node.id);
1903                    }
1904
1905                    self.nodes.insert(left_node.id, left_node);
1906                    self.nodes.insert(node.id, node);
1907
1908                    true
1909                }
1910                DiscreteContentResult::One(content) => {
1911                    node.contents = content;
1912                    self.nodes.insert(node.id, node);
1913                    false
1914                }
1915            }
1916        } else {
1917            false
1918        }
1919    }
1920    #[cfg_attr(debug_assertions, contract(
1921        ensures(ret.is_none() || old(self.nodes.len()) - 1 == self.nodes.len()),
1922        ensures(ret.is_none() || !self.nodes.contains_key(id)),
1923        ensures(ret.is_none() || old(self.nodes.contains_key(id))),
1924        ensures(ret.is_none() || !old(self.contains_active(id)) || old(self.contains_active(id)) && self.contains_active(&ret.unwrap())),
1925        ensures(ret.is_none() || old(self.nodes.get(id).and_then(|n| n.from.first()).and_then(|p| self.nodes.get(p)).map(|p| p.active)).unwrap() == self.nodes[&ret.unwrap()].active),
1926        ensures(ret.is_none() || old(self.nodes.get(id).and_then(|n| n.from.first()).and_then(|p| self.nodes.get(p)).map(|p| p.from.clone())).unwrap() == self.nodes[&ret.unwrap()].from),
1927        ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.to.clone())).unwrap() == self.nodes[&ret.unwrap()].to),
1928        ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.from.len() == 1)).unwrap()),
1929        ensures(ret.is_none() || ret.unwrap() == old(self.nodes.get(id).and_then(|node| node.from.first().copied())).unwrap()),
1930        ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1931        ensures(ret.is_some() || old(self.active.clone()) == self.active),
1932        ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1933        ensures(old(self.roots.clone()) == self.roots),
1934        invariant(self.validate())
1935    ))]
1936    fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1937        if let Some(mut node) = self.nodes.remove(id) {
1938            if node.from.len() != 1 {
1939                self.nodes.insert(node.id, node);
1940                return None;
1941            }
1942
1943            if let Some(mut parent) = node.from.first().and_then(|id| self.nodes.remove(id)) {
1944                if parent.to.len() > 1 {
1945                    self.nodes.insert(parent.id, parent);
1946                    self.nodes.insert(node.id, node);
1947                    return None;
1948                }
1949
1950                match parent.contents.merge(node.contents) {
1951                    DiscreteContentResult::Two(left, right) => {
1952                        parent.contents = left;
1953                        node.contents = right;
1954                        self.nodes.insert(parent.id, parent);
1955                        self.nodes.insert(node.id, node);
1956                        None
1957                    }
1958                    DiscreteContentResult::One(content) => {
1959                        parent.contents = content;
1960                        parent.to = node.to;
1961
1962                        for child in &parent.to {
1963                            let child = self.nodes.get_mut(child).unwrap();
1964                            let index = child.from.get_index_of(&node.id).unwrap();
1965
1966                            assert!(
1967                                child.from.replace_index(index, parent.id).is_ok(),
1968                                "Should be unreachable"
1969                            );
1970                        }
1971
1972                        let parent_id = parent.id;
1973
1974                        if node.bookmarked && !parent.bookmarked {
1975                            parent.bookmarked = true;
1976                            assert!(
1977                                self.bookmarked
1978                                    .replace_index(
1979                                        self.bookmarked.get_index_of(&node.id).unwrap(),
1980                                        parent.id,
1981                                    )
1982                                    .is_ok(),
1983                                "Should be unreachable"
1984                            );
1985                        } else if node.bookmarked {
1986                            self.bookmarked.shift_remove(&node.id);
1987                        }
1988
1989                        self.nodes.insert(parent.id, parent);
1990                        self.active.remove(&node.id);
1991
1992                        Some(parent_id)
1993                    }
1994                }
1995            } else {
1996                self.nodes.insert(node.id, node);
1997                None
1998            }
1999        } else {
2000            None
2001        }
2002    }
2003}
2004
2005impl<K, T, M, S> SemiIndependentWeave<K, IndependentNode<K, T, S>, T>
2006    for IndependentWeave<K, T, M, S>
2007where
2008    K: Hash + Copy + Eq + Ord,
2009    T: IndependentContents,
2010    S: BuildHasher + Default + Clone,
2011{
2012    #[cfg_attr(debug_assertions, contract(
2013        ensures(ret.is_some() == old(self.nodes.contains_key(id))),
2014        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
2015        ensures(old(self.roots.clone()) == self.roots),
2016        ensures(old(self.active.clone()) == self.active),
2017        ensures(old(self.bookmarked.clone()) == self.bookmarked),
2018        invariant(self.validate())
2019    ))]
2020    #[inline]
2021    fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
2022        self.nodes
2023            .get_mut(id)
2024            .map(|node| callback(&mut node.contents))
2025    }
2026}
2027
2028impl<K, T, M, S> crate::IndependentWeave<K, IndependentNode<K, T, S>, T>
2029    for IndependentWeave<K, T, M, S>
2030where
2031    K: Hash + Copy + Eq + Ord,
2032    T: IndependentContents,
2033    S: BuildHasher + Default + Clone,
2034{
2035    #[cfg_attr(debug_assertions, contract(
2036        ensures(!ret || self.nodes[id].from.iter().copied().collect::<HashSet<_>>() == new_parents.iter().copied().collect::<HashSet<_>>()),
2037        ensures(ret || old(self.nodes.get(id).map(|node| node.from.clone())).as_ref() == self.nodes.get(id).map(|node| &node.from)),
2038        ensures(ret || old(self.roots.clone()) == self.roots),
2039        ensures(ret || old(self.active.clone()) == self.active),
2040        ensures(old(self.nodes.get(id).map(|node| node.to.clone())).as_ref() == self.nodes.get(id).map(|node| &node.to)),
2041        ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
2042        ensures(old(self.bookmarked.clone()) == self.bookmarked),
2043        ensures(old(self.active.contains(id)) == self.active.contains(id)),
2044        invariant(self.validate())
2045    ))]
2046    fn move_to(&mut self, id: &K, new_parents: &[K]) -> bool {
2047        if new_parents
2048            .iter()
2049            .any(|new_parent| !self.nodes.contains_key(new_parent))
2050        {
2051            return false;
2052        }
2053
2054        let Some(node) = self.nodes.get(id) else {
2055            return false;
2056        };
2057
2058        if node.from.iter().eq(new_parents) {
2059            return true;
2060        }
2061
2062        let new_parents: IndexSet<K, S> = new_parents.iter().copied().collect();
2063
2064        if new_parents.contains(id) {
2065            return false;
2066        }
2067
2068        if !node.to.is_empty() && !new_parents.is_empty() {
2069            let guard = self.scratchpad.guard();
2070
2071            if descendant_subgraph_reaches(
2072                &self.nodes,
2073                node.to.iter().copied(),
2074                |id| new_parents.contains(id),
2075                &mut guard.vec_with_capacity(node.to.len()),
2076                &mut guard.set_with_capacity(node.to.len(), S::default()),
2077            ) {
2078                return false;
2079            }
2080        }
2081
2082        if let Some(node) = self.nodes.get_mut(id) {
2083            let old_parents = mem::take(&mut node.from);
2084
2085            for old_parent in &old_parents {
2086                if !new_parents.contains(old_parent)
2087                    && let Some(old_parent) = self.nodes.get_mut(old_parent)
2088                {
2089                    old_parent.to.shift_remove(id);
2090                }
2091            }
2092
2093            for new_parent in &new_parents {
2094                if !old_parents.contains(new_parent)
2095                    && let Some(new_parent) = self.nodes.get_mut(new_parent)
2096                {
2097                    new_parent.to.insert(*id);
2098                }
2099            }
2100        }
2101
2102        let node = self.nodes.get_mut(id).unwrap();
2103        node.from = new_parents;
2104
2105        if node.from.is_empty() {
2106            self.roots.insert(node.id);
2107        } else {
2108            self.roots.shift_remove(&node.id);
2109        }
2110
2111        if node.active {
2112            node.active = false;
2113            self.active.remove(id);
2114            self.update_node_activity_in_place(id, true);
2115        }
2116
2117        true
2118    }
2119}
2120
2121#[cfg(feature = "rkyv")]
2122impl<K, T, S> ArchivedIndependentNode<K, T, S>
2123where
2124    K: Archive + Hash + Copy + Eq + Ord,
2125    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2126    T: Archive + IndependentContents,
2127    S: BuildHasher + Default + Clone,
2128{
2129    #[inline]
2130    fn validate(&self) -> bool {
2131        (if self.from.len() <= self.to.len() {
2132            self.from.iter().all(|v| !self.to.contains(v))
2133        } else {
2134            self.to.iter().all(|v| !self.from.contains(v))
2135        }) && !self.from.contains(&self.id)
2136            && !self.to.contains(&self.id)
2137    }
2138}
2139
2140#[cfg(feature = "rkyv")]
2141impl<K, T, S> Node<K::Archived, T::Archived> for ArchivedIndependentNode<K, T, S>
2142where
2143    K: Archive + Hash + Copy + Eq + Ord,
2144    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2145    T: Archive + IndependentContents,
2146    S: BuildHasher + Default + Clone,
2147{
2148    type From = ArchivedIndexSet<K::Archived>;
2149    type To = ArchivedIndexSet<K::Archived>;
2150
2151    #[inline]
2152    fn id(&self) -> K::Archived {
2153        self.id
2154    }
2155    #[inline]
2156    fn from(&self) -> &Self::From {
2157        &self.from
2158    }
2159    #[inline]
2160    fn to(&self) -> &Self::To {
2161        &self.to
2162    }
2163    #[inline]
2164    fn is_active(&self) -> bool {
2165        self.active
2166    }
2167    #[inline]
2168    fn contents(&self) -> &T::Archived {
2169        &self.contents
2170    }
2171}
2172
2173#[cfg(feature = "rkyv")]
2174impl<K, T, M, S> ArchivedIndependentWeave<K, T, M, S>
2175where
2176    K: Archive + Hash + Copy + Eq + Ord,
2177    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2178    T: Archive + IndependentContents,
2179    M: Archive,
2180    S: BuildHasher + Default + Clone,
2181{
2182    fn validate(&self) -> bool {
2183        self.roots
2184            .iter()
2185            .all(move |value| self.nodes.contains_key(value))
2186            && self
2187                .active
2188                .iter()
2189                .all(move |value| self.nodes.contains_key(value))
2190            && self
2191                .bookmarked
2192                .iter()
2193                .all(move |value| self.nodes.contains_key(value))
2194            && self.nodes.iter().all(|(key, value)| {
2195                value.validate()
2196                    && value.id == *key
2197                    && value
2198                        .from
2199                        .iter()
2200                        .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
2201                    && value
2202                        .to
2203                        .iter()
2204                        .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
2205                    && value.from.is_empty() == self.roots.contains(key)
2206                    && value.active == self.active.contains(key)
2207                    && value.bookmarked == self.bookmarked.contains(key)
2208            })
2209            && archived_valid_topology(&self.nodes, &self.roots, &self.active)
2210    }
2211}
2212
2213#[cfg(feature = "rkyv")]
2214// SAFETY:
2215// All fields are safe to access and no unsafe functions are called
2216unsafe impl<K, T, M, S, C> Verify<C> for ArchivedIndependentWeave<K, T, M, S>
2217where
2218    K: Archive + Hash + Copy + Eq + Ord,
2219    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2220    T: Archive + IndependentContents,
2221    M: Archive,
2222    S: BuildHasher + Default + Clone,
2223    C: Fallible + ?Sized,
2224    C::Error: Source,
2225{
2226    fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
2227        if !self.validate() {
2228            fail!(ValidationError)
2229        }
2230
2231        Ok(())
2232    }
2233}
2234
2235#[cfg(feature = "rkyv")]
2236impl<K, T, M, S> ImmutableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2237    for ArchivedIndependentWeave<K, T, M, S>
2238where
2239    K: Archive + Hash + Copy + Eq + Ord,
2240    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2241    T: Archive + IndependentContents,
2242    M: Archive,
2243    S: BuildHasher + Default + Clone,
2244{
2245    type Nodes = ArchivedHashMap<K::Archived, ArchivedIndependentNode<K, T, S>>;
2246    type Roots = ArchivedIndexSet<K::Archived>;
2247
2248    #[inline]
2249    fn len(&self) -> usize {
2250        self.nodes.len()
2251    }
2252    #[inline]
2253    fn is_empty(&self) -> bool {
2254        self.nodes.is_empty()
2255    }
2256    #[inline]
2257    fn nodes(&self) -> &Self::Nodes {
2258        &self.nodes
2259    }
2260    #[inline]
2261    fn roots(&self) -> &Self::Roots {
2262        &self.roots
2263    }
2264    #[inline]
2265    fn contains(&self, id: &K::Archived) -> bool {
2266        self.nodes.contains_key(id)
2267    }
2268    #[inline]
2269    fn contains_active(&self, id: &K::Archived) -> bool {
2270        self.active.contains(id)
2271    }
2272    #[inline]
2273    fn get(&self, id: &K::Archived) -> Option<&ArchivedIndependentNode<K, T, S>> {
2274        self.nodes.get(id)
2275    }
2276    #[inline]
2277    fn get_parents(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
2278        self.nodes.get(id).map(|node| &node.from)
2279    }
2280    #[inline]
2281    fn get_children(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
2282        self.nodes.get(id).map(|node| &node.to)
2283    }
2284    #[inline]
2285    fn get_contents(&self, id: &K::Archived) -> Option<&T::Archived> {
2286        self.nodes.get(id).map(|node| &node.contents)
2287    }
2288    fn get_ordered_identifiers(&self, output: &mut Vec<K::Archived>) {
2289        output.clear();
2290        output.reserve(self.nodes.len());
2291
2292        let mut scratchpad = Scratchpad::new();
2293        let guard = scratchpad.guard();
2294
2295        archived_topological_sort(
2296            &self.nodes,
2297            &self.roots,
2298            &mut guard.vec_with_capacity(self.roots.len()),
2299            |id| output.push(id),
2300            &mut guard
2301                .map_with_capacity(self.nodes.len().strict_sub(self.roots.len()), S::default()),
2302        );
2303    }
2304    fn get_ordered_identifiers_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2305        output.clear();
2306
2307        if self.nodes.contains_key(id) {
2308            let mut scratchpad = Scratchpad::new();
2309            let guard = scratchpad.guard();
2310
2311            let mut stack = guard.vec();
2312            let mut descendants = guard.set(S::default());
2313
2314            archived_descendant_subgraph(&self.nodes, *id, &mut stack, &mut descendants);
2315
2316            output.reserve(descendants.len());
2317
2318            archived_topological_sort_subgraph(
2319                &self.nodes,
2320                |id| descendants.contains(id),
2321                *id,
2322                &mut stack,
2323                |id| output.push(id),
2324                &mut guard.map_with_capacity(descendants.len(), S::default()),
2325            );
2326        }
2327    }
2328    fn get_active_path(&self, output: &mut Vec<K::Archived>) {
2329        output.clear();
2330
2331        if self.active.is_empty() {
2332            return;
2333        }
2334
2335        output.reserve(self.active.len());
2336
2337        let mut scratchpad = Scratchpad::new();
2338        let guard = scratchpad.guard();
2339
2340        let mut stack = guard.vec();
2341        let mut topological_subgraph = guard.vec_with_capacity(self.active.len());
2342        let mut scratchpad_map = guard.map_with_capacity(self.active.len(), S::default());
2343
2344        for root in self
2345            .roots
2346            .iter()
2347            .filter(|id| self.active.contains(*id))
2348            .copied()
2349        {
2350            archived_topological_sort_subgraph(
2351                &self.nodes,
2352                |id| self.active.contains(id),
2353                root,
2354                &mut stack,
2355                |id| topological_subgraph.push(id),
2356                &mut scratchpad_map,
2357            );
2358        }
2359
2360        scratchpad_map.clear();
2361
2362        archived_longest_candidate_path_to_root(
2363            &self.nodes,
2364            &topological_subgraph,
2365            |id| self.active.contains(id),
2366            &mut scratchpad_map,
2367            |id| output.push(id),
2368        );
2369    }
2370    fn get_path_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2371        output.clear();
2372        if !self.nodes.contains_key(id) {
2373            return;
2374        }
2375
2376        let mut scratchpad = Scratchpad::new();
2377        let guard = scratchpad.guard();
2378        let mut stack = guard.vec();
2379        let mut ancestors = guard.set(S::default());
2380        let mut root_ancestors = guard.vec();
2381
2382        archived_ancestor_subgraph(&self.nodes, *id, &mut stack, &mut ancestors, |id| {
2383            root_ancestors.push(id);
2384        });
2385
2386        let mut active_topological_subgraph =
2387            guard.vec_with_capacity(self.active.len().min(ancestors.len()));
2388        let mut scratchpad_map =
2389            guard.map_with_capacity(self.active.len().min(ancestors.len()), S::default());
2390
2391        for root in root_ancestors
2392            .drain(..)
2393            .filter(|id| self.active.contains(id))
2394        {
2395            archived_topological_sort_subgraph(
2396                &self.nodes,
2397                |id| self.active.contains(id) && ancestors.contains(id),
2398                root,
2399                &mut stack,
2400                |id| active_topological_subgraph.push(id),
2401                &mut scratchpad_map,
2402            );
2403        }
2404
2405        scratchpad_map.clear();
2406
2407        let mut reversed_path = guard.vec();
2408
2409        archived_longest_candidate_path_to_root(
2410            &self.nodes,
2411            &active_topological_subgraph,
2412            |id| self.active.contains(id) && ancestors.contains(id),
2413            &mut scratchpad_map,
2414            |id| reversed_path.push(id),
2415        );
2416
2417        let mut scratchpad_map_2 = guard.map_with_capacity(ancestors.len(), S::default());
2418
2419        ancestors.clear();
2420        let mut scratchpad_set = ancestors;
2421
2422        if let Some(target) = reversed_path.first().copied() {
2423            archived_shortest_path_to_ancestor(
2424                &self.nodes,
2425                id,
2426                |node| node.id == target,
2427                &mut stack,
2428                &mut scratchpad_map_2,
2429                &mut scratchpad_set,
2430                output,
2431            );
2432
2433            output.reverse();
2434            output.pop();
2435            output.extend_from_slice(&reversed_path);
2436        } else {
2437            archived_shortest_path_to_ancestor(
2438                &self.nodes,
2439                id,
2440                |node| node.from.is_empty(),
2441                &mut stack,
2442                &mut scratchpad_map_2,
2443                &mut scratchpad_set,
2444                output,
2445            );
2446
2447            output.reverse();
2448        }
2449    }
2450}
2451
2452#[cfg(feature = "rkyv")]
2453impl<K, T, M, S>
2454    ImmutableMetadataWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived, M::Archived>
2455    for ArchivedIndependentWeave<K, T, M, S>
2456where
2457    K: Archive + Hash + Copy + Eq + Ord,
2458    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2459    T: Archive + IndependentContents,
2460    M: Archive,
2461    S: BuildHasher + Default + Clone,
2462{
2463    #[inline]
2464    fn metadata(&self) -> &M::Archived {
2465        &self.metadata
2466    }
2467}
2468
2469#[cfg(feature = "rkyv")]
2470impl<K, T, M, S>
2471    ImmutableBookmarkableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2472    for ArchivedIndependentWeave<K, T, M, S>
2473where
2474    K: Archive + Hash + Copy + Eq + Ord,
2475    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2476    T: Archive + IndependentContents,
2477    M: Archive,
2478    S: BuildHasher + Default + Clone,
2479{
2480    type Bookmarks = ArchivedIndexSet<K::Archived>;
2481
2482    #[inline]
2483    fn bookmarks(&self) -> &Self::Bookmarks {
2484        &self.bookmarked
2485    }
2486    #[inline]
2487    fn contains_bookmark(&self, id: &K::Archived) -> bool {
2488        self.bookmarked.contains(id)
2489    }
2490}
2491
2492#[cfg(feature = "rkyv")]
2493impl<K, T, M, S>
2494    ImmutableActivePathWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2495    for ArchivedIndependentWeave<K, T, M, S>
2496where
2497    K: Archive + Hash + Copy + Eq + Ord,
2498    <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2499    T: Archive + IndependentContents,
2500    M: Archive,
2501    S: BuildHasher + Default + Clone,
2502{
2503    type Active = ArchivedHashSet<K::Archived>;
2504
2505    #[inline]
2506    fn active(&self) -> &Self::Active {
2507        &self.active
2508    }
2509}