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