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