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