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