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)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
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)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
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_subgraph(
1084 &self.nodes,
1085 &|id| self.active.contains(id),
1086 root,
1087 &mut self.scratchpad_stack,
1088 &mut self.scratchpad_list,
1089 &mut self.scratchpad_set,
1090 &mut self.scratchpad_map,
1091 );
1092 }
1093
1094 self.scratchpad_set.clear();
1095 self.scratchpad_map.clear();
1096
1097 longest_candidate_path_to_root(
1098 &self.nodes,
1099 &self.scratchpad_list,
1100 &|id| self.active.contains(id),
1101 &mut self.scratchpad_map,
1102 output,
1103 );
1104
1105 self.scratchpad_list.clear();
1106 self.scratchpad_map.clear();
1107 }
1108 #[cfg_attr(debug_assertions, contract(
1109 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1110 ensures(self.nodes.contains_key(id) || output.is_empty()),
1111 ensures(lacks_duplicates(output)),
1112 ensures(valid_path(&self.nodes, output)),
1113 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1114 ensures(old(self.roots.clone()) == self.roots),
1115 ensures(old(self.active.clone()) == self.active),
1116 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1117 invariant(self.validate())
1118 ))]
1119 fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
1120 output.clear();
1121 if !self.nodes.contains_key(id) {
1122 return;
1123 }
1124
1125 ancestor_subgraph(
1126 &self.nodes,
1127 *id,
1128 &mut self.scratchpad_stack,
1129 &mut self.scratchpad_set,
1130 );
1131
1132 for root in &self.roots {
1133 topological_sort_subgraph(
1134 &self.nodes,
1135 &|id| self.active.contains(id),
1136 root,
1137 &mut self.scratchpad_stack,
1138 &mut self.scratchpad_list,
1139 &mut self.scratchpad_set_2,
1140 &mut self.scratchpad_map,
1141 );
1142 }
1143
1144 self.scratchpad_map.clear();
1145
1146 longest_candidate_path_to_root(
1147 &self.nodes,
1148 &self.scratchpad_list,
1149 &|id| self.active.contains(id) && self.scratchpad_set.contains(id),
1150 &mut self.scratchpad_map,
1151 &mut self.scratchpad_list_2,
1152 );
1153
1154 self.scratchpad_list.clear();
1155 self.scratchpad_set.clear();
1156 self.scratchpad_set_2.clear();
1157 self.scratchpad_map.clear();
1158 self.scratchpad_map_2.clear();
1159
1160 if let Some(target) = self.scratchpad_list_2.first().copied() {
1161 shortest_path_to_ancestor(
1162 &self.nodes,
1163 id,
1164 &|node| node.id == target,
1165 &mut self.scratchpad_queue,
1166 &mut self.scratchpad_map_2,
1167 &mut self.scratchpad_set_2,
1168 output,
1169 );
1170
1171 output.reverse();
1172 output.pop();
1173 output.append(&mut self.scratchpad_list_2);
1174 } else {
1175 shortest_path_to_ancestor(
1176 &self.nodes,
1177 id,
1178 &|node| node.from.is_empty(),
1179 &mut self.scratchpad_queue,
1180 &mut self.scratchpad_map_2,
1181 &mut self.scratchpad_set_2,
1182 output,
1183 );
1184
1185 output.reverse();
1186 }
1187
1188 self.scratchpad_set_2.clear();
1189 self.scratchpad_map_2.clear();
1190 }
1191 #[cfg_attr(debug_assertions, contract(
1192 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1193 ensures(!ret || old(!self.nodes.contains_key(&node.id))),
1194 ensures(!ret || self.nodes.contains_key(&old(node.id))),
1195 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))))),
1196 ensures(!ret || old(node.bookmarked) == self.bookmarked.contains(&old(node.id))),
1197 ensures(!ret || old(!node.from.is_empty()) || self.roots.contains(&old(node.id))),
1198 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1199 ensures(ret || old(self.roots.clone()) == self.roots),
1200 ensures(ret || old(self.active.clone()) == self.active),
1201 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1202 invariant(self.validate())
1203 ))]
1204 fn add_node(&mut self, mut node: IndependentNode<K, T, S>) -> bool {
1205 if self.nodes.contains_key(&node.id)
1206 || !node.validate()
1207 || !node.from.iter().all(|id| self.nodes.contains_key(id))
1208 || !node.to.iter().all(|id| self.nodes.contains_key(id))
1209 {
1210 return false;
1211 }
1212
1213 if !node.to.is_empty() && !node.from.is_empty() {
1214 for parent in node.from.iter().copied() {
1215 ancestor_subgraph(
1216 &self.nodes,
1217 parent,
1218 &mut self.scratchpad_stack,
1219 &mut self.scratchpad_set,
1220 );
1221 }
1222
1223 if node
1224 .to
1225 .iter()
1226 .any(|child| self.scratchpad_set.contains(child))
1227 {
1228 self.scratchpad_set.clear();
1229 return false;
1230 }
1231
1232 self.scratchpad_set.clear();
1233 }
1234
1235 let root_index = node
1236 .to
1237 .iter()
1238 .filter_map(|child| self.roots.get_index_of(child))
1239 .min();
1240
1241 for child in &node.to {
1242 let child = &self.nodes[child];
1243 if child.from.is_empty() {
1244 if child.active {
1245 node.active = true;
1246 }
1247 self.roots.shift_remove(&child.id);
1248 }
1249 }
1250
1251 let extends_active = node.active
1252 && node.to.is_empty()
1253 && node.from.iter().map(|id| &self.nodes[id]).any(|parent| {
1254 parent.active && parent.to.iter().all(|child| !self.active.contains(child))
1255 });
1256
1257 if node.from.is_empty() {
1258 if let Some(index) = root_index {
1259 self.roots.shift_insert(index, node.id);
1260 } else {
1261 self.roots.insert(node.id);
1262 }
1263 } else {
1264 for parent in &node.from {
1265 let parent = self.nodes.get_mut(parent).unwrap();
1266 parent.to.insert(node.id);
1267 }
1268 }
1269
1270 for child in &node.to {
1271 let child = self.nodes.get_mut(child).unwrap();
1272 child.from.insert(node.id);
1273 }
1274
1275 if node.bookmarked {
1276 self.bookmarked.insert(node.id);
1277 }
1278
1279 let id = node.id;
1280 let active = node.active;
1281
1282 if !extends_active {
1283 node.active = false;
1284 }
1285
1286 self.nodes.insert(node.id, node);
1287
1288 if extends_active {
1289 self.active.insert(id);
1290 } else if active {
1291 self.update_node_activity_in_place(&id, true);
1292 }
1293
1294 true
1295 }
1296 #[cfg_attr(debug_assertions, contract(
1297 ensures(!ret || value == self.contains_active(id)),
1298 ensures(ret || old(self.active.clone()) == self.active),
1299 ensures(ret == self.nodes.contains_key(id)),
1300 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1301 ensures(old(self.roots.clone()) == self.roots),
1302 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1303 invariant(self.validate())
1304 ))]
1305 fn set_node_active_status(&mut self, id: &K, value: bool) -> bool {
1306 self.update_node_activity_in_place(id, value)
1307 }
1308 #[cfg_attr(debug_assertions, contract(
1309 ensures(!self.nodes.contains_key(id)),
1310 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1311 ensures(ret.as_ref().is_none_or(|node| &node.id == id)),
1312 ensures(ret.is_none() || old(self.nodes.len()) > self.nodes.len()),
1313 ensures(ret.is_none() || old(self.active.len()) >= self.active.len()),
1314 ensures(ret.is_none() || old(self.bookmarked.len()) >= self.bookmarked.len()),
1315 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1316 ensures(ret.is_some() || old(self.roots.clone()) == self.roots),
1317 ensures(ret.is_some() || old(self.active.clone()) == self.active),
1318 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1319 invariant(self.validate())
1320 ))]
1321 fn remove_node(&mut self, id: &K) -> Option<IndependentNode<K, T, S>> {
1322 let mut removed_node = None;
1323 let mut removed_active = false;
1324
1325 self.scratchpad_stack.push(*id);
1326
1327 while let Some(id) = self.scratchpad_stack.pop() {
1328 if let Some(node) = self.nodes.remove(&id) {
1329 if node.from.is_empty() {
1330 self.roots.shift_remove(&id);
1331 }
1332 if node.bookmarked {
1333 self.bookmarked.shift_remove(&id);
1334 }
1335 if node.active {
1336 self.active.remove(&id);
1337 removed_active = true;
1338 }
1339
1340 for parent in &node.from {
1341 if let Some(parent) = self.nodes.get_mut(parent) {
1342 parent.to.shift_remove(&node.id);
1343 }
1344 }
1345 for child in node.to.iter().rev() {
1346 if let Some(child) = self.nodes.get_mut(child) {
1347 child.from.shift_remove(&node.id);
1348
1349 if child.from.is_empty() {
1350 self.scratchpad_stack.push(child.id);
1351 }
1352 }
1353 }
1354
1355 if removed_node.is_none() {
1356 removed_node = Some(node);
1357 }
1358 }
1359 }
1360
1361 if removed_node.is_some() {
1362 if removed_active {
1363 self.fix_orphaned_activations();
1364 }
1365 removed_node
1366 } else {
1367 None
1368 }
1369 }
1370 #[cfg_attr(debug_assertions, contract(
1371 ensures(!self.nodes.contains_key(id)),
1372 ensures(ret == old(self.nodes.contains_key(id))),
1373 ensures(!ret || old(self.nodes.len()) > self.nodes.len()),
1374 ensures(!ret || old(self.active.len()) >= self.active.len()),
1375 ensures(!ret || old(self.bookmarked.len()) >= self.bookmarked.len()),
1376 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1377 ensures(ret || old(self.roots.clone()) == self.roots),
1378 ensures(ret || old(self.active.clone()) == self.active),
1379 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1380 invariant(self.validate())
1381 ))]
1382 fn remove_node_tracked(
1383 &mut self,
1384 id: &K,
1385 mut on_removal: impl FnMut(IndependentNode<K, T, S>),
1386 ) -> bool {
1387 let had_node = self.nodes.contains_key(id);
1388 let mut removed_active = false;
1389
1390 self.scratchpad_stack.push(*id);
1391
1392 while let Some(id) = self.scratchpad_stack.pop() {
1393 if let Some(node) = self.nodes.remove(&id) {
1394 if node.from.is_empty() {
1395 self.roots.shift_remove(&id);
1396 }
1397 if node.bookmarked {
1398 self.bookmarked.shift_remove(&id);
1399 }
1400 if node.active {
1401 self.active.remove(&id);
1402 removed_active = true;
1403 }
1404
1405 for parent in &node.from {
1406 if let Some(parent) = self.nodes.get_mut(parent) {
1407 parent.to.shift_remove(&node.id);
1408 }
1409 }
1410 for child in node.to.iter().rev() {
1411 if let Some(child) = self.nodes.get_mut(child) {
1412 child.from.shift_remove(&node.id);
1413
1414 if child.from.is_empty() {
1415 self.scratchpad_stack.push(child.id);
1416 }
1417 }
1418 }
1419
1420 on_removal(node);
1421 }
1422 }
1423
1424 if had_node {
1425 if removed_active {
1426 self.fix_orphaned_activations();
1427 }
1428 true
1429 } else {
1430 false
1431 }
1432 }
1433 #[cfg_attr(debug_assertions, contract(
1434 ensures(self.nodes.is_empty()),
1435 ensures(self.validate())
1436 ))]
1437 fn remove_all_nodes(&mut self) {
1438 self.nodes.clear();
1439 self.roots.clear();
1440 self.active.clear();
1441 self.bookmarked.clear();
1442 }
1443}
1444
1445impl<K, T, M, S> IndependentWeave<K, T, M, S>
1446where
1447 K: Hash + Copy + Eq + Ord,
1448 T: IndependentContents,
1449 S: BuildHasher + Default + Clone,
1450{
1451 pub fn validate(&self) -> bool {
1453 let mut scratchpad = Vec::with_capacity(self.nodes.len());
1454 let mut scratchpad_map = HashMap::with_capacity_and_hasher(self.nodes.len(), S::default());
1455
1456 self.validate_scratchpads()
1457 && self
1458 .roots
1459 .iter()
1460 .all(move |value| self.nodes.contains_key(value))
1461 && self
1462 .active
1463 .iter()
1464 .all(move |value| self.nodes.contains_key(value))
1465 && self
1466 .bookmarked
1467 .iter()
1468 .all(move |value| self.nodes.contains_key(value))
1469 && self.nodes.iter().all(|(key, value)| {
1470 value.validate()
1471 && value.id == *key
1472 && value
1473 .from
1474 .iter()
1475 .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
1476 && value
1477 .to
1478 .iter()
1479 .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
1480 && value.from.is_empty() == self.roots.contains(key)
1481 && value.active == self.active.contains(key)
1482 && value.bookmarked == self.bookmarked.contains(key)
1483 })
1484 && !detect_cycles(
1485 &self.nodes,
1486 self.roots.iter().copied(),
1487 &mut scratchpad,
1488 &mut scratchpad_map,
1489 )
1490 && active_path_is_valid(&self.nodes, self.roots.iter(), &self.active)
1491 }
1492 fn validate_scratchpads(&self) -> bool {
1493 self.scratchpad_list.is_empty()
1494 && self.scratchpad_list_2.is_empty()
1495 && self.scratchpad_set.is_empty()
1496 && self.scratchpad_set_2.is_empty()
1497 && self.scratchpad_map.is_empty()
1498 && self.scratchpad_map_2.is_empty()
1499 && self.scratchpad_map_3.is_empty()
1500 && self.scratchpad_stack.is_empty()
1501 && self.scratchpad_queue.is_empty()
1502 }
1503}
1504
1505impl<K, T, M, S> MetadataWeave<K, IndependentNode<K, T, S>, T, M> for IndependentWeave<K, T, M, S>
1506where
1507 K: Hash + Copy + Eq + Ord,
1508 T: IndependentContents,
1509 S: BuildHasher + Default + Clone,
1510{
1511 #[inline]
1512 fn metadata(&self) -> &M {
1513 &self.metadata
1514 }
1515 #[cfg_attr(debug_assertions, contract(
1516 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1517 ensures(old(self.roots.clone()) == self.roots),
1518 ensures(old(self.active.clone()) == self.active),
1519 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1520 invariant(self.validate())
1521 ))]
1522 #[inline]
1523 fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
1524 callback(&mut self.metadata)
1525 }
1526}
1527
1528impl<K, T, M, S> BookmarkableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1529where
1530 K: Hash + Copy + Eq + Ord,
1531 T: IndependentContents,
1532 S: BuildHasher + Default + Clone,
1533{
1534 type Bookmarks = IndexSet<K, S>;
1535
1536 #[inline]
1537 fn bookmarks(&self) -> &Self::Bookmarks {
1538 &self.bookmarked
1539 }
1540 #[inline]
1541 fn contains_bookmark(&self, id: &K) -> bool {
1542 self.bookmarked.contains(id)
1543 }
1544 #[cfg_attr(debug_assertions, contract(
1545 ensures(!ret || value == self.bookmarked.contains(id)),
1546 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1547 ensures(ret == self.nodes.contains_key(id)),
1548 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1549 ensures(old(self.roots.clone()) == self.roots),
1550 ensures(old(self.active.clone()) == self.active),
1551 invariant(self.validate())
1552 ))]
1553 fn set_node_bookmarked_status(&mut self, id: &K, value: bool) -> bool {
1554 match self.nodes.get_mut(id) {
1555 Some(node) => {
1556 node.bookmarked = value;
1557 if value {
1558 self.bookmarked.insert(node.id);
1559 } else {
1560 self.bookmarked.shift_remove(id);
1561 }
1562
1563 true
1564 }
1565 None => false,
1566 }
1567 }
1568}
1569
1570impl<K, T, M, S> SortableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1571where
1572 K: Hash + Copy + Eq + Ord,
1573 T: IndependentContents,
1574 S: BuildHasher + Default + Clone,
1575{
1576 #[cfg_attr(debug_assertions, contract(
1577 ensures(output.len() == self.nodes.len()),
1578 ensures(valid_topological_sort(&self.nodes, output)),
1579 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1580 ensures(old(self.roots.clone()) == self.roots),
1581 ensures(old(self.active.clone()) == self.active),
1582 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1583 invariant(self.validate())
1584 ))]
1585 fn get_ordered_node_identifiers_mirrored(&mut self, output: &mut Vec<K>) {
1586 output.clear();
1587
1588 for root in &self.roots {
1589 topological_sort_mirrored(
1590 &self.nodes,
1591 root,
1592 &mut self.scratchpad_stack,
1593 output,
1594 &mut self.scratchpad_set,
1595 &mut self.scratchpad_map,
1596 );
1597 }
1598
1599 self.scratchpad_set.clear();
1600 self.scratchpad_map.clear();
1601 }
1602 #[cfg_attr(debug_assertions, contract(
1603 ensures(lacks_duplicates(output)),
1604 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1605 ensures(self.nodes.contains_key(id) || output.is_empty()),
1606 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1607 ensures(old(self.roots.clone()) == self.roots),
1608 ensures(old(self.active.clone()) == self.active),
1609 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1610 invariant(self.validate())
1611 ))]
1612 fn get_ordered_node_identifiers_mirrored_from(&mut self, id: &K, output: &mut Vec<K>) {
1613 output.clear();
1614
1615 if self.nodes.contains_key(id) {
1616 descendant_subgraph(
1617 &self.nodes,
1618 *id,
1619 &mut self.scratchpad_stack,
1620 &mut self.scratchpad_set,
1621 );
1622
1623 topological_sort_subgraph_mirrored(
1624 &self.nodes,
1625 &|id| self.scratchpad_set.contains(id),
1626 id,
1627 &mut self.scratchpad_stack,
1628 output,
1629 &mut self.scratchpad_set_2,
1630 &mut self.scratchpad_map,
1631 );
1632
1633 self.scratchpad_set.clear();
1634 self.scratchpad_set_2.clear();
1635 self.scratchpad_map.clear();
1636 }
1637 }
1638 #[cfg_attr(debug_assertions, contract(
1639 ensures(ret == self.nodes.contains_key(id)),
1640 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1641 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1642 ensures(old(self.roots.clone()) == self.roots),
1643 ensures(old(self.active.clone()) == self.active),
1644 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1645 invariant(self.validate())
1646 ))]
1647 fn sort_node_children_by(
1648 &mut self,
1649 id: &K,
1650 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1651 ) -> bool {
1652 if let Some(mut node) = self.nodes.remove(id) {
1653 node.to.sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1654 self.nodes.insert(node.id, node);
1655
1656 true
1657 } else {
1658 false
1659 }
1660 }
1661 #[cfg_attr(debug_assertions, contract(
1662 ensures(ret == self.nodes.contains_key(id)),
1663 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1664 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1665 ensures(old(self.roots.clone()) == self.roots),
1666 ensures(old(self.active.clone()) == self.active),
1667 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1668 invariant(self.validate())
1669 ))]
1670 fn sort_node_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
1671 if let Some(node) = self.nodes.get_mut(id) {
1672 node.to.sort_by(cmp);
1673
1674 true
1675 } else {
1676 false
1677 }
1678 }
1679 #[cfg_attr(debug_assertions, contract(
1680 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1681 ensures(old(self.roots.clone()) == self.roots),
1682 ensures(old(self.active.clone()) == self.active),
1683 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1684 invariant(self.validate())
1685 ))]
1686 fn sort_roots_by(
1687 &mut self,
1688 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1689 ) {
1690 self.roots
1691 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1692 }
1693 #[cfg_attr(debug_assertions, contract(
1694 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1695 ensures(old(self.roots.clone()) == self.roots),
1696 ensures(old(self.active.clone()) == self.active),
1697 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1698 invariant(self.validate())
1699 ))]
1700 fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1701 self.roots.sort_by(cmp);
1702 }
1703}
1704
1705impl<K, T, M, S> SortableBookmarkableWeave<K, IndependentNode<K, T, S>, T>
1706 for IndependentWeave<K, T, M, S>
1707where
1708 K: Hash + Copy + Eq + Ord,
1709 T: IndependentContents,
1710 S: BuildHasher + Default + Clone,
1711{
1712 #[cfg_attr(debug_assertions, contract(
1713 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1714 ensures(old(self.roots.clone()) == self.roots),
1715 ensures(old(self.active.clone()) == self.active),
1716 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1717 invariant(self.validate())
1718 ))]
1719 fn sort_bookmarks_by(
1720 &mut self,
1721 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1722 ) {
1723 self.bookmarked
1724 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1725 }
1726 #[cfg_attr(debug_assertions, contract(
1727 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1728 ensures(old(self.roots.clone()) == self.roots),
1729 ensures(old(self.active.clone()) == self.active),
1730 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1731 invariant(self.validate())
1732 ))]
1733 fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1734 self.bookmarked.sort_by(cmp);
1735 }
1736}
1737
1738impl<K, T, M, S> ActivePathWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1739where
1740 K: Hash + Copy + Eq + Ord,
1741 T: IndependentContents,
1742 S: BuildHasher + Default + Clone,
1743{
1744 type Active = HashSet<K, S>;
1745
1746 #[inline]
1747 fn active(&self) -> &Self::Active {
1748 &self.active
1749 }
1750 #[cfg_attr(debug_assertions, contract(
1751 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1752 ensures(old(self.roots.clone()) == self.roots),
1753 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1754 invariant(self.validate())
1755 ))]
1756 fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
1757 self.active.iter().for_each(|active| {
1758 self.nodes.get_mut(active).unwrap().active = false;
1759 });
1760 self.active.clear();
1761 self.active
1762 .extend(active.filter(|id| self.nodes.contains_key(id)));
1763 self.active.iter().for_each(|active| {
1764 self.nodes.get_mut(active).unwrap().active = true;
1765 });
1766 self.fix_orphaned_activations();
1767 }
1768}
1769
1770impl<K, T, M, S> DiscreteWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1771where
1772 K: Hash + Copy + Eq + Ord,
1773 T: IndependentContents + DiscreteContents,
1774 S: BuildHasher + Default + Clone,
1775{
1776 #[cfg_attr(debug_assertions, contract(
1777 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1778 ensures(!ret || self.nodes.contains_key(id)),
1779 ensures(!ret || self.nodes.contains_key(&new_id)),
1780 ensures(!ret || old(!self.nodes.contains_key(&new_id))),
1781 ensures(!ret || self.nodes[id].to.contains(&new_id) && self.nodes[id].to.len() == 1),
1782 ensures(!ret || self.nodes[&new_id].from.contains(id) && self.nodes[&new_id].from.len() == 1),
1783 ensures(!ret || old(self.nodes.get(id).map(|n| n.to.clone())).unwrap() == self.nodes[&new_id].to),
1784 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1785 ensures(ret || old(self.active.clone()) == self.active),
1786 ensures(old(self.roots.clone()) == self.roots),
1787 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1788 invariant(self.validate())
1789 ))]
1790 fn split_node(&mut self, id: &K, at: usize, new_id: K) -> bool {
1791 if self.nodes.contains_key(&new_id) || *id == new_id {
1792 return false;
1793 }
1794
1795 if let Some(mut node) = self.nodes.remove(id) {
1796 match node.contents.split(at) {
1797 DiscreteContentResult::Two(left, right) => {
1798 let left_node = IndependentNode {
1799 id: node.id,
1800 from: node.from,
1801 to: IndexSet::from_iter([new_id]),
1802 active: node.active,
1803 bookmarked: node.bookmarked,
1804 contents: left,
1805 };
1806
1807 node.from = IndexSet::from_iter([node.id]);
1808 node.id = new_id;
1809 node.contents = right;
1810 node.active = false;
1811 node.bookmarked = false;
1812
1813 for child in &node.to {
1814 let child = self.nodes.get_mut(child).unwrap();
1815
1816 if let Some(index) = child.from.get_index_of(&left_node.id) {
1817 if child.from.replace_index(index, node.id).is_err() {
1818 child.from.shift_remove_index(index);
1819 }
1820 } else {
1821 child.from.insert(node.id);
1822 }
1823 if child.active && left_node.active {
1824 node.active = true;
1825 self.active.insert(node.id);
1826 }
1827 }
1828
1829 self.nodes.insert(left_node.id, left_node);
1830 self.nodes.insert(node.id, node);
1831
1832 true
1833 }
1834 DiscreteContentResult::One(content) => {
1835 node.contents = content;
1836 self.nodes.insert(node.id, node);
1837 false
1838 }
1839 }
1840 } else {
1841 false
1842 }
1843 }
1844 #[cfg_attr(debug_assertions, contract(
1845 ensures(ret.is_none() || old(self.nodes.len()) - 1 == self.nodes.len()),
1846 ensures(ret.is_none() || !self.nodes.contains_key(id)),
1847 ensures(ret.is_none() || old(self.nodes.contains_key(id))),
1848 ensures(ret.is_none() || !old(self.contains_active(id)) || old(self.contains_active(id)) && self.contains_active(&ret.unwrap())),
1849 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),
1850 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),
1851 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.to.clone())).unwrap() == self.nodes[&ret.unwrap()].to),
1852 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.from.len() == 1)).unwrap()),
1853 ensures(ret.is_none() || ret.unwrap() == old(self.nodes.get(id).and_then(|node| node.from.first().copied())).unwrap()),
1854 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1855 ensures(ret.is_some() || old(self.active.clone()) == self.active),
1856 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1857 ensures(old(self.roots.clone()) == self.roots),
1858 invariant(self.validate())
1859 ))]
1860 fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1861 if let Some(mut node) = self.nodes.remove(id) {
1862 if node.from.len() != 1 {
1863 self.nodes.insert(node.id, node);
1864 return None;
1865 }
1866
1867 if let Some(mut parent) = node.from.first().and_then(|id| self.nodes.remove(id)) {
1868 if parent.to.len() > 1 {
1869 self.nodes.insert(parent.id, parent);
1870 self.nodes.insert(node.id, node);
1871 return None;
1872 }
1873
1874 match parent.contents.merge(node.contents) {
1875 DiscreteContentResult::Two(left, right) => {
1876 parent.contents = left;
1877 node.contents = right;
1878 self.nodes.insert(parent.id, parent);
1879 self.nodes.insert(node.id, node);
1880 None
1881 }
1882 DiscreteContentResult::One(content) => {
1883 parent.contents = content;
1884 parent.to = node.to;
1885
1886 for child in &parent.to {
1887 let child = self.nodes.get_mut(child).unwrap();
1888
1889 if let Some(index) = child.from.get_index_of(&node.id) {
1890 if child.from.replace_index(index, parent.id).is_err() {
1891 child.from.shift_remove_index(index);
1892 }
1893 } else {
1894 child.from.insert(parent.id);
1895 }
1896 }
1897
1898 let parent_id = parent.id;
1899
1900 self.nodes.insert(parent.id, parent);
1901
1902 self.bookmarked.shift_remove(&node.id);
1903 self.active.remove(&node.id);
1904
1905 Some(parent_id)
1906 }
1907 }
1908 } else {
1909 self.nodes.insert(node.id, node);
1910 None
1911 }
1912 } else {
1913 None
1914 }
1915 }
1916}
1917
1918impl<K, T, M, S> crate::SemiIndependentWeave<K, IndependentNode<K, T, S>, T>
1919 for IndependentWeave<K, T, M, S>
1920where
1921 K: Hash + Copy + Eq + Ord,
1922 T: IndependentContents,
1923 S: BuildHasher + Default + Clone,
1924{
1925 #[cfg_attr(debug_assertions, contract(
1926 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1927 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1928 ensures(old(self.roots.clone()) == self.roots),
1929 ensures(old(self.active.clone()) == self.active),
1930 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1931 invariant(self.validate())
1932 ))]
1933 #[inline]
1934 fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1935 self.nodes
1936 .get_mut(id)
1937 .map(|node| callback(&mut node.contents))
1938 }
1939}
1940
1941impl<K, T, M, S> DeduplicatableWeave<K, IndependentNode<K, T, S>, T>
1942 for IndependentWeave<K, T, M, S>
1943where
1944 K: Hash + Copy + Eq + Ord,
1945 T: IndependentContents + DeduplicatableContents,
1946 S: BuildHasher + Default + Clone,
1947{
1948 fn find_duplicates(&self, id: &K) -> impl Iterator<Item = K> {
1949 self.nodes.get(id).into_iter().flat_map(|node| {
1950 self.sibling_ids_from_all_parents_including_roots(node)
1951 .filter_map(|id| self.nodes.get(&id))
1952 .filter_map(|sibling| {
1953 if node.contents.is_duplicate_of(&sibling.contents) {
1954 Some(sibling.id)
1955 } else {
1956 None
1957 }
1958 })
1959 })
1960 }
1961}
1962
1963impl<K, T, M, S> crate::IndependentWeave<K, IndependentNode<K, T, S>, T>
1964 for IndependentWeave<K, T, M, S>
1965where
1966 K: Hash + Copy + Eq + Ord,
1967 T: IndependentContents,
1968 S: BuildHasher + Default + Clone,
1969{
1970 #[cfg_attr(debug_assertions, contract(
1971 ensures(!ret || self.nodes[id].from.iter().copied().collect::<HashSet<_>>() == new_parents.iter().copied().collect::<HashSet<_>>()),
1972 ensures(ret || old(self.nodes().get(id).map(|node| node.from.clone())).as_ref() == self.nodes().get(id).map(|node| &node.from)),
1973 ensures(ret || old(self.roots.clone()) == self.roots),
1974 ensures(ret || old(self.active.clone()) == self.active),
1975 ensures(old(self.nodes().get(id).map(|node| node.to.clone())).as_ref() == self.nodes().get(id).map(|node| &node.to)),
1976 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1977 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1978 ensures(old(self.active.contains(id)) == self.active.contains(id)),
1979 invariant(self.validate())
1980 ))]
1981 fn move_node(&mut self, id: &K, new_parents: &[K]) -> bool {
1982 if new_parents
1983 .iter()
1984 .any(|new_parent| !self.nodes.contains_key(new_parent))
1985 {
1986 return false;
1987 }
1988
1989 if let Some(node) = self.nodes.get(id)
1990 && !node.to.is_empty()
1991 && !new_parents.is_empty()
1992 {
1993 for child in node.to.iter().copied() {
1994 descendant_subgraph(
1995 &self.nodes,
1996 child,
1997 &mut self.scratchpad_stack,
1998 &mut self.scratchpad_set,
1999 );
2000 }
2001
2002 if new_parents
2003 .iter()
2004 .any(|new_parent| self.scratchpad_set.contains(new_parent))
2005 {
2006 self.scratchpad_set.clear();
2007 return false;
2008 }
2009
2010 self.scratchpad_set.clear();
2011 }
2012
2013 let new_parents: IndexSet<K, S> = new_parents.iter().copied().collect();
2014
2015 if new_parents.contains(id) {
2016 return false;
2017 }
2018
2019 if let Some(node) = self.nodes.get_mut(id) {
2020 for child in &node.to {
2021 if new_parents.contains(child) {
2022 return false;
2023 }
2024 }
2025
2026 let old_parents = mem::take(&mut node.from);
2027
2028 for old_parent in &old_parents {
2029 if !new_parents.contains(old_parent)
2030 && let Some(old_parent) = self.nodes.get_mut(old_parent)
2031 {
2032 old_parent.to.shift_remove(id);
2033 }
2034 }
2035
2036 for new_parent in &new_parents {
2037 if !old_parents.contains(new_parent)
2038 && let Some(new_parent) = self.nodes.get_mut(new_parent)
2039 {
2040 new_parent.to.insert(*id);
2041 }
2042 }
2043 } else {
2044 return false;
2045 }
2046
2047 let node = self.nodes.get_mut(id).unwrap();
2048 node.from = new_parents;
2049
2050 if node.from.is_empty() {
2051 self.roots.insert(node.id);
2052 } else {
2053 self.roots.shift_remove(&node.id);
2054 }
2055
2056 if node.active {
2057 node.active = false;
2058 self.update_node_activity_in_place(id, true);
2059 }
2060
2061 true
2062 }
2063}
2064
2065#[cfg(feature = "rkyv")]
2066impl<K, T, S> ArchivedIndependentNode<K, T, S>
2067where
2068 K: Archive + Hash + Copy + Eq + Ord,
2069 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2070 T: Archive + IndependentContents,
2071 S: BuildHasher + Default + Clone,
2072{
2073 #[inline]
2074 fn validate(&self) -> bool {
2075 (if self.from.len() <= self.to.len() {
2076 self.from.iter().all(|v| !self.to.contains(v))
2077 } else {
2078 self.to.iter().all(|v| !self.from.contains(v))
2079 }) && !self.from.contains(&self.id)
2080 && !self.to.contains(&self.id)
2081 }
2082}
2083
2084#[cfg(feature = "rkyv")]
2085impl<K, T, S> Node<K::Archived, T::Archived> for ArchivedIndependentNode<K, T, S>
2086where
2087 K: Archive + Hash + Copy + Eq + Ord,
2088 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2089 T: Archive + IndependentContents,
2090 S: BuildHasher + Default + Clone,
2091{
2092 type From = ArchivedIndexSet<K::Archived>;
2093 type To = ArchivedIndexSet<K::Archived>;
2094
2095 #[inline]
2096 fn id(&self) -> K::Archived {
2097 self.id
2098 }
2099 #[inline]
2100 fn from(&self) -> &Self::From {
2101 &self.from
2102 }
2103 #[inline]
2104 fn to(&self) -> &Self::To {
2105 &self.to
2106 }
2107 #[inline]
2108 fn is_active(&self) -> bool {
2109 self.active
2110 }
2111 #[inline]
2112 fn contents(&self) -> &T::Archived {
2113 &self.contents
2114 }
2115}
2116
2117#[cfg(feature = "rkyv")]
2118impl<K, T, M, S> ArchivedIndependentWeave<K, T, M, S>
2119where
2120 K: Archive + Hash + Copy + Eq + Ord,
2121 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2122 T: Archive + IndependentContents,
2123 M: Archive,
2124 S: BuildHasher + Default + Clone,
2125{
2126 fn validate(&self) -> bool {
2127 let mut scratchpad = Vec::with_capacity(self.nodes.len());
2128 let mut scratchpad_map = HashMap::with_capacity(self.nodes.len());
2129
2130 self.roots
2131 .iter()
2132 .all(move |value| self.nodes.contains_key(value))
2133 && self
2134 .active
2135 .iter()
2136 .all(move |value| self.nodes.contains_key(value))
2137 && self
2138 .bookmarked
2139 .iter()
2140 .all(move |value| self.nodes.contains_key(value))
2141 && self.nodes.iter().all(|(key, value)| {
2142 value.validate()
2143 && value.id == *key
2144 && value
2145 .from
2146 .iter()
2147 .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
2148 && value
2149 .to
2150 .iter()
2151 .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
2152 && value.from.is_empty() == self.roots.contains(key)
2153 && value.active == self.active.contains(key)
2154 && value.bookmarked == self.bookmarked.contains(key)
2155 })
2156 && !archived_detect_cycles(
2157 &self.nodes,
2158 self.roots.iter().copied(),
2159 &mut scratchpad,
2160 &mut scratchpad_map,
2161 )
2162 && archived_active_path_is_valid(&self.nodes, self.roots.iter(), &self.active)
2163 }
2164}
2165
2166#[cfg(feature = "rkyv")]
2167unsafe impl<K, T, M, S, C> Verify<C> 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 C: Fallible + ?Sized,
2177 C::Error: Source,
2178{
2179 fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
2180 if !self.validate() {
2181 fail!(ValidationError)
2182 }
2183
2184 Ok(())
2185 }
2186}
2187
2188#[cfg(feature = "rkyv")]
2189impl<K, T, M, S> ImmutableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2190 for ArchivedIndependentWeave<K, T, M, S>
2191where
2192 K: Archive + Hash + Copy + Eq + Ord,
2193 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2194 T: Archive + IndependentContents,
2195 M: Archive,
2196 S: BuildHasher + Default + Clone,
2197{
2198 type Nodes = ArchivedHashMap<K::Archived, ArchivedIndependentNode<K, T, S>>;
2199 type Roots = ArchivedIndexSet<K::Archived>;
2200
2201 #[inline]
2202 fn len(&self) -> usize {
2203 self.nodes.len()
2204 }
2205 #[inline]
2206 fn is_empty(&self) -> bool {
2207 self.nodes.is_empty()
2208 }
2209 #[inline]
2210 fn nodes(&self) -> &Self::Nodes {
2211 &self.nodes
2212 }
2213 #[inline]
2214 fn roots(&self) -> &Self::Roots {
2215 &self.roots
2216 }
2217 #[inline]
2218 fn contains(&self, id: &K::Archived) -> bool {
2219 self.nodes.contains_key(id)
2220 }
2221 #[inline]
2222 fn contains_active(&self, id: &K::Archived) -> bool {
2223 self.active.contains(id)
2224 }
2225 #[inline]
2226 fn get_node(&self, id: &K::Archived) -> Option<&ArchivedIndependentNode<K, T, S>> {
2227 self.nodes.get(id)
2228 }
2229 fn get_ordered_node_identifiers(&self, output: &mut Vec<K::Archived>) {
2230 output.clear();
2231 let mut scratchpad = Vec::with_capacity(self.len());
2232 let mut scratchpad_2 = Vec::with_capacity(self.len());
2233 let mut identifier_set = HashSet::with_capacity(self.len());
2234 let mut scratchpad_map = HashMap::with_capacity(self.len());
2235
2236 for root in self.roots.iter() {
2237 archived_topological_sort(
2238 &self.nodes,
2239 root,
2240 &mut scratchpad,
2241 &mut scratchpad_2,
2242 output,
2243 &mut identifier_set,
2244 &mut scratchpad_map,
2245 );
2246 }
2247 }
2248 fn get_ordered_node_identifiers_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2249 output.clear();
2250
2251 if self.nodes.contains_key(id) {
2252 let mut scratchpad = Vec::with_capacity(self.len());
2253 let mut scratchpad_2 = Vec::with_capacity(self.len());
2254 let mut scratchpad_set = HashSet::with_capacity(self.len());
2255 let mut scratchpad_set_2 = HashSet::with_capacity(self.len());
2256 let mut scratchpad_map = HashMap::with_capacity(self.len());
2257
2258 archived_descendant_subgraph(&self.nodes, *id, &mut scratchpad, &mut scratchpad_set);
2259
2260 archived_topological_sort_subgraph(
2261 &self.nodes,
2262 &|id| scratchpad_set.contains(id),
2263 id,
2264 &mut scratchpad,
2265 &mut scratchpad_2,
2266 output,
2267 &mut scratchpad_set_2,
2268 &mut scratchpad_map,
2269 );
2270 }
2271 }
2272 fn get_active_path(&self, output: &mut Vec<K::Archived>) {
2273 output.clear();
2274 let mut scratchpad_list = Vec::with_capacity(self.len());
2275 let mut scratchpad_list_2 = Vec::with_capacity(self.len());
2276 let mut scratchpad_list_3 = Vec::with_capacity(self.len());
2277 let mut scratchpad_set = HashSet::with_capacity(self.len());
2278 let mut scratchpad_map = HashMap::with_capacity(self.len());
2279
2280 for root in self.roots.iter() {
2281 archived_topological_sort_subgraph(
2282 &self.nodes,
2283 &|id| self.active.contains(id),
2284 root,
2285 &mut scratchpad_list,
2286 &mut scratchpad_list_2,
2287 &mut scratchpad_list_3,
2288 &mut scratchpad_set,
2289 &mut scratchpad_map,
2290 );
2291 }
2292
2293 scratchpad_map.clear();
2294
2295 archived_longest_candidate_path_to_root(
2296 &self.nodes,
2297 &scratchpad_list_3,
2298 &|id| self.active.contains(id),
2299 &mut scratchpad_map,
2300 output,
2301 );
2302 }
2303 fn get_path_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2304 output.clear();
2305 if !self.nodes.contains_key(id) {
2306 return;
2307 }
2308
2309 let mut scratchpad_list = Vec::with_capacity(self.len());
2310 let mut scratchpad_list_2 = Vec::with_capacity(self.len());
2311 let mut scratchpad_stack = Vec::with_capacity(self.len());
2312 let mut scratchpad_queue = VecDeque::with_capacity(self.len());
2313 let mut scratchpad_set = HashSet::with_capacity(self.len());
2314 let mut scratchpad_set_2 = HashSet::with_capacity(self.len());
2315 let mut scratchpad_map = HashMap::with_capacity(self.len());
2316 let mut scratchpad_map_2 = HashMap::with_capacity(self.len());
2317
2318 archived_ancestor_subgraph(&self.nodes, *id, &mut scratchpad_stack, &mut scratchpad_set);
2319
2320 for root in self.roots.iter() {
2321 archived_topological_sort_subgraph(
2322 &self.nodes,
2323 &|id| self.active.contains(id),
2324 root,
2325 &mut scratchpad_stack,
2326 &mut scratchpad_list_2,
2327 &mut scratchpad_list,
2328 &mut scratchpad_set_2,
2329 &mut scratchpad_map,
2330 );
2331 }
2332
2333 scratchpad_map.clear();
2334
2335 archived_longest_candidate_path_to_root(
2336 &self.nodes,
2337 &scratchpad_list,
2338 &|id| self.active.contains(id) && scratchpad_set.contains(id),
2339 &mut scratchpad_map,
2340 &mut scratchpad_list_2,
2341 );
2342
2343 scratchpad_set_2.clear();
2344
2345 if let Some(target) = scratchpad_list_2.first().copied() {
2346 archived_shortest_path_to_ancestor(
2347 &self.nodes,
2348 id,
2349 &|node| node.id == target,
2350 &mut scratchpad_queue,
2351 &mut scratchpad_map_2,
2352 &mut scratchpad_set_2,
2353 output,
2354 );
2355
2356 output.reverse();
2357 output.pop();
2358 output.append(&mut scratchpad_list_2);
2359 } else {
2360 archived_shortest_path_to_ancestor(
2361 &self.nodes,
2362 id,
2363 &|node| node.from.is_empty(),
2364 &mut scratchpad_queue,
2365 &mut scratchpad_map_2,
2366 &mut scratchpad_set_2,
2367 output,
2368 );
2369
2370 output.reverse();
2371 }
2372 }
2373}
2374
2375#[cfg(feature = "rkyv")]
2376impl<K, T, M, S>
2377 ImmutableMetadataWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived, M::Archived>
2378 for ArchivedIndependentWeave<K, T, M, S>
2379where
2380 K: Archive + Hash + Copy + Eq + Ord,
2381 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2382 T: Archive + IndependentContents,
2383 M: Archive,
2384 S: BuildHasher + Default + Clone,
2385{
2386 #[inline]
2387 fn metadata(&self) -> &M::Archived {
2388 &self.metadata
2389 }
2390}
2391
2392#[cfg(feature = "rkyv")]
2393impl<K, T, M, S>
2394 ImmutableBookmarkableWeave<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 type Bookmarks = ArchivedIndexSet<K::Archived>;
2404
2405 #[inline]
2406 fn bookmarks(&self) -> &Self::Bookmarks {
2407 &self.bookmarked
2408 }
2409 #[inline]
2410 fn contains_bookmark(&self, id: &K::Archived) -> bool {
2411 self.bookmarked.contains(id)
2412 }
2413}
2414
2415#[cfg(feature = "rkyv")]
2416impl<K, T, M, S> ImmutableSortableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2417 for ArchivedIndependentWeave<K, T, M, S>
2418where
2419 K: Archive + Hash + Copy + Eq + Ord,
2420 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2421 T: Archive + IndependentContents,
2422 M: Archive,
2423 S: BuildHasher + Default + Clone,
2424{
2425 fn get_ordered_node_identifiers_mirrored(&self, output: &mut Vec<K::Archived>) {
2426 output.clear();
2427 let mut scratchpad = Vec::with_capacity(self.len());
2428 let mut identifier_set = HashSet::with_capacity(self.len());
2429 let mut scratchpad_map = HashMap::with_capacity(self.len());
2430
2431 for root in self.roots.iter() {
2432 archived_topological_sort_mirrored(
2433 &self.nodes,
2434 root,
2435 &mut scratchpad,
2436 output,
2437 &mut identifier_set,
2438 &mut scratchpad_map,
2439 );
2440 }
2441 }
2442 fn get_ordered_node_identifiers_mirrored_from(
2443 &self,
2444 id: &K::Archived,
2445 output: &mut Vec<K::Archived>,
2446 ) {
2447 output.clear();
2448
2449 if self.nodes.contains_key(id) {
2450 let mut scratchpad = Vec::with_capacity(self.len());
2451 let mut scratchpad_set = HashSet::with_capacity(self.len());
2452 let mut scratchpad_set_2 = HashSet::with_capacity(self.len());
2453 let mut scratchpad_map = HashMap::with_capacity(self.len());
2454
2455 archived_descendant_subgraph(&self.nodes, *id, &mut scratchpad, &mut scratchpad_set);
2456
2457 archived_topological_sort_subgraph_mirrored(
2458 &self.nodes,
2459 &|id| scratchpad_set.contains(id),
2460 id,
2461 &mut scratchpad,
2462 output,
2463 &mut scratchpad_set_2,
2464 &mut scratchpad_map,
2465 );
2466 }
2467 }
2468}
2469
2470#[cfg(feature = "rkyv")]
2471impl<K, T, M, S>
2472 ImmutableActivePathWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2473 for ArchivedIndependentWeave<K, T, M, S>
2474where
2475 K: Archive + Hash + Copy + Eq + Ord,
2476 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2477 T: Archive + IndependentContents,
2478 M: Archive,
2479 S: BuildHasher + Default + Clone,
2480{
2481 type Active = ArchivedHashSet<K::Archived>;
2482
2483 #[inline]
2484 fn active(&self) -> &Self::Active {
2485 &self.active
2486 }
2487}
2488
2489#[cfg(feature = "rkyv")]
2490fn archived_topological_sort<'a, K, N, T, S>(
2491 nodes: &'a ArchivedHashMap<K, N>,
2492 id: &'a K,
2493 scratchpad: &mut Vec<K>,
2494 scratchpad_2: &mut Vec<K>,
2495 identifiers: &mut Vec<K>,
2496 identifier_set: &mut HashSet<K, S>,
2497 identifier_map: &mut HashMap<K, usize, S>,
2498) where
2499 K: Hash + Copy + Eq + Ord + 'a,
2500 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2501 S: BuildHasher + Default + Clone,
2502{
2503 scratchpad.push(*id);
2504
2505 while let Some(id) = scratchpad.pop() {
2506 let node = &nodes[&id];
2507
2508 if identifier_set.contains(&id)
2509 || identifier_map
2510 .get(&id)
2511 .copied()
2512 .unwrap_or_else(|| node.from().len())
2513 != 0
2514 {
2515 continue;
2516 }
2517
2518 identifiers.push(id);
2519 identifier_set.insert(id);
2520
2521 for child in node.to().iter().copied() {
2522 let remaining = identifier_map
2523 .entry(child)
2524 .or_insert_with(|| nodes[&child].from().len());
2525 *remaining = remaining.strict_sub(1);
2526
2527 scratchpad_2.push(child);
2528 }
2529
2530 scratchpad_2.reverse();
2531 scratchpad.append(scratchpad_2);
2532 }
2533}
2534
2535#[cfg(feature = "rkyv")]
2536#[allow(clippy::too_many_arguments, reason = "Rkyv limitation")]
2537fn archived_topological_sort_subgraph<'a, K, N, T, S>(
2538 nodes: &'a ArchivedHashMap<K, N>,
2539 filter: &impl Fn(&K) -> bool,
2540 id: &'a K,
2541 scratchpad: &mut Vec<K>,
2542 scratchpad_2: &mut Vec<K>,
2543 identifiers: &mut Vec<K>,
2544 identifier_set: &mut HashSet<K, S>,
2545 identifier_map: &mut HashMap<K, usize, S>,
2546) where
2547 K: Hash + Copy + Eq + Ord + 'a,
2548 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2549 S: BuildHasher + Default + Clone,
2550{
2551 scratchpad.push(*id);
2552
2553 while let Some(id) = scratchpad.pop() {
2554 let node = &nodes[&id];
2555
2556 if !filter(&id)
2557 || identifier_set.contains(&id)
2558 || identifier_map
2559 .get(&id)
2560 .copied()
2561 .unwrap_or_else(|| node.from().iter().filter(|&parent| filter(parent)).count())
2562 != 0
2563 {
2564 continue;
2565 }
2566
2567 identifiers.push(id);
2568 identifier_set.insert(id);
2569
2570 for child in node.to().iter().copied() {
2571 let remaining = identifier_map.entry(child).or_insert_with(|| {
2572 nodes[&child]
2573 .from()
2574 .iter()
2575 .filter(|&parent| filter(parent))
2576 .count()
2577 });
2578 *remaining = remaining.strict_sub(1);
2579
2580 scratchpad_2.push(child);
2581 }
2582
2583 scratchpad_2.reverse();
2584 scratchpad.append(scratchpad_2);
2585 }
2586}
2587
2588#[cfg(feature = "rkyv")]
2589fn archived_topological_sort_subgraph_mirrored<'a, K, N, T, S>(
2590 nodes: &'a ArchivedHashMap<K, N>,
2591 filter: &impl Fn(&K) -> bool,
2592 id: &'a K,
2593 scratchpad: &mut Vec<K>,
2594 identifiers: &mut Vec<K>,
2595 identifier_set: &mut HashSet<K, S>,
2596 identifier_map: &mut HashMap<K, usize, S>,
2597) where
2598 K: Hash + Copy + Eq + Ord + 'a,
2599 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2600 S: BuildHasher + Default + Clone,
2601{
2602 scratchpad.push(*id);
2603
2604 while let Some(id) = scratchpad.pop() {
2605 let node = &nodes[&id];
2606
2607 if !filter(&id)
2608 || identifier_set.contains(&id)
2609 || identifier_map
2610 .get(&id)
2611 .copied()
2612 .unwrap_or_else(|| node.from().iter().filter(|&parent| filter(parent)).count())
2613 != 0
2614 {
2615 continue;
2616 }
2617
2618 identifiers.push(id);
2619 identifier_set.insert(id);
2620
2621 for child in node.to().iter().copied() {
2622 let remaining = identifier_map.entry(child).or_insert_with(|| {
2623 nodes[&child]
2624 .from()
2625 .iter()
2626 .filter(|&parent| filter(parent))
2627 .count()
2628 });
2629 *remaining = remaining.strict_sub(1);
2630
2631 scratchpad.push(child);
2632 }
2633 }
2634}
2635
2636#[cfg(feature = "rkyv")]
2637fn archived_topological_sort_mirrored<'a, K, N, T, S>(
2638 nodes: &'a ArchivedHashMap<K, N>,
2639 id: &'a K,
2640 scratchpad: &mut Vec<K>,
2641 identifiers: &mut Vec<K>,
2642 identifier_set: &mut HashSet<K, S>,
2643 identifier_map: &mut HashMap<K, usize, S>,
2644) where
2645 K: Hash + Copy + Eq + Ord + 'a,
2646 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2647 S: BuildHasher + Default + Clone,
2648{
2649 scratchpad.push(*id);
2650
2651 while let Some(id) = scratchpad.pop() {
2652 let node = &nodes[&id];
2653
2654 if identifier_set.contains(&id)
2655 || identifier_map
2656 .get(&id)
2657 .copied()
2658 .unwrap_or_else(|| node.from().len())
2659 != 0
2660 {
2661 continue;
2662 }
2663
2664 identifiers.push(id);
2665 identifier_set.insert(id);
2666
2667 for child in node.to().iter().copied() {
2668 let remaining = identifier_map
2669 .entry(child)
2670 .or_insert_with(|| nodes[&child].from().len());
2671 *remaining = remaining.strict_sub(1);
2672
2673 scratchpad.push(child);
2674 }
2675 }
2676}
2677
2678#[cfg(feature = "rkyv")]
2679fn archived_detect_cycles<'a, K, N, T, S>(
2680 nodes: &'a ArchivedHashMap<K, N>,
2681 roots: impl Iterator<Item = K>,
2682 scratchpad: &mut Vec<Step<K, K>>,
2683 scratchpad_map: &mut HashMap<K, bool, S>,
2684) -> bool
2685where
2686 K: Hash + Copy + Eq + Ord + 'a,
2687 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2688 S: BuildHasher + Default + Clone,
2689{
2690 for root in roots {
2691 if scratchpad_map.contains_key(&root) {
2692 continue;
2693 }
2694
2695 scratchpad.push(Step::Enter(root));
2696
2697 while let Some(step) = scratchpad.pop() {
2698 match step {
2699 Step::Enter(id) => {
2700 scratchpad.push(Step::Exit(id));
2701
2702 match scratchpad_map.entry(id) {
2703 Entry::Occupied(entry) => {
2704 if !entry.get() {
2705 return true;
2706 }
2707 }
2708 Entry::Vacant(entry) => {
2709 entry.insert_entry(false);
2710
2711 scratchpad.extend(nodes[&id].to().iter().copied().map(Step::Enter));
2712 }
2713 }
2714 }
2715 Step::Exit(id) => {
2716 scratchpad_map.insert(id, true);
2717 }
2718 }
2719 }
2720 }
2721
2722 scratchpad_map.len() != nodes.len()
2723}
2724
2725#[cfg(feature = "rkyv")]
2726#[allow(clippy::too_many_arguments, reason = "Rkyv limitation")]
2727fn archived_shortest_path_to_ancestor<'a, K, N, T, S>(
2728 nodes: &'a ArchivedHashMap<K, N>,
2729 id: &'a K,
2730 target: &impl Fn(&'a N) -> bool,
2731 scratchpad: &mut VecDeque<K>,
2732 scratchpad_map: &mut HashMap<K, K, S>,
2733 scratchpad_set: &mut HashSet<K, S>,
2734 path: &mut Vec<K>,
2735) where
2736 K: Hash + Copy + Eq + Ord + 'a,
2737 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2738 S: BuildHasher + Default + Clone,
2739{
2740 scratchpad.push_front(*id);
2741 scratchpad_set.insert(*id);
2742
2743 while let Some(id) = scratchpad.pop_back() {
2744 let node = &nodes[&id];
2745
2746 if target(node) {
2747 scratchpad.clear();
2748
2749 path.push(id);
2750
2751 while let Some(child) = scratchpad_map.remove(path.last().unwrap()) {
2752 path.push(child);
2753 }
2754
2755 return;
2756 }
2757
2758 for parent in node.from().iter().copied() {
2759 if scratchpad_set.insert(parent) {
2760 scratchpad.push_front(parent);
2761 scratchpad_map.insert(parent, id);
2762 }
2763 }
2764 }
2765}
2766
2767#[cfg(feature = "rkyv")]
2768fn archived_longest_candidate_path_to_root<'a, K, N, T, S>(
2769 nodes: &'a ArchivedHashMap<K, N>,
2770 topological_order: &'a [K],
2771 is_candidate: &impl Fn(&K) -> bool,
2772 scratchpad_map: &mut HashMap<K, usize, S>,
2773 reversed_path: &mut Vec<K>,
2774) where
2775 K: Hash + Copy + Eq + Ord + 'a,
2776 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2777 S: BuildHasher + Default + Clone,
2778{
2779 let mut longest_distance = None;
2780
2781 for id in topological_order {
2782 if !is_candidate(id) {
2783 continue;
2784 }
2785
2786 let node = &nodes[id];
2787 let distance = if node.from().is_empty() {
2788 Some(0)
2789 } else {
2790 node.from()
2791 .iter()
2792 .filter_map(|parent| scratchpad_map.get(parent).copied())
2793 .max()
2794 .map(|l| l.strict_add(1))
2795 };
2796
2797 if let Some(distance) = distance {
2798 scratchpad_map.insert(*id, distance);
2799
2800 if longest_distance.is_none_or(|(value, _)| distance > value) {
2801 longest_distance = Some((distance, id));
2802 }
2803 }
2804 }
2805
2806 let mut current = longest_distance.map(|(_, id)| id);
2807
2808 while let Some(id) = current {
2809 reversed_path.push(*id);
2810
2811 current = nodes[id]
2812 .from()
2813 .iter()
2814 .filter(|id| scratchpad_map.contains_key(*id))
2815 .min_by_key(|id| Reverse(scratchpad_map[*id]));
2816 }
2817}
2818
2819#[cfg(feature = "rkyv")]
2820fn archived_ancestor_subgraph<'a, K, N, T, S>(
2821 nodes: &'a ArchivedHashMap<K, N>,
2822 id: K,
2823 scratchpad: &mut Vec<K>,
2824 identifiers: &mut HashSet<K, S>,
2825) where
2826 K: Hash + Copy + Eq + Ord + 'a,
2827 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2828 S: BuildHasher + Default + Clone,
2829{
2830 scratchpad.push(id);
2831
2832 while let Some(id) = scratchpad.pop() {
2833 if identifiers.insert(id) {
2834 scratchpad.extend(nodes[&id].from().iter().copied());
2835 }
2836 }
2837}
2838
2839#[cfg(feature = "rkyv")]
2840fn archived_descendant_subgraph<'a, K, N, T, S>(
2841 nodes: &'a ArchivedHashMap<K, N>,
2842 id: K,
2843 scratchpad: &mut Vec<K>,
2844 identifiers: &mut HashSet<K, S>,
2845) where
2846 K: Hash + Copy + Eq + Ord + 'a,
2847 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2848 S: BuildHasher + Default + Clone,
2849{
2850 scratchpad.push(id);
2851
2852 while let Some(id) = scratchpad.pop() {
2853 if identifiers.insert(id) {
2854 scratchpad.extend(nodes[&id].to().iter().copied());
2855 }
2856 }
2857}
2858
2859#[cfg(feature = "rkyv")]
2860fn archived_active_path_is_valid<'a, K, N, T>(
2861 nodes: &'a ArchivedHashMap<K, N>,
2862 roots: impl Iterator<Item = &'a K>,
2863 active: &'a ArchivedHashSet<K>,
2864) -> bool
2865where
2866 K: Hash + Copy + Eq + Ord + 'a,
2867 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2868{
2869 let mut scratchpad = Vec::with_capacity(nodes.len());
2870 let mut scratchpad_list = Vec::with_capacity(nodes.len());
2871 let mut scratchpad_list_2 = Vec::with_capacity(nodes.len());
2872 let mut scratchpad_set = HashSet::with_capacity(nodes.len());
2873 let mut scratchpad_map = HashMap::with_capacity(nodes.len());
2874
2875 for root in roots {
2876 archived_topological_sort(
2877 nodes,
2878 root,
2879 &mut scratchpad,
2880 &mut scratchpad_list_2,
2881 &mut scratchpad_list,
2882 &mut scratchpad_set,
2883 &mut scratchpad_map,
2884 );
2885 }
2886
2887 scratchpad_list_2.clear();
2888 scratchpad_set.clear();
2889 scratchpad_map.clear();
2890
2891 archived_longest_candidate_path_to_root(
2892 nodes,
2893 &scratchpad_list,
2894 &|id| active.contains(id),
2895 &mut scratchpad_map,
2896 &mut scratchpad_list_2,
2897 );
2898
2899 scratchpad_set.extend(scratchpad_list_2);
2900
2901 scratchpad_set.len() == active.len()
2902 && scratchpad_set.into_iter().all(|id| active.contains(&id))
2903}