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