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