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,
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 if let Some(node) = self.nodes.get_mut(id) {
544 if node.active == value {
545 return true;
546 }
547
548 node.active = value;
549 if value {
550 self.active.insert(node.id);
551 } else {
552 self.active.remove(id);
553 }
554 } else {
555 return false;
556 }
557
558 if value {
559 for root in &self.roots {
560 topological_sort(
561 &self.nodes,
562 root,
563 &mut self.scratchpad_stack,
564 &mut self.scratchpad_list, &mut self.scratchpad_set,
566 &mut self.scratchpad_map,
567 );
568 }
569
570 self.scratchpad_set.clear();
571 self.scratchpad_map.clear();
572
573 for id in self.scratchpad_list.iter().copied() {
574 let node = &self.nodes[&id];
575
576 let best_parent = node
577 .from
578 .iter()
579 .map(|id| (id, self.scratchpad_map_3[id])) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
581
582 let (parent, score) = if let Some((parent, mut score)) = best_parent {
583 if node.active {
584 score.1 = score.1.strict_add(1);
585 } else {
586 score.0 = score.0.strict_add(1);
587 }
588
589 (Some(parent), score)
590 } else {
591 (None, if node.active { (0, 1) } else { (1, 0) })
592 };
593
594 if let Some(parent) = parent {
595 self.scratchpad_map_2.insert(id, *parent); }
597
598 self.scratchpad_map_3.insert(id, score);
599 }
600
601 let mut current = Some(id);
602
603 while let Some(id) = current {
604 self.scratchpad_set.insert(*id);
605 current = self.scratchpad_map_2.get(id);
606 }
607
608 self.scratchpad_map_2.clear();
609 self.scratchpad_map_3.clear();
610
611 for id in self.scratchpad_list.drain(..).rev() {
612 let node = &self.nodes[&id];
613
614 let best_child = node
615 .to
616 .iter()
617 .map(|id| (id, self.scratchpad_map_3[id])) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
619
620 let (child, score) = if let Some((child, mut score)) = best_child {
621 if node.active {
622 score.1 = score.1.strict_add(1);
623 } else {
624 score.0 = score.0.strict_add(1);
625 }
626
627 (Some(child), score)
628 } else {
629 (None, if node.active { (0, 1) } else { (1, 0) })
630 };
631
632 if let Some(child) = child {
633 self.scratchpad_map_2.insert(id, *child); }
635
636 self.scratchpad_map_3.insert(id, score);
637 }
638
639 let mut current = Some(id);
640
641 while let Some(id) = current {
642 self.scratchpad_set.insert(*id);
643
644 current = if self.scratchpad_map_3[id].1 > usize::from(self.nodes[id].active) {
645 self.scratchpad_map_2.get(id)
646 } else {
647 None
648 };
649 }
650
651 self.scratchpad_map_2.clear();
652 self.scratchpad_map_3.clear();
653
654 self.scratchpad_list
655 .extend(self.active.difference(&self.scratchpad_set).copied());
656
657 for id in self.scratchpad_list.drain(..) {
658 self.nodes.get_mut(&id).unwrap().active = false;
659 self.active.remove(&id);
660 }
661
662 self.scratchpad_list
663 .extend(self.scratchpad_set.difference(&self.active).copied());
664
665 self.scratchpad_set.clear();
666
667 for id in self.scratchpad_list.drain(..) {
668 self.nodes.get_mut(&id).unwrap().active = true;
669 self.active.insert(id);
670 }
671 } else {
672 self.fix_orphaned_activations();
673 }
674
675 true
676 }
677 #[cfg_attr(debug_assertions, contract(
678 requires(self.validate_scratchpads()),
679 ensures(self.validate())
680 ))]
681 fn fix_orphaned_activations(&mut self) {
682 for root in &self.roots {
683 topological_sort(
684 &self.nodes,
685 root,
686 &mut self.scratchpad_stack,
687 &mut self.scratchpad_list,
688 &mut self.scratchpad_set,
689 &mut self.scratchpad_map,
690 );
691 }
692
693 self.scratchpad_map.clear();
694
695 longest_candidate_path_to_root(
696 &self.nodes,
697 &self.scratchpad_list,
698 &|id| self.active.contains(id),
699 &mut self.scratchpad_map,
700 &mut self.scratchpad_list_2,
701 );
702
703 self.scratchpad_list.clear();
704 self.scratchpad_set.clear();
705 self.scratchpad_map.clear();
706
707 self.scratchpad_set.extend(self.scratchpad_list_2.drain(..));
708 self.scratchpad_list
709 .extend(self.active.difference(&self.scratchpad_set).copied());
710
711 self.scratchpad_set.clear();
712
713 for orphan in self.scratchpad_list.drain(..) {
714 self.active.remove(&orphan);
715 if let Some(node) = self.nodes.get_mut(&orphan) {
716 node.active = false;
717 }
718 }
719 }
720 #[cfg_attr(debug_assertions, contract(
721 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))))),
722 ensures(!ret || !value || self.contains_active(id) && !self.nodes[id].to.iter().any(|id| self.active.contains(id))),
723 ensures(ret || old(self.active.clone()) == self.active),
724 ensures(ret == self.nodes.contains_key(id)),
725 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
726 ensures(old(self.roots.clone()) == self.roots),
727 ensures(old(self.bookmarked.clone()) == self.bookmarked),
728 invariant(self.validate())
729 ))]
730 #[allow(clippy::missing_panics_doc, reason = "Should never panic")]
731 pub fn set_node_active_status_dependent_semantics(&mut self, id: &K, value: bool) -> bool {
733 if value {
734 if let Some(node) = self.nodes.get(id) {
735 if node.active && !node.to.iter().any(|id| self.active.contains(id)) {
736 return true;
737 }
738 } else {
739 return false;
740 }
741
742 for root in &self.roots {
743 topological_sort(
744 &self.nodes,
745 root,
746 &mut self.scratchpad_stack,
747 &mut self.scratchpad_list, &mut self.scratchpad_set,
749 &mut self.scratchpad_map,
750 );
751 }
752
753 self.scratchpad_set.clear();
754 self.scratchpad_map.clear();
755
756 for id in self.scratchpad_list.drain(..) {
757 let node = &self.nodes[&id];
758
759 let best_parent = node
760 .from
761 .iter()
762 .map(|id| (id, self.scratchpad_map_3[id])) .min_by(|(_, a), (_, b)| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
764
765 let (parent, score) = if let Some((parent, mut score)) = best_parent {
766 if node.active {
767 score.1 = score.1.strict_add(1);
768 } else {
769 score.0 = score.0.strict_add(1);
770 }
771
772 (Some(parent), score)
773 } else {
774 (None, if node.active { (0, 1) } else { (1, 0) })
775 };
776
777 if let Some(parent) = parent {
778 self.scratchpad_map_2.insert(id, *parent); }
780
781 self.scratchpad_map_3.insert(id, score);
782 }
783
784 let mut current = Some(id);
785
786 while let Some(id) = current {
787 self.scratchpad_set.insert(*id);
788 current = self.scratchpad_map_2.get(id);
789 }
790
791 self.scratchpad_map_2.clear();
792 self.scratchpad_map_3.clear();
793
794 self.scratchpad_list
795 .extend(self.active.difference(&self.scratchpad_set).copied());
796
797 for id in self.scratchpad_list.drain(..) {
798 self.nodes.get_mut(&id).unwrap().active = false;
799 self.active.remove(&id);
800 }
801
802 self.scratchpad_list
803 .extend(self.scratchpad_set.difference(&self.active).copied());
804
805 self.scratchpad_set.clear();
806
807 for id in self.scratchpad_list.drain(..) {
808 self.nodes.get_mut(&id).unwrap().active = true;
809 self.active.insert(id);
810 }
811 } else {
812 if let Some(node) = self.nodes.get(id) {
813 if !node.active || node.to.iter().any(|id| self.active.contains(id)) {
814 return true;
815 }
816 } else {
817 return false;
818 }
819
820 self.active.iter().for_each(|active| {
821 self.nodes.get_mut(active).unwrap().active = false;
822 });
823 self.active.clear();
824 }
825
826 true
827 }
828}
829
830impl<K, T, M, S> From<DependentWeave<K, T, M, S>> for IndependentWeave<K, T, M, S>
831where
832 K: Hash + Copy + Eq + Ord,
833 T: IndependentContents,
834 S: BuildHasher + Default + Clone,
835{
836 fn from(value: DependentWeave<K, T, M, S>) -> Self {
837 let mut output = Self {
838 active: HashSet::with_capacity_and_hasher(value.nodes.capacity(), S::default()),
839 scratchpad_list: Vec::with_capacity(value.nodes.capacity()),
840 scratchpad_list_2: Vec::with_capacity(value.nodes.capacity()),
841 scratchpad_set: HashSet::with_capacity_and_hasher(value.nodes.capacity(), S::default()),
842 scratchpad_set_2: HashSet::with_capacity_and_hasher(
843 value.nodes.capacity(),
844 S::default(),
845 ),
846 scratchpad_map: HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default()),
847 scratchpad_map_2: HashMap::with_capacity_and_hasher(
848 value.nodes.capacity(),
849 S::default(),
850 ),
851 scratchpad_map_3: HashMap::with_capacity_and_hasher(
852 value.nodes.capacity(),
853 S::default(),
854 ),
855 scratchpad_stack: Vec::with_capacity(value.nodes.capacity()),
856 scratchpad_queue: VecDeque::with_capacity(value.nodes.capacity()),
857 nodes: {
858 let mut map =
859 HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default());
860 map.extend(value.nodes.into_iter().map(|(id, mut node)| {
861 node.active = false;
862 (id, node.into())
863 }));
864
865 map
866 },
867 roots: value.roots,
868 bookmarked: value.bookmarked,
869 metadata: value.metadata,
870 };
871
872 if let Some(active) = value.active {
873 output.set_node_active_status(&active, true);
874 }
875
876 debug_assert!(output.validate(), "Converted weave is malformed");
877
878 output
879 }
880}
881
882#[allow(clippy::panic_in_result_fn, reason = "Should never panic")]
883#[allow(clippy::unreachable, reason = "Should never panic")]
884impl<K, T, M, S> TryFrom<IndependentWeave<K, T, M, S>> for DependentWeave<K, T, M, S>
885where
886 K: Hash + Copy + Eq + Ord,
887 T: IndependentContents,
888 S: BuildHasher + Default + Clone,
889{
890 type Error = IndependentWeave<K, T, M, S>;
891
892 fn try_from(value: IndependentWeave<K, T, M, S>) -> Result<Self, Self::Error> {
893 if value.nodes.iter().all(|(_, node)| node.from.len() < 2) {
894 let mut active = None;
895
896 let output = Self {
897 nodes: {
898 let mut map =
899 HashMap::with_capacity_and_hasher(value.nodes.capacity(), S::default());
900 map.extend(value.nodes.into_iter().map(|(id, mut node)| {
901 node.active =
902 node.active && !node.to.iter().any(|id| value.active.contains(id));
903 if node.active {
904 active = Some(id);
905 }
906
907 node.try_into()
908 .map_or_else(|_| unreachable!(), |node| (id, node))
909 }));
910
911 map
912 },
913 roots: value.roots,
914 active,
915 bookmarked: value.bookmarked,
916 scratchpad: value.scratchpad_stack,
917 metadata: value.metadata,
918 };
919
920 debug_assert!(output.validate(), "Converted weave is malformed");
921
922 Ok(output)
923 } else {
924 Err(value)
925 }
926 }
927}
928
929impl<K, T, M, S> Weave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
930where
931 K: Hash + Copy + Eq + Ord,
932 T: IndependentContents,
933 S: BuildHasher + Default + Clone,
934{
935 type Nodes = HashMap<K, IndependentNode<K, T, S>, S>;
936 type Roots = IndexSet<K, S>;
937
938 #[inline]
939 fn len(&self) -> usize {
940 self.nodes.len()
941 }
942 #[inline]
943 fn is_empty(&self) -> bool {
944 self.nodes.is_empty()
945 }
946 #[inline]
947 fn nodes(&self) -> &Self::Nodes {
948 &self.nodes
949 }
950 #[inline]
951 fn roots(&self) -> &Self::Roots {
952 &self.roots
953 }
954 #[inline]
955 fn contains(&self, id: &K) -> bool {
956 self.nodes.contains_key(id)
957 }
958 #[inline]
959 fn contains_active(&self, id: &K) -> bool {
960 self.active.contains(id)
961 }
962 #[inline]
963 fn get_node(&self, id: &K) -> Option<&IndependentNode<K, T, S>> {
964 self.nodes.get(id)
965 }
966 #[inline]
967 fn get_node_parents(&self, id: &K) -> Option<&IndexSet<K, S>> {
968 self.nodes.get(id).map(|node| &node.from)
969 }
970 #[inline]
971 fn get_node_children(&self, id: &K) -> Option<&IndexSet<K, S>> {
972 self.nodes.get(id).map(|node| &node.to)
973 }
974 #[cfg_attr(debug_assertions, contract(
975 ensures(output.len() == self.nodes.len()),
976 ensures(valid_topological_sort(&self.nodes, output)),
977 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
978 ensures(old(self.roots.clone()) == self.roots),
979 ensures(old(self.active.clone()) == self.active),
980 ensures(old(self.bookmarked.clone()) == self.bookmarked),
981 invariant(self.validate())
982 ))]
983 fn get_ordered_node_identifiers(&mut self, output: &mut Vec<K>) {
984 output.clear();
985
986 for root in &self.roots {
987 topological_sort(
988 &self.nodes,
989 root,
990 &mut self.scratchpad_stack,
991 output,
992 &mut self.scratchpad_set,
993 &mut self.scratchpad_map,
994 );
995 }
996
997 self.scratchpad_set.clear();
998 self.scratchpad_map.clear();
999 }
1000 #[cfg_attr(debug_assertions, contract(
1001 ensures(lacks_duplicates(output)),
1002 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1003 ensures(self.nodes.contains_key(id) || output.is_empty()),
1004 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1005 ensures(old(self.roots.clone()) == self.roots),
1006 ensures(old(self.active.clone()) == self.active),
1007 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1008 invariant(self.validate())
1009 ))]
1010 fn get_ordered_node_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
1011 output.clear();
1012
1013 if self.nodes.contains_key(id) {
1014 descendant_subgraph(
1015 &self.nodes,
1016 *id,
1017 &mut self.scratchpad_stack,
1018 &mut self.scratchpad_set,
1019 );
1020
1021 topological_sort_subgraph(
1022 &self.nodes,
1023 &|id| self.scratchpad_set.contains(id),
1024 id,
1025 &mut self.scratchpad_stack,
1026 output,
1027 &mut self.scratchpad_set_2,
1028 &mut self.scratchpad_map,
1029 );
1030
1031 self.scratchpad_set.clear();
1032 self.scratchpad_set_2.clear();
1033 self.scratchpad_map.clear();
1034 }
1035 }
1036 #[cfg_attr(debug_assertions, contract(
1037 ensures(output.len() == self.active.len()),
1038 ensures(output.iter().all(|i| self.active.contains(i))),
1039 ensures(lacks_duplicates(output)),
1040 ensures(valid_path(&self.nodes, output)),
1041 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1042 ensures(old(self.roots.clone()) == self.roots),
1043 ensures(old(self.active.clone()) == self.active),
1044 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1045 invariant(self.validate())
1046 ))]
1047 fn get_active_path(&mut self, output: &mut Vec<K>) {
1048 output.clear();
1049
1050 for root in &self.roots {
1051 topological_sort_subgraph(
1052 &self.nodes,
1053 &|id| self.active.contains(id),
1054 root,
1055 &mut self.scratchpad_stack,
1056 &mut self.scratchpad_list,
1057 &mut self.scratchpad_set,
1058 &mut self.scratchpad_map,
1059 );
1060 }
1061
1062 self.scratchpad_set.clear();
1063 self.scratchpad_map.clear();
1064
1065 longest_candidate_path_to_root(
1066 &self.nodes,
1067 &self.scratchpad_list,
1068 &|id| self.active.contains(id),
1069 &mut self.scratchpad_map,
1070 output,
1071 );
1072
1073 self.scratchpad_list.clear();
1074 self.scratchpad_map.clear();
1075 }
1076 #[cfg_attr(debug_assertions, contract(
1077 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
1078 ensures(self.nodes.contains_key(id) || output.is_empty()),
1079 ensures(lacks_duplicates(output)),
1080 ensures(valid_path(&self.nodes, output)),
1081 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1082 ensures(old(self.roots.clone()) == self.roots),
1083 ensures(old(self.active.clone()) == self.active),
1084 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1085 invariant(self.validate())
1086 ))]
1087 fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
1088 output.clear();
1089 if !self.nodes.contains_key(id) {
1090 return;
1091 }
1092
1093 ancestor_subgraph(
1094 &self.nodes,
1095 *id,
1096 &mut self.scratchpad_stack,
1097 &mut self.scratchpad_set,
1098 );
1099
1100 for root in &self.roots {
1101 topological_sort_subgraph(
1102 &self.nodes,
1103 &|id| self.active.contains(id),
1104 root,
1105 &mut self.scratchpad_stack,
1106 &mut self.scratchpad_list,
1107 &mut self.scratchpad_set_2,
1108 &mut self.scratchpad_map,
1109 );
1110 }
1111
1112 self.scratchpad_map.clear();
1113
1114 longest_candidate_path_to_root(
1115 &self.nodes,
1116 &self.scratchpad_list,
1117 &|id| self.active.contains(id) && self.scratchpad_set.contains(id),
1118 &mut self.scratchpad_map,
1119 &mut self.scratchpad_list_2,
1120 );
1121
1122 self.scratchpad_list.clear();
1123 self.scratchpad_set.clear();
1124 self.scratchpad_set_2.clear();
1125 self.scratchpad_map.clear();
1126 self.scratchpad_map_2.clear();
1127
1128 if let Some(target) = self.scratchpad_list_2.first().copied() {
1129 shortest_path_to_ancestor(
1130 &self.nodes,
1131 id,
1132 &|node| node.id == target,
1133 &mut self.scratchpad_queue,
1134 &mut self.scratchpad_map_2,
1135 &mut self.scratchpad_set_2,
1136 output,
1137 );
1138
1139 output.reverse();
1140 output.pop();
1141 output.append(&mut self.scratchpad_list_2);
1142 } else {
1143 shortest_path_to_ancestor(
1144 &self.nodes,
1145 id,
1146 &|node| node.from.is_empty(),
1147 &mut self.scratchpad_queue,
1148 &mut self.scratchpad_map_2,
1149 &mut self.scratchpad_set_2,
1150 output,
1151 );
1152
1153 output.reverse();
1154 }
1155
1156 self.scratchpad_set_2.clear();
1157 self.scratchpad_map_2.clear();
1158 }
1159 #[cfg_attr(debug_assertions, contract(
1160 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1161 ensures(!ret || old(!self.nodes.contains_key(&node.id))),
1162 ensures(!ret || self.nodes.contains_key(&old(node.id))),
1163 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))))),
1164 ensures(!ret || old(node.bookmarked) == self.bookmarked.contains(&old(node.id))),
1165 ensures(!ret || old(!node.from.is_empty()) || self.roots.contains(&old(node.id))),
1166 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1167 ensures(ret || old(self.roots.clone()) == self.roots),
1168 ensures(ret || old(self.active.clone()) == self.active),
1169 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1170 invariant(self.validate())
1171 ))]
1172 fn add_node(&mut self, mut node: IndependentNode<K, T, S>) -> bool {
1173 if self.nodes.contains_key(&node.id)
1174 || !node.validate()
1175 || !node.from.iter().all(|id| self.nodes.contains_key(id))
1176 || !node.to.iter().all(|id| self.nodes.contains_key(id))
1177 {
1178 return false;
1179 }
1180
1181 if !node.to.is_empty() && !node.from.is_empty() {
1182 for parent in node.from.iter().copied() {
1183 ancestor_subgraph(
1184 &self.nodes,
1185 parent,
1186 &mut self.scratchpad_stack,
1187 &mut self.scratchpad_set,
1188 );
1189 }
1190
1191 if node
1192 .to
1193 .iter()
1194 .any(|child| self.scratchpad_set.contains(child))
1195 {
1196 self.scratchpad_set.clear();
1197 return false;
1198 }
1199
1200 self.scratchpad_set.clear();
1201 }
1202
1203 let root_index = if node.from.is_empty() {
1204 node.to
1205 .iter()
1206 .filter_map(|child| self.roots.get_index_of(child))
1207 .min()
1208 } else {
1209 None
1210 };
1211
1212 for child in &node.to {
1213 let child = &self.nodes[child];
1214 if child.from.is_empty() {
1215 if child.active {
1216 node.active = true;
1217 }
1218 self.roots.shift_remove(&child.id);
1219 }
1220 }
1221
1222 let extends_active = node.active
1223 && node.to.is_empty()
1224 && node.from.iter().map(|id| &self.nodes[id]).any(|parent| {
1225 parent.active && parent.to.iter().all(|child| !self.active.contains(child))
1226 });
1227
1228 if node.from.is_empty() {
1229 if let Some(index) = root_index {
1230 self.roots.shift_insert(index, node.id);
1231 } else {
1232 self.roots.insert(node.id);
1233 }
1234 } else {
1235 for parent in &node.from {
1236 let parent = self.nodes.get_mut(parent).unwrap();
1237 parent.to.insert(node.id);
1238 }
1239 }
1240
1241 for child in &node.to {
1242 let child = self.nodes.get_mut(child).unwrap();
1243 child.from.insert(node.id);
1244 }
1245
1246 if node.bookmarked {
1247 self.bookmarked.insert(node.id);
1248 }
1249
1250 let id = node.id;
1251 let active = node.active;
1252
1253 if !extends_active {
1254 node.active = false;
1255 }
1256
1257 self.nodes.insert(node.id, node);
1258
1259 if extends_active {
1260 self.active.insert(id);
1261 } else if active {
1262 self.update_node_activity_in_place(&id, true);
1263 }
1264
1265 true
1266 }
1267 #[cfg_attr(debug_assertions, contract(
1268 ensures(!ret || value == self.contains_active(id)),
1269 ensures(ret || old(self.active.clone()) == self.active),
1270 ensures(ret == self.nodes.contains_key(id)),
1271 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1272 ensures(old(self.roots.clone()) == self.roots),
1273 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1274 invariant(self.validate())
1275 ))]
1276 fn set_node_active_status(&mut self, id: &K, value: bool) -> bool {
1277 self.update_node_activity_in_place(id, value)
1278 }
1279 #[cfg_attr(debug_assertions, contract(
1280 ensures(!self.nodes.contains_key(id)),
1281 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1282 ensures(ret.as_ref().is_none_or(|node| &node.id == id)),
1283 ensures(ret.is_none() || old(self.nodes.len()) > self.nodes.len()),
1284 ensures(ret.is_none() || old(self.active.len()) >= self.active.len()),
1285 ensures(ret.is_none() || old(self.bookmarked.len()) >= self.bookmarked.len()),
1286 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1287 ensures(ret.is_some() || old(self.roots.clone()) == self.roots),
1288 ensures(ret.is_some() || old(self.active.clone()) == self.active),
1289 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1290 invariant(self.validate())
1291 ))]
1292 fn remove_node(&mut self, id: &K) -> Option<IndependentNode<K, T, S>> {
1293 let mut removed_node = None;
1294 let mut removed_active = false;
1295
1296 self.scratchpad_stack.push(*id);
1297
1298 while let Some(id) = self.scratchpad_stack.pop() {
1299 if let Some(node) = self.nodes.remove(&id) {
1300 if node.from.is_empty() {
1301 self.roots.shift_remove(&id);
1302 }
1303 if node.bookmarked {
1304 self.bookmarked.shift_remove(&id);
1305 }
1306 if node.active {
1307 self.active.remove(&id);
1308 removed_active = true;
1309 }
1310
1311 for parent in &node.from {
1312 if let Some(parent) = self.nodes.get_mut(parent) {
1313 parent.to.shift_remove(&node.id);
1314 }
1315 }
1316 for child in node.to.iter().rev() {
1317 if let Some(child) = self.nodes.get_mut(child) {
1318 child.from.shift_remove(&node.id);
1319
1320 if child.from.is_empty() {
1321 self.scratchpad_stack.push(child.id);
1322 }
1323 }
1324 }
1325
1326 if removed_node.is_none() {
1327 removed_node = Some(node);
1328 }
1329 }
1330 }
1331
1332 if removed_node.is_some() {
1333 if removed_active {
1334 self.fix_orphaned_activations();
1336 }
1337 removed_node
1338 } else {
1339 None
1340 }
1341 }
1342 #[cfg_attr(debug_assertions, contract(
1343 ensures(!self.nodes.contains_key(id)),
1344 ensures(ret == old(self.nodes.contains_key(id))),
1345 ensures(!ret || old(self.nodes.len()) > self.nodes.len()),
1346 ensures(!ret || old(self.active.len()) >= self.active.len()),
1347 ensures(!ret || old(self.bookmarked.len()) >= self.bookmarked.len()),
1348 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1349 ensures(ret || old(self.roots.clone()) == self.roots),
1350 ensures(ret || old(self.active.clone()) == self.active),
1351 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1352 invariant(self.validate())
1353 ))]
1354 fn remove_node_tracked(
1355 &mut self,
1356 id: &K,
1357 mut on_removal: impl FnMut(IndependentNode<K, T, S>),
1358 ) -> bool {
1359 let had_node = self.nodes.contains_key(id);
1360 let mut removed_active = false;
1361
1362 self.scratchpad_stack.push(*id);
1363
1364 while let Some(id) = self.scratchpad_stack.pop() {
1365 if let Some(node) = self.nodes.remove(&id) {
1366 if node.from.is_empty() {
1367 self.roots.shift_remove(&id);
1368 }
1369 if node.bookmarked {
1370 self.bookmarked.shift_remove(&id);
1371 }
1372 if node.active {
1373 self.active.remove(&id);
1374 removed_active = true;
1375 }
1376
1377 for parent in &node.from {
1378 if let Some(parent) = self.nodes.get_mut(parent) {
1379 parent.to.shift_remove(&node.id);
1380 }
1381 }
1382 for child in node.to.iter().rev() {
1383 if let Some(child) = self.nodes.get_mut(child) {
1384 child.from.shift_remove(&node.id);
1385
1386 if child.from.is_empty() {
1387 self.scratchpad_stack.push(child.id);
1388 }
1389 }
1390 }
1391
1392 on_removal(node);
1393 }
1394 }
1395
1396 if had_node {
1397 if removed_active {
1398 self.fix_orphaned_activations();
1399 }
1400 true
1401 } else {
1402 false
1403 }
1404 }
1405 #[cfg_attr(debug_assertions, contract(
1406 ensures(self.nodes.is_empty()),
1407 ensures(self.validate())
1408 ))]
1409 fn remove_all_nodes(&mut self) {
1410 self.nodes.clear();
1411 self.roots.clear();
1412 self.active.clear();
1413 self.bookmarked.clear();
1414 }
1415}
1416
1417impl<K, T, M, S> IndependentWeave<K, T, M, S>
1418where
1419 K: Hash + Copy + Eq + Ord,
1420 T: IndependentContents,
1421 S: BuildHasher + Default + Clone,
1422{
1423 pub fn validate(&self) -> bool {
1425 let mut scratchpad = Vec::with_capacity(self.nodes.len());
1426 let mut scratchpad_map = HashMap::with_capacity_and_hasher(self.nodes.len(), S::default());
1427
1428 self.validate_scratchpads()
1429 && self
1430 .roots
1431 .iter()
1432 .all(move |value| self.nodes.contains_key(value))
1433 && self
1434 .active
1435 .iter()
1436 .all(move |value| self.nodes.contains_key(value))
1437 && self
1438 .bookmarked
1439 .iter()
1440 .all(move |value| self.nodes.contains_key(value))
1441 && self.nodes.iter().all(|(key, value)| {
1442 value.validate()
1443 && value.id == *key
1444 && value
1445 .from
1446 .iter()
1447 .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
1448 && value
1449 .to
1450 .iter()
1451 .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
1452 && value.from.is_empty() == self.roots.contains(key)
1453 && value.active == self.active.contains(key)
1454 && value.bookmarked == self.bookmarked.contains(key)
1455 })
1456 && !detect_cycles(
1457 &self.nodes,
1458 self.roots.iter().copied(),
1459 &mut scratchpad,
1460 &mut scratchpad_map,
1461 )
1462 && active_path_is_valid(&self.nodes, self.roots.iter(), &self.active)
1463 }
1464 fn validate_scratchpads(&self) -> bool {
1465 self.scratchpad_list.is_empty()
1466 && self.scratchpad_list_2.is_empty()
1467 && self.scratchpad_set.is_empty()
1468 && self.scratchpad_set_2.is_empty()
1469 && self.scratchpad_map.is_empty()
1470 && self.scratchpad_map_2.is_empty()
1471 && self.scratchpad_map_3.is_empty()
1472 && self.scratchpad_stack.is_empty()
1473 && self.scratchpad_queue.is_empty()
1474 }
1475}
1476
1477impl<K, T, M, S> MetadataWeave<K, IndependentNode<K, T, S>, T, M> for IndependentWeave<K, T, M, S>
1478where
1479 K: Hash + Copy + Eq + Ord,
1480 T: IndependentContents,
1481 S: BuildHasher + Default + Clone,
1482{
1483 #[inline]
1484 fn metadata(&self) -> &M {
1485 &self.metadata
1486 }
1487 #[cfg_attr(debug_assertions, contract(
1488 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1489 ensures(old(self.roots.clone()) == self.roots),
1490 ensures(old(self.active.clone()) == self.active),
1491 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1492 invariant(self.validate())
1493 ))]
1494 #[inline]
1495 fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
1496 callback(&mut self.metadata)
1497 }
1498}
1499
1500impl<K, T, M, S> BookmarkableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1501where
1502 K: Hash + Copy + Eq + Ord,
1503 T: IndependentContents,
1504 S: BuildHasher + Default + Clone,
1505{
1506 type Bookmarks = IndexSet<K, S>;
1507
1508 #[inline]
1509 fn bookmarks(&self) -> &Self::Bookmarks {
1510 &self.bookmarked
1511 }
1512 #[inline]
1513 fn contains_bookmark(&self, id: &K) -> bool {
1514 self.bookmarked.contains(id)
1515 }
1516 #[cfg_attr(debug_assertions, contract(
1517 ensures(!ret || value == self.bookmarked.contains(id)),
1518 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
1519 ensures(ret == self.nodes.contains_key(id)),
1520 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1521 ensures(old(self.roots.clone()) == self.roots),
1522 ensures(old(self.active.clone()) == self.active),
1523 invariant(self.validate())
1524 ))]
1525 fn set_node_bookmarked_status(&mut self, id: &K, value: bool) -> bool {
1526 match self.nodes.get_mut(id) {
1527 Some(node) => {
1528 node.bookmarked = value;
1529 if value {
1530 self.bookmarked.insert(node.id);
1531 } else {
1532 self.bookmarked.shift_remove(id);
1533 }
1534
1535 true
1536 }
1537 None => false,
1538 }
1539 }
1540}
1541
1542impl<K, T, M, S> SortableWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1543where
1544 K: Hash + Copy + Eq + Ord,
1545 T: IndependentContents,
1546 S: BuildHasher + Default + Clone,
1547{
1548 #[cfg_attr(debug_assertions, contract(
1549 ensures(ret == self.nodes.contains_key(id)),
1550 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1551 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1552 ensures(old(self.roots.clone()) == self.roots),
1553 ensures(old(self.active.clone()) == self.active),
1554 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1555 invariant(self.validate())
1556 ))]
1557 fn sort_node_children_by(
1558 &mut self,
1559 id: &K,
1560 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1561 ) -> bool {
1562 if let Some(mut node) = self.nodes.remove(id) {
1563 node.to.sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1564 self.nodes.insert(node.id, node);
1565
1566 true
1567 } else {
1568 false
1569 }
1570 }
1571 #[cfg_attr(debug_assertions, contract(
1572 ensures(ret == self.nodes.contains_key(id)),
1573 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
1574 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1575 ensures(old(self.roots.clone()) == self.roots),
1576 ensures(old(self.active.clone()) == self.active),
1577 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1578 invariant(self.validate())
1579 ))]
1580 fn sort_node_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
1581 if let Some(node) = self.nodes.get_mut(id) {
1582 node.to.sort_by(cmp);
1583
1584 true
1585 } else {
1586 false
1587 }
1588 }
1589 #[cfg_attr(debug_assertions, contract(
1590 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1591 ensures(old(self.roots.clone()) == self.roots),
1592 ensures(old(self.active.clone()) == self.active),
1593 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1594 invariant(self.validate())
1595 ))]
1596 fn sort_roots_by(
1597 &mut self,
1598 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1599 ) {
1600 self.roots
1601 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1602 }
1603 #[cfg_attr(debug_assertions, contract(
1604 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1605 ensures(old(self.roots.clone()) == self.roots),
1606 ensures(old(self.active.clone()) == self.active),
1607 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1608 invariant(self.validate())
1609 ))]
1610 fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1611 self.roots.sort_by(cmp);
1612 }
1613}
1614
1615impl<K, T, M, S> SortableBookmarkableWeave<K, IndependentNode<K, T, S>, T>
1616 for IndependentWeave<K, T, M, S>
1617where
1618 K: Hash + Copy + Eq + Ord,
1619 T: IndependentContents,
1620 S: BuildHasher + Default + Clone,
1621{
1622 #[cfg_attr(debug_assertions, contract(
1623 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1624 ensures(old(self.roots.clone()) == self.roots),
1625 ensures(old(self.active.clone()) == self.active),
1626 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1627 invariant(self.validate())
1628 ))]
1629 fn sort_bookmarks_by(
1630 &mut self,
1631 mut cmp: impl FnMut(&IndependentNode<K, T, S>, &IndependentNode<K, T, S>) -> Ordering,
1632 ) {
1633 self.bookmarked
1634 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
1635 }
1636 #[cfg_attr(debug_assertions, contract(
1637 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1638 ensures(old(self.roots.clone()) == self.roots),
1639 ensures(old(self.active.clone()) == self.active),
1640 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1641 invariant(self.validate())
1642 ))]
1643 fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
1644 self.bookmarked.sort_by(cmp);
1645 }
1646}
1647
1648impl<K, T, M, S> ActivePathWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1649where
1650 K: Hash + Copy + Eq + Ord,
1651 T: IndependentContents,
1652 S: BuildHasher + Default + Clone,
1653{
1654 type Active = HashSet<K, S>;
1655
1656 #[inline]
1657 fn active(&self) -> &Self::Active {
1658 &self.active
1659 }
1660 #[cfg_attr(debug_assertions, contract(
1661 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1662 ensures(old(self.roots.clone()) == self.roots),
1663 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1664 invariant(self.validate())
1665 ))]
1666 fn set_active_path(&mut self, active: impl Iterator<Item = K>) {
1667 self.active.iter().for_each(|active| {
1668 self.nodes.get_mut(active).unwrap().active = false;
1669 });
1670 self.active.clear();
1671 self.active
1672 .extend(active.filter(|id| self.nodes.contains_key(id)));
1673 self.active.iter().for_each(|active| {
1674 self.nodes.get_mut(active).unwrap().active = true;
1675 });
1676 self.fix_orphaned_activations();
1677 }
1678}
1679
1680impl<K, T, M, S> DiscreteWeave<K, IndependentNode<K, T, S>, T> for IndependentWeave<K, T, M, S>
1681where
1682 K: Hash + Copy + Eq + Ord,
1683 T: IndependentContents + DiscreteContents,
1684 S: BuildHasher + Default + Clone,
1685{
1686 #[cfg_attr(debug_assertions, contract(
1687 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
1688 ensures(!ret || self.nodes.contains_key(id)),
1689 ensures(!ret || self.nodes.contains_key(&new_id)),
1690 ensures(!ret || old(!self.nodes.contains_key(&new_id))),
1691 ensures(!ret || self.nodes[id].to.contains(&new_id) && self.nodes[id].to.len() == 1),
1692 ensures(!ret || self.nodes[&new_id].from.contains(id) && self.nodes[&new_id].from.len() == 1),
1693 ensures(!ret || old(self.nodes.get(id).map(|n| n.to.clone())).unwrap() == self.nodes[&new_id].to),
1694 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1695 ensures(ret || old(self.active.clone()) == self.active),
1696 ensures(old(self.roots.clone()) == self.roots),
1697 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1698 invariant(self.validate())
1699 ))]
1700 fn split_node(&mut self, id: &K, at: usize, new_id: K) -> bool {
1701 if self.nodes.contains_key(&new_id) || *id == new_id {
1702 return false;
1703 }
1704
1705 if let Some(mut node) = self.nodes.remove(id) {
1706 match node.contents.split(at) {
1707 DiscreteContentResult::Two(left, right) => {
1708 let left_node = IndependentNode {
1709 id: node.id,
1710 from: node.from,
1711 to: IndexSet::from_iter([new_id]),
1712 active: node.active,
1713 bookmarked: node.bookmarked,
1714 contents: left,
1715 };
1716
1717 node.from = IndexSet::from_iter([node.id]);
1718 node.id = new_id;
1719 node.contents = right;
1720 node.active = false;
1721 node.bookmarked = false;
1722
1723 for child in &node.to {
1724 let child = self.nodes.get_mut(child).unwrap();
1725
1726 if let Some(index) = child.from.get_index_of(&left_node.id) {
1727 assert!(
1728 child.from.replace_index(index, node.id).is_ok(),
1729 "Should be unreachable"
1730 );
1731 } else {
1732 child.from.insert(node.id);
1733 }
1734 if child.active && left_node.active {
1735 node.active = true;
1736 self.active.insert(node.id);
1737 }
1738 }
1739
1740 self.nodes.insert(left_node.id, left_node);
1741 self.nodes.insert(node.id, node);
1742
1743 true
1744 }
1745 DiscreteContentResult::One(content) => {
1746 node.contents = content;
1747 self.nodes.insert(node.id, node);
1748 false
1749 }
1750 }
1751 } else {
1752 false
1753 }
1754 }
1755 #[cfg_attr(debug_assertions, contract(
1756 ensures(ret.is_none() || old(self.nodes.len()) - 1 == self.nodes.len()),
1757 ensures(ret.is_none() || !self.nodes.contains_key(id)),
1758 ensures(ret.is_none() || old(self.nodes.contains_key(id))),
1759 ensures(ret.is_none() || !old(self.contains_active(id)) || old(self.contains_active(id)) && self.contains_active(&ret.unwrap())),
1760 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),
1761 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),
1762 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.to.clone())).unwrap() == self.nodes[&ret.unwrap()].to),
1763 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.from.len() == 1)).unwrap()),
1764 ensures(ret.is_none() || ret.unwrap() == old(self.nodes.get(id).and_then(|node| node.from.first().copied())).unwrap()),
1765 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1766 ensures(ret.is_some() || old(self.active.clone()) == self.active),
1767 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1768 ensures(old(self.roots.clone()) == self.roots),
1769 invariant(self.validate())
1770 ))]
1771 fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1772 if let Some(mut node) = self.nodes.remove(id) {
1773 if node.from.len() != 1 {
1774 self.nodes.insert(node.id, node);
1775 return None;
1776 }
1777
1778 if let Some(mut parent) = node.from.first().and_then(|id| self.nodes.remove(id)) {
1779 if parent.to.len() > 1 {
1780 self.nodes.insert(parent.id, parent);
1781 self.nodes.insert(node.id, node);
1782 return None;
1783 }
1784
1785 match parent.contents.merge(node.contents) {
1786 DiscreteContentResult::Two(left, right) => {
1787 parent.contents = left;
1788 node.contents = right;
1789 self.nodes.insert(parent.id, parent);
1790 self.nodes.insert(node.id, node);
1791 None
1792 }
1793 DiscreteContentResult::One(content) => {
1794 parent.contents = content;
1795 parent.to = node.to;
1796
1797 for child in &parent.to {
1798 let child = self.nodes.get_mut(child).unwrap();
1799
1800 if let Some(index) = child.from.get_index_of(&node.id) {
1801 assert!(
1802 child.from.replace_index(index, parent.id).is_ok(),
1803 "Should be unreachable"
1804 );
1805 } else {
1806 child.from.insert(parent.id);
1807 }
1808 }
1809
1810 let parent_id = parent.id;
1811
1812 if node.bookmarked && !parent.bookmarked {
1813 parent.bookmarked = true;
1814 assert!(
1815 self.bookmarked
1816 .replace_index(
1817 self.bookmarked.get_index_of(&node.id).unwrap(),
1818 parent.id,
1819 )
1820 .is_ok(),
1821 "Should be unreachable"
1822 );
1823 } else {
1824 self.bookmarked.shift_remove(&node.id);
1825 }
1826
1827 self.nodes.insert(parent.id, parent);
1828 self.active.remove(&node.id);
1829
1830 Some(parent_id)
1831 }
1832 }
1833 } else {
1834 self.nodes.insert(node.id, node);
1835 None
1836 }
1837 } else {
1838 None
1839 }
1840 }
1841}
1842
1843impl<K, T, M, S> SemiIndependentWeave<K, IndependentNode<K, T, S>, T>
1844 for IndependentWeave<K, T, M, S>
1845where
1846 K: Hash + Copy + Eq + Ord,
1847 T: IndependentContents,
1848 S: BuildHasher + Default + Clone,
1849{
1850 #[cfg_attr(debug_assertions, contract(
1851 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1852 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1853 ensures(old(self.roots.clone()) == self.roots),
1854 ensures(old(self.active.clone()) == self.active),
1855 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1856 invariant(self.validate())
1857 ))]
1858 #[inline]
1859 fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1860 self.nodes
1861 .get_mut(id)
1862 .map(|node| callback(&mut node.contents))
1863 }
1864}
1865
1866impl<K, T, M, S> crate::IndependentWeave<K, IndependentNode<K, T, S>, T>
1867 for IndependentWeave<K, T, M, S>
1868where
1869 K: Hash + Copy + Eq + Ord,
1870 T: IndependentContents,
1871 S: BuildHasher + Default + Clone,
1872{
1873 #[cfg_attr(debug_assertions, contract(
1874 ensures(!ret || self.nodes[id].from.iter().copied().collect::<HashSet<_>>() == new_parents.iter().copied().collect::<HashSet<_>>()),
1875 ensures(ret || old(self.nodes.get(id).map(|node| node.from.clone())).as_ref() == self.nodes.get(id).map(|node| &node.from)),
1876 ensures(ret || old(self.roots.clone()) == self.roots),
1877 ensures(ret || old(self.active.clone()) == self.active),
1878 ensures(old(self.nodes.get(id).map(|node| node.to.clone())).as_ref() == self.nodes.get(id).map(|node| &node.to)),
1879 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1880 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1881 ensures(old(self.active.contains(id)) == self.active.contains(id)),
1882 invariant(self.validate())
1883 ))]
1884 fn move_node(&mut self, id: &K, new_parents: &[K]) -> bool {
1885 if new_parents
1886 .iter()
1887 .any(|new_parent| !self.nodes.contains_key(new_parent))
1888 {
1889 return false;
1890 }
1891
1892 if let Some(node) = self.nodes.get(id)
1893 && !node.to.is_empty()
1894 && !new_parents.is_empty()
1895 {
1896 for child in node.to.iter().copied() {
1897 descendant_subgraph(
1898 &self.nodes,
1899 child,
1900 &mut self.scratchpad_stack,
1901 &mut self.scratchpad_set,
1902 );
1903 }
1904
1905 if new_parents
1906 .iter()
1907 .any(|new_parent| self.scratchpad_set.contains(new_parent))
1908 {
1909 self.scratchpad_set.clear();
1910 return false;
1911 }
1912
1913 self.scratchpad_set.clear();
1914 }
1915
1916 let new_parents: IndexSet<K, S> = new_parents.iter().copied().collect();
1917
1918 if new_parents.contains(id) {
1919 return false;
1920 }
1921
1922 if let Some(node) = self.nodes.get_mut(id) {
1923 for child in &node.to {
1924 if new_parents.contains(child) {
1925 return false;
1926 }
1927 }
1928
1929 let old_parents = mem::take(&mut node.from);
1930
1931 for old_parent in &old_parents {
1932 if !new_parents.contains(old_parent)
1933 && let Some(old_parent) = self.nodes.get_mut(old_parent)
1934 {
1935 old_parent.to.shift_remove(id);
1936 }
1937 }
1938
1939 for new_parent in &new_parents {
1940 if !old_parents.contains(new_parent)
1941 && let Some(new_parent) = self.nodes.get_mut(new_parent)
1942 {
1943 new_parent.to.insert(*id);
1944 }
1945 }
1946 } else {
1947 return false;
1948 }
1949
1950 let node = self.nodes.get_mut(id).unwrap();
1951 node.from = new_parents;
1952
1953 if node.from.is_empty() {
1954 self.roots.insert(node.id);
1955 } else {
1956 self.roots.shift_remove(&node.id);
1957 }
1958
1959 if node.active {
1960 node.active = false;
1961 self.update_node_activity_in_place(id, true);
1962 }
1963
1964 true
1965 }
1966}
1967
1968#[cfg(feature = "rkyv")]
1969impl<K, T, S> ArchivedIndependentNode<K, T, S>
1970where
1971 K: Archive + Hash + Copy + Eq + Ord,
1972 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1973 T: Archive + IndependentContents,
1974 S: BuildHasher + Default + Clone,
1975{
1976 #[inline]
1977 fn validate(&self) -> bool {
1978 (if self.from.len() <= self.to.len() {
1979 self.from.iter().all(|v| !self.to.contains(v))
1980 } else {
1981 self.to.iter().all(|v| !self.from.contains(v))
1982 }) && !self.from.contains(&self.id)
1983 && !self.to.contains(&self.id)
1984 }
1985}
1986
1987#[cfg(feature = "rkyv")]
1988impl<K, T, S> Node<K::Archived, T::Archived> for ArchivedIndependentNode<K, T, S>
1989where
1990 K: Archive + Hash + Copy + Eq + Ord,
1991 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1992 T: Archive + IndependentContents,
1993 S: BuildHasher + Default + Clone,
1994{
1995 type From = ArchivedIndexSet<K::Archived>;
1996 type To = ArchivedIndexSet<K::Archived>;
1997
1998 #[inline]
1999 fn id(&self) -> K::Archived {
2000 self.id
2001 }
2002 #[inline]
2003 fn from(&self) -> &Self::From {
2004 &self.from
2005 }
2006 #[inline]
2007 fn to(&self) -> &Self::To {
2008 &self.to
2009 }
2010 #[inline]
2011 fn is_active(&self) -> bool {
2012 self.active
2013 }
2014 #[inline]
2015 fn contents(&self) -> &T::Archived {
2016 &self.contents
2017 }
2018}
2019
2020#[cfg(feature = "rkyv")]
2021impl<K, T, M, S> ArchivedIndependentWeave<K, T, M, S>
2022where
2023 K: Archive + Hash + Copy + Eq + Ord,
2024 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2025 T: Archive + IndependentContents,
2026 M: Archive,
2027 S: BuildHasher + Default + Clone,
2028{
2029 fn validate(&self) -> bool {
2030 let mut scratchpad = Vec::with_capacity(self.nodes.len());
2031 let mut scratchpad_map = HashMap::with_capacity(self.nodes.len());
2032
2033 self.roots
2034 .iter()
2035 .all(move |value| self.nodes.contains_key(value))
2036 && self
2037 .active
2038 .iter()
2039 .all(move |value| self.nodes.contains_key(value))
2040 && self
2041 .bookmarked
2042 .iter()
2043 .all(move |value| self.nodes.contains_key(value))
2044 && self.nodes.iter().all(|(key, value)| {
2045 value.validate()
2046 && value.id == *key
2047 && value
2048 .from
2049 .iter()
2050 .all(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
2051 && value
2052 .to
2053 .iter()
2054 .all(|v| self.nodes.get(v).is_some_and(|p| p.from.contains(key)))
2055 && value.from.is_empty() == self.roots.contains(key)
2056 && value.active == self.active.contains(key)
2057 && value.bookmarked == self.bookmarked.contains(key)
2058 })
2059 && !archived_detect_cycles(
2060 &self.nodes,
2061 self.roots.iter().copied(),
2062 &mut scratchpad,
2063 &mut scratchpad_map,
2064 )
2065 && archived_active_path_is_valid(&self.nodes, self.roots.iter(), &self.active)
2066 }
2067}
2068
2069#[cfg(feature = "rkyv")]
2070unsafe impl<K, T, M, S, C> Verify<C> for ArchivedIndependentWeave<K, T, M, S>
2073where
2074 K: Archive + Hash + Copy + Eq + Ord,
2075 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2076 T: Archive + IndependentContents,
2077 M: Archive,
2078 S: BuildHasher + Default + Clone,
2079 C: Fallible + ?Sized,
2080 C::Error: Source,
2081{
2082 fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
2083 if !self.validate() {
2084 fail!(ValidationError)
2085 }
2086
2087 Ok(())
2088 }
2089}
2090
2091#[cfg(feature = "rkyv")]
2092impl<K, T, M, S> ImmutableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2093 for ArchivedIndependentWeave<K, T, M, S>
2094where
2095 K: Archive + Hash + Copy + Eq + Ord,
2096 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2097 T: Archive + IndependentContents,
2098 M: Archive,
2099 S: BuildHasher + Default + Clone,
2100{
2101 type Nodes = ArchivedHashMap<K::Archived, ArchivedIndependentNode<K, T, S>>;
2102 type Roots = ArchivedIndexSet<K::Archived>;
2103
2104 #[inline]
2105 fn len(&self) -> usize {
2106 self.nodes.len()
2107 }
2108 #[inline]
2109 fn is_empty(&self) -> bool {
2110 self.nodes.is_empty()
2111 }
2112 #[inline]
2113 fn nodes(&self) -> &Self::Nodes {
2114 &self.nodes
2115 }
2116 #[inline]
2117 fn roots(&self) -> &Self::Roots {
2118 &self.roots
2119 }
2120 #[inline]
2121 fn contains(&self, id: &K::Archived) -> bool {
2122 self.nodes.contains_key(id)
2123 }
2124 #[inline]
2125 fn contains_active(&self, id: &K::Archived) -> bool {
2126 self.active.contains(id)
2127 }
2128 #[inline]
2129 fn get_node(&self, id: &K::Archived) -> Option<&ArchivedIndependentNode<K, T, S>> {
2130 self.nodes.get(id)
2131 }
2132 #[inline]
2133 fn get_node_parents(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
2134 self.nodes.get(id).map(|node| &node.from)
2135 }
2136 #[inline]
2137 fn get_node_children(&self, id: &K::Archived) -> Option<&ArchivedIndexSet<K::Archived>> {
2138 self.nodes.get(id).map(|node| &node.to)
2139 }
2140 fn get_ordered_node_identifiers(&self, output: &mut Vec<K::Archived>) {
2141 output.clear();
2142 let mut scratchpad = Vec::with_capacity(self.len());
2143 let mut scratchpad_2 = Vec::with_capacity(self.len());
2144 let mut identifier_set = HashSet::with_capacity(self.len());
2145 let mut scratchpad_map = HashMap::with_capacity(self.len());
2146
2147 for root in self.roots.iter() {
2148 archived_topological_sort(
2149 &self.nodes,
2150 root,
2151 &mut scratchpad,
2152 &mut scratchpad_2,
2153 output,
2154 &mut identifier_set,
2155 &mut scratchpad_map,
2156 );
2157 }
2158 }
2159 fn get_ordered_node_identifiers_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2160 output.clear();
2161
2162 if self.nodes.contains_key(id) {
2163 let mut scratchpad = Vec::with_capacity(self.len());
2164 let mut scratchpad_2 = Vec::with_capacity(self.len());
2165 let mut scratchpad_set = HashSet::with_capacity(self.len());
2166 let mut scratchpad_set_2 = HashSet::with_capacity(self.len());
2167 let mut scratchpad_map = HashMap::with_capacity(self.len());
2168
2169 archived_descendant_subgraph(&self.nodes, *id, &mut scratchpad, &mut scratchpad_set);
2170
2171 archived_topological_sort_subgraph(
2172 &self.nodes,
2173 &|id| scratchpad_set.contains(id),
2174 id,
2175 &mut scratchpad,
2176 &mut scratchpad_2,
2177 output,
2178 &mut scratchpad_set_2,
2179 &mut scratchpad_map,
2180 );
2181 }
2182 }
2183 fn get_active_path(&self, output: &mut Vec<K::Archived>) {
2184 output.clear();
2185 let mut scratchpad_list = Vec::with_capacity(self.len());
2186 let mut scratchpad_list_2 = Vec::with_capacity(self.len());
2187 let mut scratchpad_list_3 = Vec::with_capacity(self.len());
2188 let mut scratchpad_set = HashSet::with_capacity(self.len());
2189 let mut scratchpad_map = HashMap::with_capacity(self.len());
2190
2191 for root in self.roots.iter() {
2192 archived_topological_sort_subgraph(
2193 &self.nodes,
2194 &|id| self.active.contains(id),
2195 root,
2196 &mut scratchpad_list,
2197 &mut scratchpad_list_2,
2198 &mut scratchpad_list_3,
2199 &mut scratchpad_set,
2200 &mut scratchpad_map,
2201 );
2202 }
2203
2204 scratchpad_map.clear();
2205
2206 archived_longest_candidate_path_to_root(
2207 &self.nodes,
2208 &scratchpad_list_3,
2209 &|id| self.active.contains(id),
2210 &mut scratchpad_map,
2211 output,
2212 );
2213 }
2214 fn get_path_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
2215 output.clear();
2216
2217 if self.nodes.contains_key(id) {
2218 let mut scratchpad_list = Vec::with_capacity(self.len());
2219 let mut scratchpad_list_2 = Vec::with_capacity(self.len());
2220 let mut scratchpad_stack = Vec::with_capacity(self.len());
2221 let mut scratchpad_queue = VecDeque::with_capacity(self.len());
2222 let mut scratchpad_set = HashSet::with_capacity(self.len());
2223 let mut scratchpad_set_2 = HashSet::with_capacity(self.len());
2224 let mut scratchpad_map = HashMap::with_capacity(self.len());
2225 let mut scratchpad_map_2 = HashMap::with_capacity(self.len());
2226
2227 archived_ancestor_subgraph(
2228 &self.nodes,
2229 *id,
2230 &mut scratchpad_stack,
2231 &mut scratchpad_set,
2232 );
2233
2234 for root in self.roots.iter() {
2235 archived_topological_sort_subgraph(
2236 &self.nodes,
2237 &|id| self.active.contains(id),
2238 root,
2239 &mut scratchpad_stack,
2240 &mut scratchpad_list_2,
2241 &mut scratchpad_list,
2242 &mut scratchpad_set_2,
2243 &mut scratchpad_map,
2244 );
2245 }
2246
2247 scratchpad_map.clear();
2248
2249 archived_longest_candidate_path_to_root(
2250 &self.nodes,
2251 &scratchpad_list,
2252 &|id| self.active.contains(id) && scratchpad_set.contains(id),
2253 &mut scratchpad_map,
2254 &mut scratchpad_list_2,
2255 );
2256
2257 scratchpad_set_2.clear();
2258
2259 if let Some(target) = scratchpad_list_2.first().copied() {
2260 archived_shortest_path_to_ancestor(
2261 &self.nodes,
2262 id,
2263 &|node| node.id == target,
2264 &mut scratchpad_queue,
2265 &mut scratchpad_map_2,
2266 &mut scratchpad_set_2,
2267 output,
2268 );
2269
2270 output.reverse();
2271 output.pop();
2272 output.append(&mut scratchpad_list_2);
2273 } else {
2274 archived_shortest_path_to_ancestor(
2275 &self.nodes,
2276 id,
2277 &|node| node.from.is_empty(),
2278 &mut scratchpad_queue,
2279 &mut scratchpad_map_2,
2280 &mut scratchpad_set_2,
2281 output,
2282 );
2283
2284 output.reverse();
2285 }
2286 }
2287 }
2288}
2289
2290#[cfg(feature = "rkyv")]
2291impl<K, T, M, S>
2292 ImmutableMetadataWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived, M::Archived>
2293 for ArchivedIndependentWeave<K, T, M, S>
2294where
2295 K: Archive + Hash + Copy + Eq + Ord,
2296 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2297 T: Archive + IndependentContents,
2298 M: Archive,
2299 S: BuildHasher + Default + Clone,
2300{
2301 #[inline]
2302 fn metadata(&self) -> &M::Archived {
2303 &self.metadata
2304 }
2305}
2306
2307#[cfg(feature = "rkyv")]
2308impl<K, T, M, S>
2309 ImmutableBookmarkableWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2310 for ArchivedIndependentWeave<K, T, M, S>
2311where
2312 K: Archive + Hash + Copy + Eq + Ord,
2313 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2314 T: Archive + IndependentContents,
2315 M: Archive,
2316 S: BuildHasher + Default + Clone,
2317{
2318 type Bookmarks = ArchivedIndexSet<K::Archived>;
2319
2320 #[inline]
2321 fn bookmarks(&self) -> &Self::Bookmarks {
2322 &self.bookmarked
2323 }
2324 #[inline]
2325 fn contains_bookmark(&self, id: &K::Archived) -> bool {
2326 self.bookmarked.contains(id)
2327 }
2328}
2329
2330#[cfg(feature = "rkyv")]
2331impl<K, T, M, S>
2332 ImmutableActivePathWeave<K::Archived, ArchivedIndependentNode<K, T, S>, T::Archived>
2333 for ArchivedIndependentWeave<K, T, M, S>
2334where
2335 K: Archive + Hash + Copy + Eq + Ord,
2336 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
2337 T: Archive + IndependentContents,
2338 M: Archive,
2339 S: BuildHasher + Default + Clone,
2340{
2341 type Active = ArchivedHashSet<K::Archived>;
2342
2343 #[inline]
2344 fn active(&self) -> &Self::Active {
2345 &self.active
2346 }
2347}
2348
2349#[cfg(feature = "rkyv")]
2350fn archived_topological_sort<'a, K, N, T, S>(
2351 nodes: &'a ArchivedHashMap<K, N>,
2352 id: &'a K,
2353 scratchpad: &mut Vec<K>,
2354 scratchpad_2: &mut Vec<K>,
2355 identifiers: &mut Vec<K>,
2356 identifier_set: &mut HashSet<K, S>,
2357 identifier_map: &mut HashMap<K, usize, S>,
2358) where
2359 K: Hash + Copy + Eq + Ord + 'a,
2360 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2361 S: BuildHasher + Default + Clone,
2362{
2363 scratchpad.push(*id);
2364
2365 while let Some(id) = scratchpad.pop() {
2366 let node = &nodes[&id];
2367
2368 if identifier_set.contains(&id)
2369 || identifier_map
2370 .get(&id)
2371 .copied()
2372 .unwrap_or_else(|| node.from().len())
2373 != 0
2374 {
2375 continue;
2376 }
2377
2378 identifiers.push(id);
2379 identifier_set.insert(id);
2380
2381 for child in node.to().iter().copied() {
2382 let remaining = identifier_map
2383 .entry(child)
2384 .or_insert_with(|| nodes[&child].from().len());
2385 *remaining = remaining.strict_sub(1);
2386
2387 scratchpad_2.push(child);
2388 }
2389
2390 scratchpad_2.reverse();
2391 scratchpad.append(scratchpad_2);
2392 }
2393}
2394
2395#[cfg(feature = "rkyv")]
2396#[allow(clippy::too_many_arguments, reason = "Rkyv limitation")]
2397fn archived_topological_sort_subgraph<'a, K, N, T, S>(
2398 nodes: &'a ArchivedHashMap<K, N>,
2399 filter: &impl Fn(&K) -> bool,
2400 id: &'a K,
2401 scratchpad: &mut Vec<K>,
2402 scratchpad_2: &mut Vec<K>,
2403 identifiers: &mut Vec<K>,
2404 identifier_set: &mut HashSet<K, S>,
2405 identifier_map: &mut HashMap<K, usize, S>,
2406) where
2407 K: Hash + Copy + Eq + Ord + 'a,
2408 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2409 S: BuildHasher + Default + Clone,
2410{
2411 scratchpad.push(*id);
2412
2413 while let Some(id) = scratchpad.pop() {
2414 let node = &nodes[&id];
2415
2416 if !filter(&id)
2417 || identifier_set.contains(&id)
2418 || identifier_map
2419 .get(&id)
2420 .copied()
2421 .unwrap_or_else(|| node.from().iter().filter(|&parent| filter(parent)).count())
2422 != 0
2423 {
2424 continue;
2425 }
2426
2427 identifiers.push(id);
2428 identifier_set.insert(id);
2429
2430 for child in node.to().iter().copied() {
2431 let remaining = identifier_map.entry(child).or_insert_with(|| {
2432 nodes[&child]
2433 .from()
2434 .iter()
2435 .filter(|&parent| filter(parent))
2436 .count()
2437 });
2438 *remaining = remaining.strict_sub(1);
2439
2440 scratchpad_2.push(child);
2441 }
2442
2443 scratchpad_2.reverse();
2444 scratchpad.append(scratchpad_2);
2445 }
2446}
2447
2448#[cfg(feature = "rkyv")]
2449fn archived_detect_cycles<'a, K, N, T, S>(
2450 nodes: &'a ArchivedHashMap<K, N>,
2451 roots: impl Iterator<Item = K>,
2452 scratchpad: &mut Vec<Step<K, K>>,
2453 scratchpad_map: &mut HashMap<K, bool, S>,
2454) -> bool
2455where
2456 K: Hash + Copy + Eq + Ord + 'a,
2457 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2458 S: BuildHasher + Default + Clone,
2459{
2460 for root in roots {
2461 if scratchpad_map.contains_key(&root) {
2462 continue;
2463 }
2464
2465 scratchpad.push(Step::Enter(root));
2466
2467 while let Some(step) = scratchpad.pop() {
2468 match step {
2469 Step::Enter(id) => {
2470 scratchpad.push(Step::Exit(id));
2471
2472 match scratchpad_map.entry(id) {
2473 Entry::Occupied(entry) => {
2474 if !entry.get() {
2475 return true;
2476 }
2477 }
2478 Entry::Vacant(entry) => {
2479 entry.insert_entry(false);
2480
2481 scratchpad.extend(nodes[&id].to().iter().copied().map(Step::Enter));
2482 }
2483 }
2484 }
2485 Step::Exit(id) => {
2486 scratchpad_map.insert(id, true);
2487 }
2488 }
2489 }
2490 }
2491
2492 scratchpad_map.len() != nodes.len()
2493}
2494
2495#[cfg(feature = "rkyv")]
2496#[allow(clippy::too_many_arguments, reason = "Rkyv limitation")]
2497fn archived_shortest_path_to_ancestor<'a, K, N, T, S>(
2498 nodes: &'a ArchivedHashMap<K, N>,
2499 id: &'a K,
2500 target: &impl Fn(&'a N) -> bool,
2501 scratchpad: &mut VecDeque<K>,
2502 scratchpad_map: &mut HashMap<K, K, S>,
2503 scratchpad_set: &mut HashSet<K, S>,
2504 path: &mut Vec<K>,
2505) where
2506 K: Hash + Copy + Eq + Ord + 'a,
2507 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2508 S: BuildHasher + Default + Clone,
2509{
2510 scratchpad.push_front(*id);
2511 scratchpad_set.insert(*id);
2512
2513 while let Some(id) = scratchpad.pop_back() {
2514 let node = &nodes[&id];
2515
2516 if target(node) {
2517 scratchpad.clear();
2518
2519 path.push(id);
2520
2521 while let Some(child) = scratchpad_map.remove(path.last().unwrap()) {
2522 path.push(child);
2523 }
2524
2525 return;
2526 }
2527
2528 for parent in node.from().iter().copied() {
2529 if scratchpad_set.insert(parent) {
2530 scratchpad.push_front(parent);
2531 scratchpad_map.insert(parent, id);
2532 }
2533 }
2534 }
2535}
2536
2537#[cfg(feature = "rkyv")]
2538fn archived_longest_candidate_path_to_root<'a, K, N, T, S>(
2539 nodes: &'a ArchivedHashMap<K, N>,
2540 topological_order: &'a [K],
2541 is_candidate: &impl Fn(&K) -> bool,
2542 scratchpad_map: &mut HashMap<K, usize, S>,
2543 reversed_path: &mut Vec<K>,
2544) where
2545 K: Hash + Copy + Eq + Ord + 'a,
2546 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2547 S: BuildHasher + Default + Clone,
2548{
2549 let mut longest_distance = None;
2550
2551 for id in topological_order {
2552 if !is_candidate(id) {
2553 continue;
2554 }
2555
2556 let node = &nodes[id];
2557 let distance = if node.from().is_empty() {
2558 Some(0)
2559 } else {
2560 node.from()
2561 .iter()
2562 .filter_map(|parent| scratchpad_map.get(parent).copied())
2563 .max()
2564 .map(|l| l.strict_add(1))
2565 };
2566
2567 if let Some(distance) = distance {
2568 scratchpad_map.insert(*id, distance);
2569
2570 if longest_distance.is_none_or(|(value, _)| distance > value) {
2571 longest_distance = Some((distance, id));
2572 }
2573 }
2574 }
2575
2576 let mut current = longest_distance.map(|(_, id)| id);
2577
2578 while let Some(id) = current {
2579 reversed_path.push(*id);
2580
2581 current = nodes[id]
2582 .from()
2583 .iter()
2584 .filter(|id| scratchpad_map.contains_key(*id))
2585 .min_by_key(|id| Reverse(scratchpad_map[*id]));
2586 }
2587}
2588
2589#[cfg(feature = "rkyv")]
2590fn archived_ancestor_subgraph<'a, K, N, T, S>(
2591 nodes: &'a ArchivedHashMap<K, N>,
2592 id: K,
2593 scratchpad: &mut Vec<K>,
2594 identifiers: &mut HashSet<K, S>,
2595) where
2596 K: Hash + Copy + Eq + Ord + 'a,
2597 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2598 S: BuildHasher + Default + Clone,
2599{
2600 scratchpad.push(id);
2601
2602 while let Some(id) = scratchpad.pop() {
2603 if identifiers.insert(id) {
2604 scratchpad.extend(nodes[&id].from().iter().copied());
2605 }
2606 }
2607}
2608
2609#[cfg(feature = "rkyv")]
2610fn archived_descendant_subgraph<'a, K, N, T, S>(
2611 nodes: &'a ArchivedHashMap<K, N>,
2612 id: K,
2613 scratchpad: &mut Vec<K>,
2614 identifiers: &mut HashSet<K, S>,
2615) where
2616 K: Hash + Copy + Eq + Ord + 'a,
2617 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2618 S: BuildHasher + Default + Clone,
2619{
2620 scratchpad.push(id);
2621
2622 while let Some(id) = scratchpad.pop() {
2623 if identifiers.insert(id) {
2624 scratchpad.extend(nodes[&id].to().iter().copied());
2625 }
2626 }
2627}
2628
2629#[cfg(feature = "rkyv")]
2630fn archived_active_path_is_valid<'a, K, N, T>(
2631 nodes: &'a ArchivedHashMap<K, N>,
2632 roots: impl Iterator<Item = &'a K>,
2633 active: &'a ArchivedHashSet<K>,
2634) -> bool
2635where
2636 K: Hash + Copy + Eq + Ord + 'a,
2637 N: Node<K, T, From = ArchivedIndexSet<K>, To = ArchivedIndexSet<K>> + 'a,
2638{
2639 let mut scratchpad = Vec::with_capacity(nodes.len());
2640 let mut scratchpad_list = Vec::with_capacity(nodes.len());
2641 let mut scratchpad_list_2 = Vec::with_capacity(nodes.len());
2642 let mut scratchpad_set = HashSet::with_capacity(nodes.len());
2643 let mut scratchpad_map = HashMap::with_capacity(nodes.len());
2644
2645 for root in roots {
2646 archived_topological_sort(
2647 nodes,
2648 root,
2649 &mut scratchpad,
2650 &mut scratchpad_list_2,
2651 &mut scratchpad_list,
2652 &mut scratchpad_set,
2653 &mut scratchpad_map,
2654 );
2655 }
2656
2657 scratchpad_list_2.clear();
2658 scratchpad_set.clear();
2659 scratchpad_map.clear();
2660
2661 archived_longest_candidate_path_to_root(
2662 nodes,
2663 &scratchpad_list,
2664 &|id| active.contains(id),
2665 &mut scratchpad_map,
2666 &mut scratchpad_list_2,
2667 );
2668
2669 scratchpad_set.extend(scratchpad_list_2);
2670
2671 scratchpad_set.len() == active.len()
2672 && scratchpad_set.into_iter().all(|id| active.contains(&id))
2673}