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