1use alloc::{boxed::Box, vec::Vec};
4use core::{
5 cmp::Ordering,
6 hash::{BuildHasher, Hash},
7};
8
9use contracts::contract;
10use hashbrown::{HashMap, HashSet};
11use indexmap::IndexSet;
12
13#[cfg(feature = "rkyv")]
14use rkyv::{
15 Archive, Deserialize, Serialize,
16 bytecheck::Verify,
17 collections::swiss_table::{ArchivedHashMap, ArchivedIndexSet},
18 option::ArchivedOption,
19 rancor::{Fallible, Source, fail},
20 with::Skip,
21};
22
23#[cfg(feature = "serde")]
24use serde::{
25 Deserialize as SerdeDeserialize, Deserializer as SerdeDeserializer,
26 Serialize as SerdeSerialize, de::Error as _,
27};
28
29use crate::{
30 ActiveSingularWeave, BookmarkableWeave, DeduplicatableContents, DeduplicatableWeave,
31 DiscreteContentResult, DiscreteContents, DiscreteWeave, IndependentContents, MetadataWeave,
32 Node, SemiIndependentWeave, SortableBookmarkableWeave, SortableWeave, Weave,
33 contract::{lacks_duplicates, valid_path, valid_topological_sort},
34};
35
36#[cfg(feature = "rkyv")]
37use crate::{
38 ImmutableActiveSingularWeave, ImmutableBookmarkableWeave, ImmutableMetadataWeave,
39 ImmutableSortableWeave, ImmutableWeave,
40};
41
42#[cfg(any(feature = "serde", feature = "rkyv"))]
43use crate::contract::ValidationError;
44
45#[cfg(feature = "loro")]
46pub mod loro;
47
48#[cfg(feature = "legacy")]
49#[deprecated]
50pub mod legacy_dependent;
51
52#[derive(Default, Debug, Clone)]
53#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
54#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
55#[must_use]
57pub struct DependentNode<K, T, S>
58where
59 K: Hash + Copy + Eq + Ord,
60 S: BuildHasher + Default + Clone,
61{
62 pub id: K,
64 pub from: Option<K>,
66 #[cfg_attr(
68 feature = "serde",
69 serde(bound(
70 serialize = "IndexSet<K, S>: SerdeSerialize",
71 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
72 ))
73 )]
74 pub to: IndexSet<K, S>,
75 pub active: bool,
79 pub bookmarked: bool,
81 pub contents: T,
83}
84
85#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
86impl<K, T, S> PartialEq for DependentNode<K, T, S>
87where
88 K: Hash + Copy + Eq + Ord,
89 T: PartialEq,
90 S: BuildHasher + Default + Clone,
91{
92 #[inline]
93 fn eq(&self, other: &Self) -> bool {
94 self.id == other.id
95 && self.from == other.from
96 && self.to.len() == other.to.len()
97 && self.to.iter().zip(other.to.iter()).all(|(a, b)| a == b)
98 && self.active == other.active
99 && self.bookmarked == other.bookmarked
100 && self.contents == other.contents
101 }
102}
103
104#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
105impl<K, T, S> Eq for DependentNode<K, T, S>
106where
107 K: Hash + Copy + Eq + Ord,
108 T: Eq,
109 S: BuildHasher + Default + Clone,
110{
111}
112
113impl<K, T, S> DependentNode<K, T, S>
114where
115 K: Hash + Copy + Eq + Ord,
116 S: BuildHasher + Default + Clone,
117{
118 #[inline]
119 fn validate(&self) -> bool {
120 self.from.is_none_or(|from| !self.to.contains(&from))
121 && self.from != Some(self.id)
122 && !self.to.contains(&self.id)
123 }
124}
125
126impl<K, T, S> Node<K, T> for DependentNode<K, T, S>
127where
128 K: Hash + Copy + Eq + Ord,
129 S: BuildHasher + Default + Clone,
130{
131 type From = Option<K>;
132 type To = IndexSet<K, S>;
133
134 #[inline]
135 fn id(&self) -> K {
136 self.id
137 }
138 #[inline]
139 fn from(&self) -> &Self::From {
140 &self.from
141 }
142 #[inline]
143 fn to(&self) -> &Self::To {
144 &self.to
145 }
146 #[inline]
147 fn is_active(&self) -> bool {
148 self.active
149 }
150 #[inline]
151 fn contents(&self) -> &T {
152 &self.contents
153 }
154}
155
156#[derive(Default, Debug, Clone)]
158#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
159#[cfg_attr(feature = "serde", derive(SerdeSerialize))]
160#[cfg_attr(feature = "rkyv", rkyv(bytecheck(verify)))]
161#[must_use]
162pub struct DependentWeave<K, T, M, S>
163where
164 K: Hash + Copy + Eq + Ord,
165 S: BuildHasher + Default + Clone,
166{
167 #[cfg_attr(
168 feature = "serde",
169 serde(bound(
170 serialize = "HashMap<K, DependentNode<K, T, S>, S>: SerdeSerialize",
171 deserialize = "HashMap<K, DependentNode<K, T, S>, S>: SerdeDeserialize<'de>"
172 ))
173 )]
174 pub(super) nodes: HashMap<K, DependentNode<K, T, S>, S>,
175 #[cfg_attr(
176 feature = "serde",
177 serde(bound(
178 serialize = "IndexSet<K, S>: SerdeSerialize",
179 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
180 ))
181 )]
182 pub(super) roots: IndexSet<K, S>,
183 pub(super) active: Option<K>,
184 #[cfg_attr(
185 feature = "serde",
186 serde(bound(
187 serialize = "IndexSet<K, S>: SerdeSerialize",
188 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
189 ))
190 )]
191 pub(super) bookmarked: IndexSet<K, S>,
192
193 #[cfg_attr(feature = "rkyv", rkyv(with = Skip))]
194 #[cfg_attr(feature = "serde", serde(skip))]
195 pub(super) scratchpad: Vec<K>,
196
197 pub metadata: M,
199}
200
201#[cfg(feature = "serde")]
202#[derive(SerdeDeserialize)]
203#[serde(rename = "DependentWeave")]
204struct ProxyDependentWeave<K, T, M, S>
205where
206 K: Hash + Copy + Eq + Ord,
207 S: BuildHasher + Default + Clone,
208{
209 #[serde(bound(
210 serialize = "HashMap<K, DependentNode<K, T, S>, S>: SerdeSerialize",
211 deserialize = "HashMap<K, DependentNode<K, T, S>, S>: SerdeDeserialize<'de>"
212 ))]
213 nodes: HashMap<K, DependentNode<K, T, S>, S>,
214 #[serde(bound(
215 serialize = "IndexSet<K, S>: SerdeSerialize",
216 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
217 ))]
218 roots: IndexSet<K, S>,
219 active: Option<K>,
220 #[serde(bound(
221 serialize = "IndexSet<K, S>: SerdeSerialize",
222 deserialize = "IndexSet<K, S>: SerdeDeserialize<'de>"
223 ))]
224 bookmarked: IndexSet<K, S>,
225 metadata: M,
226}
227
228#[cfg(feature = "serde")]
229#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
230impl<'de, K, T, M, S> SerdeDeserialize<'de> for DependentWeave<K, T, M, S>
231where
232 K: Hash + Copy + Eq + Ord + SerdeDeserialize<'de>,
233 T: SerdeDeserialize<'de>,
234 M: SerdeDeserialize<'de>,
235 S: BuildHasher + Default + Clone,
236{
237 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
238 where
239 D: SerdeDeserializer<'de>,
240 {
241 let proxy = ProxyDependentWeave::deserialize(deserializer)?;
242 let weave = Self {
243 scratchpad: Vec::with_capacity(proxy.nodes.capacity()),
244 nodes: proxy.nodes,
245 roots: proxy.roots,
246 active: proxy.active,
247 bookmarked: proxy.bookmarked,
248 metadata: proxy.metadata,
249 };
250
251 if weave.validate() {
252 Ok(weave)
253 } else {
254 Err(D::Error::custom(ValidationError))
255 }
256 }
257}
258
259#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
260impl<K, T, M, S> PartialEq for DependentWeave<K, T, M, S>
261where
262 K: Hash + Copy + Eq + Ord,
263 T: PartialEq,
264 M: PartialEq,
265 S: BuildHasher + Default + Clone,
266{
267 #[inline]
268 fn eq(&self, other: &Self) -> bool {
269 self.roots.len() == other.roots.len()
270 && self.bookmarked.len() == other.bookmarked.len()
271 && self.active == other.active
272 && self
273 .roots
274 .iter()
275 .zip(other.roots.iter())
276 .all(|(a, b)| a == b)
277 && self
278 .bookmarked
279 .iter()
280 .zip(other.bookmarked.iter())
281 .all(|(a, b)| a == b)
282 && self.nodes == other.nodes
283 && self.metadata == other.metadata
284 }
285}
286
287#[allow(clippy::missing_trait_methods, reason = "Conflicting lint")]
288impl<K, T, M, S> Eq for DependentWeave<K, T, M, S>
289where
290 K: Hash + Copy + Eq + Ord,
291 T: Eq,
292 M: Eq,
293 S: BuildHasher + Default + Clone,
294{
295}
296
297impl<K, T, M, S> DependentWeave<K, T, M, S>
298where
299 K: Hash + Copy + Eq + Ord,
300 S: BuildHasher + Default + Clone,
301{
302 #[contract(
304 ensures(ret.nodes.is_empty()),
305 ensures(ret.validate())
306 )]
307 pub fn with_capacity(capacity: usize, metadata: M) -> Self {
308 Self {
309 nodes: HashMap::with_capacity_and_hasher(capacity, S::default()),
310 roots: IndexSet::with_capacity_and_hasher(capacity, S::default()),
311 active: None,
312 bookmarked: IndexSet::with_capacity_and_hasher(capacity, S::default()),
313 scratchpad: Vec::with_capacity(capacity),
314 metadata,
315 }
316 }
317 #[inline]
319 pub fn capacity(&self) -> usize {
320 self.nodes.capacity()
321 }
322 #[contract(
324 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
325 ensures(old(self.roots.clone()) == self.roots),
326 ensures(old(self.active) == self.active),
327 ensures(old(self.bookmarked.clone()) == self.bookmarked),
328 invariant(self.validate())
329 )]
330 pub fn reserve(&mut self, additional: usize) {
331 self.nodes.reserve(additional);
332 self.roots
333 .reserve(self.nodes.capacity().saturating_sub(self.roots.len()));
334 self.bookmarked
335 .reserve(self.nodes.capacity().saturating_sub(self.bookmarked.len()));
336 self.scratchpad
337 .reserve(self.nodes.capacity().saturating_sub(self.scratchpad.len()));
338 }
339 #[contract(
341 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
342 ensures(old(self.roots.clone()) == self.roots),
343 ensures(old(self.active) == self.active),
344 ensures(old(self.bookmarked.clone()) == self.bookmarked),
345 invariant(self.validate())
346 )]
347 pub fn shrink_to(&mut self, min_capacity: usize) {
348 self.nodes.shrink_to(min_capacity);
349 self.roots.shrink_to(min_capacity);
350 self.bookmarked.shrink_to(min_capacity);
351 self.scratchpad.shrink_to(min_capacity);
352 }
353 fn siblings<'a>(
354 &'a self,
355 node: &'a DependentNode<K, T, S>,
356 ) -> Box<dyn Iterator<Item = &'a DependentNode<K, T, S>> + 'a> {
357 match &node.from {
358 Some(parent) => Box::new(self.nodes.get(parent).into_iter().flat_map(|parent| {
359 parent
360 .to
361 .iter()
362 .copied()
363 .filter(|id| *id != node.id)
364 .filter_map(|id| self.nodes.get(&id))
365 })),
366 None => Box::new(
367 self.roots
368 .iter()
369 .copied()
370 .filter(|id| *id != node.id)
371 .filter_map(|id| self.nodes.get(&id)),
372 ),
373 }
374 }
375}
376
377impl<K, T, M, S> Weave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
378where
379 K: Hash + Copy + Eq + Ord,
380 S: BuildHasher + Default + Clone,
381{
382 type Nodes = HashMap<K, DependentNode<K, T, S>, S>;
383 type Roots = IndexSet<K, S>;
384
385 #[inline]
386 fn len(&self) -> usize {
387 self.nodes.len()
388 }
389 #[inline]
390 fn is_empty(&self) -> bool {
391 self.nodes.is_empty()
392 }
393 #[inline]
394 fn nodes(&self) -> &Self::Nodes {
395 &self.nodes
396 }
397 #[inline]
398 fn roots(&self) -> &Self::Roots {
399 &self.roots
400 }
401 #[inline]
402 fn contains(&self, id: &K) -> bool {
403 self.nodes.contains_key(id)
404 }
405 #[inline]
406 fn contains_active(&self, id: &K) -> bool {
407 self.active == Some(*id)
408 }
409 #[inline]
410 fn get_node(&self, id: &K) -> Option<&DependentNode<K, T, S>> {
411 self.nodes.get(id)
412 }
413 #[contract(
414 ensures(output.len() == self.nodes.len()),
415 ensures(valid_topological_sort(&self.nodes, output)),
416 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
417 ensures(old(self.roots.clone()) == self.roots),
418 ensures(old(self.active) == self.active),
419 ensures(old(self.bookmarked.clone()) == self.bookmarked),
420 invariant(self.validate())
421 )]
422 fn get_ordered_node_identifiers(&mut self, output: &mut Vec<K>) {
423 output.clear();
424
425 for root in &self.roots {
426 topological_sort(&self.nodes, *root, &mut self.scratchpad, output);
427 }
428 }
429 #[contract(
430 ensures(lacks_duplicates(output)),
431 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
432 ensures(self.nodes.contains_key(id) || output.is_empty()),
433 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
434 ensures(old(self.roots.clone()) == self.roots),
435 ensures(old(self.active) == self.active),
436 ensures(old(self.bookmarked.clone()) == self.bookmarked),
437 invariant(self.validate())
438 )]
439 fn get_ordered_node_identifiers_from(&mut self, id: &K, output: &mut Vec<K>) {
440 output.clear();
441
442 if self.nodes.contains_key(id) {
443 topological_sort(&self.nodes, *id, &mut self.scratchpad, output);
444 }
445 }
446 #[contract(
447 ensures(self.active == output.first().copied()),
448 ensures(lacks_duplicates(output)),
449 ensures(valid_path(&self.nodes, output)),
450 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
451 ensures(old(self.roots.clone()) == self.roots),
452 ensures(old(self.active) == self.active),
453 ensures(old(self.bookmarked.clone()) == self.bookmarked),
454 invariant(self.validate())
455 )]
456 fn get_active_path(&mut self, output: &mut Vec<K>) {
457 output.clear();
458
459 if let Some(active) = self.active {
460 path_to_root(&self.nodes, active, output);
461 }
462 }
463 #[contract(
464 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
465 ensures(self.nodes.contains_key(id) || output.is_empty()),
466 ensures(lacks_duplicates(output)),
467 ensures(valid_path(&self.nodes, output)),
468 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
469 ensures(old(self.roots.clone()) == self.roots),
470 ensures(old(self.active) == self.active),
471 ensures(old(self.bookmarked.clone()) == self.bookmarked),
472 invariant(self.validate())
473 )]
474 fn get_path_from(&mut self, id: &K, output: &mut Vec<K>) {
475 output.clear();
476
477 if self.nodes.contains_key(id) {
478 path_to_root(&self.nodes, *id, output);
479 }
480 }
481 #[contract(
482 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
483 ensures(!ret || old(!self.nodes.contains_key(&node.id))),
484 ensures(!ret || self.nodes.contains_key(&old(node.id))),
485 ensures(!ret || old(node.active) == (self.active == Some(old(node.id)))),
486 ensures(!ret || old(node.bookmarked) == self.bookmarked.contains(&old(node.id))),
487 ensures(!ret || old(node.from.is_some()) || self.roots.contains(&old(node.id))),
488 ensures(!ret || old(node.from.is_none()) || old(self.roots.clone()) == self.roots),
489 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
490 ensures(ret || old(self.roots.clone()) == self.roots),
491 ensures(ret || old(self.active) == self.active),
492 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
493 invariant(self.validate())
494 )]
495 fn add_node(&mut self, node: DependentNode<K, T, S>) -> bool {
496 if self.nodes.contains_key(&node.id) || !node.validate() || !node.to.is_empty() {
497 return false;
498 }
499
500 if let Some(from) = node.from {
501 match self.nodes.get_mut(&from) {
502 Some(parent) => {
503 parent.to.insert(node.id);
504 }
505 None => return false,
506 }
507 } else {
508 self.roots.insert(node.id);
509 }
510
511 if node.active {
512 if let Some(active) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
513 active.active = false;
514 }
515
516 self.active = Some(node.id);
517 }
518
519 if node.bookmarked {
520 self.bookmarked.insert(node.id);
521 }
522
523 self.nodes.insert(node.id, node);
524
525 true
526 }
527 #[contract(
528 ensures(!ret || value == self.contains_active(id)),
529 ensures(ret || old(self.active) == self.active),
530 ensures(ret == self.nodes.contains_key(id)),
531 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
532 ensures(old(self.roots.clone()) == self.roots),
533 ensures(old(self.bookmarked.clone()) == self.bookmarked),
534 invariant(self.validate())
535 )]
536 fn set_node_active_status(&mut self, id: &K, value: bool) -> bool {
537 match self.nodes.get_mut(id) {
538 Some(node) => {
539 node.active = value;
540
541 if value {
542 if self.active != Some(node.id)
543 && let Some(active) = self.active.and_then(|id| self.nodes.get_mut(&id))
544 {
545 active.active = false;
546 }
547
548 self.active = Some(*id);
549 } else if self.active == Some(node.id) {
550 self.active = None;
551 }
552
553 true
554 }
555 None => false,
556 }
557 }
558 #[contract(
559 ensures(!self.nodes.contains_key(id)),
560 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
561 ensures(ret.as_ref().is_none_or(|node| &node.id == id)),
562 ensures(ret.is_none() || old(self.nodes.len()) > self.nodes.len()),
563 ensures(ret.is_none() || old(self.bookmarked.len()) >= self.bookmarked.len()),
564 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
565 ensures(ret.is_some() || old(self.roots.clone()) == self.roots),
566 ensures(ret.is_some() || old(self.active) == self.active),
567 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
568 invariant(self.validate())
569 )]
570 fn remove_node(&mut self, id: &K) -> Option<DependentNode<K, T, S>> {
571 let mut removed_node = None;
572 let mut removed_active = false;
573
574 self.scratchpad.push(*id);
575
576 while let Some(id) = self.scratchpad.pop() {
577 if let Some(node) = self.nodes.remove(&id) {
578 if node.from.is_none() {
579 self.roots.shift_remove(&id);
580 }
581 if node.bookmarked {
582 self.bookmarked.shift_remove(&id);
583 }
584 if node.active {
585 self.active = None;
586 removed_active = true;
587 }
588
589 if let Some(parent) = node.from.and_then(|id| self.nodes.get_mut(&id)) {
590 parent.to.shift_remove(&id);
591 }
592 self.scratchpad.extend(node.to.iter().rev().copied());
593
594 if removed_node.is_none() {
595 removed_node = Some(node);
596 }
597 }
598 }
599
600 if let Some(removed) = removed_node {
601 if removed_active {
602 self.active = removed.from;
603
604 if let Some(node) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
605 node.active = true;
606 }
607 }
608 Some(removed)
609 } else {
610 None
611 }
612 }
613 #[contract(
614 ensures(!self.nodes.contains_key(id)),
615 ensures(ret == old(self.nodes.contains_key(id))),
616 ensures(!ret || old(self.nodes.len()) > self.nodes.len()),
617 ensures(!ret || old(self.bookmarked.len()) >= self.bookmarked.len()),
618 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
619 ensures(ret || old(self.roots.clone()) == self.roots),
620 ensures(ret || old(self.active) == self.active),
621 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
622 invariant(self.validate())
623 )]
624 fn remove_node_tracked(
625 &mut self,
626 id: &K,
627 mut on_removal: impl FnMut(DependentNode<K, T, S>),
628 ) -> bool {
629 let removed_node_parent = self.nodes.get(id).map(|node| node.from);
630 let mut removed_active = false;
631
632 self.scratchpad.push(*id);
633
634 while let Some(id) = self.scratchpad.pop() {
635 if let Some(node) = self.nodes.remove(&id) {
636 if node.from.is_none() {
637 self.roots.shift_remove(&id);
638 }
639 if node.bookmarked {
640 self.bookmarked.shift_remove(&id);
641 }
642 if node.active {
643 self.active = None;
644 removed_active = true;
645 }
646
647 if let Some(parent) = node.from.and_then(|id| self.nodes.get_mut(&id)) {
648 parent.to.shift_remove(&id);
649 }
650 self.scratchpad.extend(node.to.iter().rev().copied());
651
652 on_removal(node);
653 }
654 }
655
656 if let Some(parent) = removed_node_parent {
657 if removed_active {
658 self.active = parent;
659
660 if let Some(node) = self.active.and_then(|id| self.nodes.get_mut(&id)) {
661 node.active = true;
662 }
663 }
664 true
665 } else {
666 false
667 }
668 }
669 #[contract(
670 ensures(self.nodes.is_empty()),
671 ensures(self.validate())
672 )]
673 fn remove_all_nodes(&mut self) {
674 self.nodes.clear();
675 self.roots.clear();
676 self.active = None;
677 self.bookmarked.clear();
678 }
679}
680
681impl<K, T, M, S> DependentWeave<K, T, M, S>
682where
683 K: Hash + Copy + Eq + Ord,
684 S: BuildHasher + Default + Clone,
685{
686 pub fn validate(&self) -> bool {
688 let mut scratchpad = Vec::with_capacity(self.nodes.len());
689 let mut scratchpad_set = HashSet::with_capacity_and_hasher(self.nodes.len(), S::default());
690
691 self.scratchpad.is_empty()
692 && self
693 .roots
694 .iter()
695 .all(move |value| self.nodes.contains_key(value))
696 && self
697 .active
698 .as_ref()
699 .is_none_or(|active| self.nodes.contains_key(active))
700 && self
701 .bookmarked
702 .iter()
703 .all(move |value| self.nodes.contains_key(value))
704 && self.nodes.iter().all(|(key, value)| {
705 value.validate()
706 && value.id == *key
707 && value
708 .from
709 .as_ref()
710 .is_none_or(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
711 && value.to.iter().all(|v| {
712 self.nodes
713 .get(v)
714 .is_some_and(|p| p.from.as_ref() == Some(key))
715 })
716 && value.from.is_none() == self.roots.contains(key)
717 && value.active == (self.active == Some(*key))
718 && value.bookmarked == self.bookmarked.contains(key)
719 })
720 && !detect_cycles(
721 &self.nodes,
722 self.roots.iter().copied(),
723 &mut scratchpad,
724 &mut scratchpad_set,
725 )
726 }
727}
728
729impl<K, T, M, S> MetadataWeave<K, DependentNode<K, T, S>, T, M> for DependentWeave<K, T, M, S>
730where
731 K: Hash + Copy + Eq + Ord,
732 S: BuildHasher + Default + Clone,
733{
734 #[inline]
735 fn metadata(&self) -> &M {
736 &self.metadata
737 }
738 #[contract(
739 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
740 ensures(old(self.roots.clone()) == self.roots),
741 ensures(old(self.active) == self.active),
742 ensures(old(self.bookmarked.clone()) == self.bookmarked),
743 invariant(self.validate())
744 )]
745 #[inline]
746 fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O {
747 callback(&mut self.metadata)
748 }
749}
750
751impl<K, T, M, S> BookmarkableWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
752where
753 K: Hash + Copy + Eq + Ord,
754 S: BuildHasher + Default + Clone,
755{
756 type Bookmarks = IndexSet<K, S>;
757
758 #[inline]
759 fn bookmarks(&self) -> &Self::Bookmarks {
760 &self.bookmarked
761 }
762 #[inline]
763 fn contains_bookmark(&self, id: &K) -> bool {
764 self.bookmarked.contains(id)
765 }
766 #[contract(
767 ensures(!ret || value == self.bookmarked.contains(id)),
768 ensures(ret || old(self.bookmarked.clone()) == self.bookmarked),
769 ensures(ret == self.nodes.contains_key(id)),
770 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
771 ensures(old(self.roots.clone()) == self.roots),
772 ensures(old(self.active) == self.active),
773 invariant(self.validate())
774 )]
775 fn set_node_bookmarked_status(&mut self, id: &K, value: bool) -> bool {
776 match self.nodes.get_mut(id) {
777 Some(node) => {
778 node.bookmarked = value;
779 if value {
780 self.bookmarked.insert(node.id);
781 } else {
782 self.bookmarked.shift_remove(id);
783 }
784
785 true
786 }
787 None => false,
788 }
789 }
790}
791
792impl<K, T, M, S> SortableWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
793where
794 K: Hash + Copy + Eq + Ord,
795 S: BuildHasher + Default + Clone,
796{
797 #[contract(
798 ensures(output.len() == self.nodes.len()),
799 ensures(valid_topological_sort(&self.nodes, output)),
800 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
801 ensures(old(self.roots.clone()) == self.roots),
802 ensures(old(self.active) == self.active),
803 ensures(old(self.bookmarked.clone()) == self.bookmarked),
804 invariant(self.validate())
805 )]
806 fn get_ordered_node_identifiers_mirrored(&mut self, output: &mut Vec<K>) {
807 output.clear();
808
809 for root in &self.roots {
810 topological_sort_mirrored(&self.nodes, *root, &mut self.scratchpad, output);
811 }
812 }
813 #[contract(
814 ensures(lacks_duplicates(output)),
815 ensures(!self.nodes.contains_key(id) || output.first() == Some(id)),
816 ensures(self.nodes.contains_key(id) || output.is_empty()),
817 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
818 ensures(old(self.roots.clone()) == self.roots),
819 ensures(old(self.active) == self.active),
820 ensures(old(self.bookmarked.clone()) == self.bookmarked),
821 invariant(self.validate())
822 )]
823 fn get_ordered_node_identifiers_mirrored_from(&mut self, id: &K, output: &mut Vec<K>) {
824 output.clear();
825
826 if self.nodes.contains_key(id) {
827 topological_sort_mirrored(&self.nodes, *id, &mut self.scratchpad, output);
828 }
829 }
830 #[contract(
831 ensures(ret == self.nodes.contains_key(id)),
832 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
833 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
834 ensures(old(self.roots.clone()) == self.roots),
835 ensures(old(self.active) == self.active),
836 ensures(old(self.bookmarked.clone()) == self.bookmarked),
837 invariant(self.validate())
838 )]
839 fn sort_node_children_by(
840 &mut self,
841 id: &K,
842 mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
843 ) -> bool {
844 if let Some(mut node) = self.nodes.remove(id) {
845 node.to.sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
846 self.nodes.insert(node.id, node);
847
848 true
849 } else {
850 false
851 }
852 }
853 #[contract(
854 ensures(ret == self.nodes.contains_key(id)),
855 ensures(old(self.nodes.get(id).map(|n| n.to.clone())) == self.nodes.get(id).map(|n| n.to.clone())),
856 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
857 ensures(old(self.roots.clone()) == self.roots),
858 ensures(old(self.active) == self.active),
859 ensures(old(self.bookmarked.clone()) == self.bookmarked),
860 invariant(self.validate())
861 )]
862 fn sort_node_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool {
863 if let Some(node) = self.nodes.get_mut(id) {
864 node.to.sort_by(cmp);
865
866 true
867 } else {
868 false
869 }
870 }
871 #[contract(
872 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
873 ensures(old(self.roots.clone()) == self.roots),
874 ensures(old(self.active) == self.active),
875 ensures(old(self.bookmarked.clone()) == self.bookmarked),
876 invariant(self.validate())
877 )]
878 fn sort_roots_by(
879 &mut self,
880 mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
881 ) {
882 self.roots
883 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
884 }
885 #[contract(
886 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
887 ensures(old(self.roots.clone()) == self.roots),
888 ensures(old(self.active) == self.active),
889 ensures(old(self.bookmarked.clone()) == self.bookmarked),
890 invariant(self.validate())
891 )]
892 fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
893 self.roots.sort_by(cmp);
894 }
895}
896
897impl<K, T, M, S> SortableBookmarkableWeave<K, DependentNode<K, T, S>, T>
898 for DependentWeave<K, T, M, S>
899where
900 K: Hash + Copy + Eq + Ord,
901 S: BuildHasher + Default + Clone,
902{
903 #[contract(
904 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
905 ensures(old(self.roots.clone()) == self.roots),
906 ensures(old(self.active) == self.active),
907 ensures(old(self.bookmarked.clone()) == self.bookmarked),
908 invariant(self.validate())
909 )]
910 fn sort_bookmarks_by(
911 &mut self,
912 mut cmp: impl FnMut(&DependentNode<K, T, S>, &DependentNode<K, T, S>) -> Ordering,
913 ) {
914 self.bookmarked
915 .sort_by(|a, b| cmp(&self.nodes[a], &self.nodes[b]));
916 }
917 #[contract(
918 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
919 ensures(old(self.roots.clone()) == self.roots),
920 ensures(old(self.active) == self.active),
921 ensures(old(self.bookmarked.clone()) == self.bookmarked),
922 invariant(self.validate())
923 )]
924 fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering) {
925 self.bookmarked.sort_by(cmp);
926 }
927}
928
929impl<K, T, M, S> ActiveSingularWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
930where
931 K: Hash + Copy + Eq + Ord,
932 S: BuildHasher + Default + Clone,
933{
934 #[inline]
935 fn active(&self) -> Option<K> {
936 self.active
937 }
938}
939
940impl<K, T, M, S> DiscreteWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
941where
942 K: Hash + Copy + Eq + Ord,
943 T: DiscreteContents,
944 S: BuildHasher + Default + Clone,
945{
946 #[contract(
947 ensures(!ret || old(self.nodes.len()) + 1 == self.nodes.len()),
948 ensures(!ret || self.nodes.contains_key(id)),
949 ensures(!ret || self.nodes.contains_key(&new_id)),
950 ensures(!ret || old(!self.nodes.contains_key(&new_id))),
951 ensures(!ret || self.nodes[id].to.contains(&new_id) && self.nodes[id].to.len() == 1),
952 ensures(!ret || self.nodes[&new_id].from == Some(*id)),
953 ensures(!ret || old(self.nodes.get(id).map(|n| n.to.clone())).unwrap() == self.nodes[&new_id].to),
954 ensures(ret || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
955 ensures(old(self.roots.clone()) == self.roots),
956 ensures(old(self.active) == self.active),
957 ensures(old(self.bookmarked.clone()) == self.bookmarked),
958 invariant(self.validate())
959 )]
960 fn split_node(&mut self, id: &K, at: usize, new_id: K) -> bool {
961 if self.nodes.contains_key(&new_id) || *id == new_id {
962 return false;
963 }
964
965 if let Some(mut node) = self.nodes.remove(id) {
966 match node.contents.split(at) {
967 DiscreteContentResult::Two(left, right) => {
968 let left_node = DependentNode {
969 id: node.id,
970 from: node.from,
971 to: IndexSet::from_iter([new_id]),
972 active: node.active,
973 bookmarked: node.bookmarked,
974 contents: left,
975 };
976
977 node.from = Some(node.id);
978 node.id = new_id;
979 node.contents = right;
980 node.active = false;
981 node.bookmarked = false;
982
983 for child in &node.to {
984 let child = self.nodes.get_mut(child).unwrap();
985 child.from = Some(node.id);
986 }
987
988 self.nodes.insert(left_node.id, left_node);
989 self.nodes.insert(node.id, node);
990
991 true
992 }
993 DiscreteContentResult::One(content) => {
994 node.contents = content;
995 self.nodes.insert(node.id, node);
996 false
997 }
998 }
999 } else {
1000 false
1001 }
1002 }
1003 #[contract(
1004 ensures(ret.is_none() || old(self.nodes.len()) - 1 == self.nodes.len()),
1005 ensures(ret.is_none() || !self.nodes.contains_key(id)),
1006 ensures(ret.is_none() || old(self.nodes.contains_key(id))),
1007 ensures(ret.is_none() || !old(self.contains_active(id)) || old(self.contains_active(id)) && self.contains_active(&ret.unwrap())),
1008 ensures(ret.is_none() || old(self.contains_active(id)) || old(self.nodes.get(id).and_then(|n| n.from).and_then(|p| self.nodes.get(&p)).map(|p| p.active)).unwrap() == self.nodes[&ret.unwrap()].active),
1009 ensures(ret.is_none() || old(self.nodes.get(id).and_then(|n| n.from).and_then(|p| self.nodes.get(&p)).map(|p| p.from)).unwrap() == self.nodes[&ret.unwrap()].from),
1010 ensures(ret.is_none() || old(self.nodes.get(id).map(|node| node.to.clone())).unwrap() == self.nodes[&ret.unwrap()].to),
1011 ensures(ret.is_none() || ret.unwrap() == old(self.nodes.get(id).and_then(|node| node.from)).unwrap()),
1012 ensures(ret.is_some() || old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1013 ensures(ret.is_some() || old(self.active) == self.active),
1014 ensures(ret.is_some() || old(self.bookmarked.clone()) == self.bookmarked),
1015 ensures(old(self.roots.clone()) == self.roots),
1016 invariant(self.validate())
1017 )]
1018 fn merge_with_parent(&mut self, id: &K) -> Option<K> {
1019 if let Some(mut node) = self.nodes.remove(id) {
1020 if let Some(mut parent) = node.from.and_then(|id| self.nodes.remove(&id)) {
1021 if parent.to.len() > 1 {
1022 self.nodes.insert(parent.id, parent);
1023 self.nodes.insert(node.id, node);
1024 return None;
1025 }
1026
1027 match parent.contents.merge(node.contents) {
1028 DiscreteContentResult::Two(left, right) => {
1029 parent.contents = left;
1030 node.contents = right;
1031 self.nodes.insert(parent.id, parent);
1032 self.nodes.insert(node.id, node);
1033 None
1034 }
1035 DiscreteContentResult::One(content) => {
1036 parent.contents = content;
1037 parent.to = node.to;
1038
1039 for child in &parent.to {
1040 let child = self.nodes.get_mut(child).unwrap();
1041 child.from = Some(parent.id);
1042 }
1043
1044 if node.active {
1045 parent.active = true;
1046 self.active = Some(parent.id);
1047 }
1048
1049 let parent_id = parent.id;
1050
1051 self.nodes.insert(parent.id, parent);
1052
1053 self.bookmarked.shift_remove(&node.id);
1054
1055 Some(parent_id)
1056 }
1057 }
1058 } else {
1059 self.nodes.insert(node.id, node);
1060 None
1061 }
1062 } else {
1063 None
1064 }
1065 }
1066}
1067
1068impl<K, T, M, S> SemiIndependentWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
1069where
1070 K: Hash + Copy + Eq + Ord,
1071 T: IndependentContents,
1072 S: BuildHasher + Default + Clone,
1073{
1074 #[contract(
1075 ensures(ret.is_some() == old(self.nodes.contains_key(id))),
1076 ensures(old(self.nodes.keys().copied().collect::<HashSet<_>>()) == self.nodes.keys().copied().collect::<HashSet<_>>()),
1077 ensures(old(self.roots.clone()) == self.roots),
1078 ensures(old(self.active) == self.active),
1079 ensures(old(self.bookmarked.clone()) == self.bookmarked),
1080 invariant(self.validate())
1081 )]
1082 #[inline]
1083 fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O> {
1084 self.nodes
1085 .get_mut(id)
1086 .map(|node| callback(&mut node.contents))
1087 }
1088}
1089
1090impl<K, T, M, S> DeduplicatableWeave<K, DependentNode<K, T, S>, T> for DependentWeave<K, T, M, S>
1091where
1092 K: Hash + Copy + Eq + Ord,
1093 T: DeduplicatableContents,
1094 S: BuildHasher + Default + Clone,
1095{
1096 fn find_duplicates(&self, id: &K) -> impl Iterator<Item = K> {
1097 self.nodes.get(id).into_iter().flat_map(|node| {
1098 self.siblings(node).filter_map(|sibling| {
1099 if node.contents.is_duplicate_of(&sibling.contents) {
1100 Some(sibling.id)
1101 } else {
1102 None
1103 }
1104 })
1105 })
1106 }
1107}
1108
1109#[cfg(feature = "rkyv")]
1110impl<K, T, S> ArchivedDependentNode<K, T, S>
1111where
1112 K: Archive + Hash + Copy + Eq + Ord,
1113 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1114 T: Archive,
1115 S: BuildHasher + Default + Clone,
1116{
1117 #[inline]
1118 fn validate(&self) -> bool {
1119 (if let ArchivedOption::Some(from) = &self.from {
1120 !self.to.contains(from)
1121 } else {
1122 true
1123 }) && self.from != Some(self.id)
1124 && !self.to.contains(&self.id)
1125 }
1126}
1127
1128#[cfg(feature = "rkyv")]
1129impl<K, T, S> Node<K::Archived, T::Archived> for ArchivedDependentNode<K, T, S>
1130where
1131 K: Archive + Hash + Copy + Eq + Ord,
1132 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1133 T: Archive,
1134 S: BuildHasher + Default + Clone,
1135{
1136 type From = ArchivedOption<K::Archived>;
1137 type To = ArchivedIndexSet<K::Archived>;
1138
1139 #[inline]
1140 fn id(&self) -> K::Archived {
1141 self.id
1142 }
1143 #[inline]
1144 fn from(&self) -> &Self::From {
1145 &self.from
1146 }
1147 #[inline]
1148 fn to(&self) -> &Self::To {
1149 &self.to
1150 }
1151 #[inline]
1152 fn is_active(&self) -> bool {
1153 self.active
1154 }
1155 #[inline]
1156 fn contents(&self) -> &<T as Archive>::Archived {
1157 &self.contents
1158 }
1159}
1160
1161#[cfg(feature = "rkyv")]
1162impl<K, T, M, S> ArchivedDependentWeave<K, T, M, S>
1163where
1164 K: Archive + Hash + Copy + Eq + Ord,
1165 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1166 T: Archive,
1167 M: Archive,
1168 S: BuildHasher + Default + Clone,
1169{
1170 fn validate(&self) -> bool {
1171 let mut scratchpad = Vec::with_capacity(self.nodes.len());
1172 let mut scratchpad_set = HashSet::with_capacity(self.nodes.len());
1173
1174 self.roots
1175 .iter()
1176 .all(move |value| self.nodes.contains_key(value))
1177 && self
1178 .active
1179 .as_ref()
1180 .is_none_or(|active| self.nodes.contains_key(active))
1181 && self
1182 .bookmarked
1183 .iter()
1184 .all(move |value| self.nodes.contains_key(value))
1185 && self.nodes.iter().all(|(key, value)| {
1186 value.validate()
1187 && value.id == *key
1188 && value
1189 .from
1190 .as_ref()
1191 .is_none_or(|v| self.nodes.get(v).is_some_and(|p| p.to.contains(key)))
1192 && value.to.iter().all(|v| {
1193 self.nodes
1194 .get(v)
1195 .is_some_and(|p| p.from.as_ref() == Some(key))
1196 })
1197 && value.from.is_none() == self.roots.contains(key)
1198 && value.active == (self.active == Some(*key))
1199 && value.bookmarked == self.bookmarked.contains(key)
1200 })
1201 && !archived_detect_cycles(
1202 &self.nodes,
1203 self.roots.iter().copied(),
1204 &mut scratchpad,
1205 &mut scratchpad_set,
1206 )
1207 }
1208}
1209
1210#[cfg(feature = "rkyv")]
1211unsafe impl<K, T, M, S, C> Verify<C> for ArchivedDependentWeave<K, T, M, S>
1214where
1215 K: Archive + Hash + Copy + Eq + Ord,
1216 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1217 T: Archive,
1218 M: Archive,
1219 S: BuildHasher + Default + Clone,
1220 C: Fallible + ?Sized,
1221 C::Error: Source,
1222{
1223 fn verify(&self, _context: &mut C) -> Result<(), C::Error> {
1224 if !self.validate() {
1225 fail!(ValidationError)
1226 }
1227
1228 Ok(())
1229 }
1230}
1231
1232#[cfg(feature = "rkyv")]
1233impl<K, T, M, S> ImmutableWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1234 for ArchivedDependentWeave<K, T, M, S>
1235where
1236 K: Archive + Hash + Copy + Eq + Ord,
1237 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1238 T: Archive,
1239 M: Archive,
1240 S: BuildHasher + Default + Clone,
1241{
1242 type Nodes = ArchivedHashMap<K::Archived, ArchivedDependentNode<K, T, S>>;
1243 type Roots = ArchivedIndexSet<K::Archived>;
1244
1245 #[inline]
1246 fn len(&self) -> usize {
1247 self.nodes.len()
1248 }
1249 #[inline]
1250 fn is_empty(&self) -> bool {
1251 self.nodes.is_empty()
1252 }
1253 #[inline]
1254 fn nodes(&self) -> &Self::Nodes {
1255 &self.nodes
1256 }
1257 #[inline]
1258 fn roots(&self) -> &Self::Roots {
1259 &self.roots
1260 }
1261 #[inline]
1262 fn contains(&self, id: &K::Archived) -> bool {
1263 self.nodes.contains_key(id)
1264 }
1265 #[inline]
1266 fn contains_active(&self, id: &K::Archived) -> bool {
1267 self.active == Some(*id)
1268 }
1269 #[inline]
1270 fn get_node(&self, id: &K::Archived) -> Option<&ArchivedDependentNode<K, T, S>> {
1271 self.nodes.get(id)
1272 }
1273 fn get_ordered_node_identifiers(&self, output: &mut Vec<K::Archived>) {
1274 output.clear();
1275
1276 let mut scratchpad = Vec::with_capacity(self.len());
1277 let mut scratchpad_2 = Vec::with_capacity(self.len());
1278
1279 for root in self.roots().iter() {
1280 archived_topological_sort(
1281 &self.nodes,
1282 *root,
1283 &mut scratchpad,
1284 &mut scratchpad_2,
1285 output,
1286 );
1287 }
1288 }
1289 fn get_ordered_node_identifiers_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
1290 output.clear();
1291
1292 if self.nodes.contains_key(id) {
1293 let mut scratchpad = Vec::with_capacity(self.len());
1294 let mut scratchpad_2 = Vec::with_capacity(self.len());
1295
1296 archived_topological_sort(&self.nodes, *id, &mut scratchpad, &mut scratchpad_2, output);
1297 }
1298 }
1299 fn get_active_path(&self, output: &mut Vec<K::Archived>) {
1300 output.clear();
1301
1302 if let ArchivedOption::Some(active) = self.active {
1303 archived_path_to_root(&self.nodes, active, output);
1304 }
1305 }
1306 fn get_path_from(&self, id: &K::Archived, output: &mut Vec<K::Archived>) {
1307 output.clear();
1308
1309 if self.nodes.contains_key(id) {
1310 archived_path_to_root(&self.nodes, *id, output);
1311 }
1312 }
1313}
1314
1315#[cfg(feature = "rkyv")]
1316impl<K, T, M, S>
1317 ImmutableMetadataWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived, M::Archived>
1318 for ArchivedDependentWeave<K, T, M, S>
1319where
1320 K: Archive + Hash + Copy + Eq + Ord,
1321 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1322 T: Archive,
1323 M: Archive,
1324 S: BuildHasher + Default + Clone,
1325{
1326 #[inline]
1327 fn metadata(&self) -> &M::Archived {
1328 &self.metadata
1329 }
1330}
1331
1332#[cfg(feature = "rkyv")]
1333impl<K, T, M, S>
1334 ImmutableBookmarkableWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1335 for ArchivedDependentWeave<K, T, M, S>
1336where
1337 K: Archive + Hash + Copy + Eq + Ord,
1338 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1339 T: Archive,
1340 M: Archive,
1341 S: BuildHasher + Default + Clone,
1342{
1343 type Bookmarks = ArchivedIndexSet<K::Archived>;
1344
1345 #[inline]
1346 fn bookmarks(&self) -> &Self::Bookmarks {
1347 &self.bookmarked
1348 }
1349 #[inline]
1350 fn contains_bookmark(&self, id: &K::Archived) -> bool {
1351 self.bookmarked.contains(id)
1352 }
1353}
1354
1355#[cfg(feature = "rkyv")]
1356impl<K, T, M, S> ImmutableSortableWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1357 for ArchivedDependentWeave<K, T, M, S>
1358where
1359 K: Archive + Hash + Copy + Eq + Ord,
1360 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1361 T: Archive,
1362 M: Archive,
1363 S: BuildHasher + Default + Clone,
1364{
1365 fn get_ordered_node_identifiers_mirrored(&self, output: &mut Vec<K::Archived>) {
1366 output.clear();
1367 let mut scratchpad = Vec::with_capacity(self.len());
1368
1369 for root in self.roots().iter() {
1370 archived_topological_sort_mirrored(&self.nodes, *root, &mut scratchpad, output);
1371 }
1372 }
1373 fn get_ordered_node_identifiers_mirrored_from(
1374 &self,
1375 id: &K::Archived,
1376 output: &mut Vec<K::Archived>,
1377 ) {
1378 output.clear();
1379
1380 if self.nodes.contains_key(id) {
1381 let mut scratchpad = Vec::with_capacity(self.len());
1382
1383 archived_topological_sort_mirrored(&self.nodes, *id, &mut scratchpad, output);
1384 }
1385 }
1386}
1387
1388#[cfg(feature = "rkyv")]
1389impl<K, T, M, S>
1390 ImmutableActiveSingularWeave<K::Archived, ArchivedDependentNode<K, T, S>, T::Archived>
1391 for ArchivedDependentWeave<K, T, M, S>
1392where
1393 K: Archive + Hash + Copy + Eq + Ord,
1394 <K as Archive>::Archived: Hash + Copy + Eq + Ord + 'static,
1395 T: Archive,
1396 M: Archive,
1397 S: BuildHasher + Default + Clone,
1398{
1399 #[inline]
1400 fn active(&self) -> Option<K::Archived> {
1401 match self.active {
1402 ArchivedOption::Some(active) => Some(active),
1403 ArchivedOption::None => None,
1404 }
1405 }
1406}
1407
1408fn path_to_root<K, T, S>(
1409 nodes: &HashMap<K, DependentNode<K, T, S>, S>,
1410 mut id: K,
1411 thread: &mut Vec<K>,
1412) where
1413 K: Hash + Copy + Eq + Ord,
1414 S: BuildHasher + Default + Clone,
1415{
1416 thread.push(id);
1417
1418 while let Some(parent) = nodes[&id].from {
1419 thread.push(parent);
1420 id = parent;
1421 }
1422}
1423
1424fn topological_sort<K, N, T, S>(
1425 nodes: &HashMap<K, N, S>,
1426 id: K,
1427 scratchpad: &mut Vec<K>,
1428 identifiers: &mut Vec<K>,
1429) where
1430 K: Hash + Copy + Eq + Ord,
1431 N: Node<K, T, From = Option<K>, To = IndexSet<K, S>>,
1432 S: BuildHasher + Default + Clone,
1433{
1434 scratchpad.push(id);
1435
1436 while let Some(id) = scratchpad.pop() {
1437 identifiers.push(id);
1438 scratchpad.extend(nodes[&id].to().into_iter().rev().copied());
1439 }
1440}
1441
1442fn topological_sort_mirrored<K, N, T, S>(
1443 nodes: &HashMap<K, N, S>,
1444 id: K,
1445 scratchpad: &mut Vec<K>,
1446 identifiers: &mut Vec<K>,
1447) where
1448 K: Hash + Copy + Eq + Ord,
1449 N: Node<K, T, From = Option<K>, To = IndexSet<K, S>>,
1450 S: BuildHasher + Default + Clone,
1451{
1452 scratchpad.push(id);
1453
1454 while let Some(id) = scratchpad.pop() {
1455 identifiers.push(id);
1456 scratchpad.extend(nodes[&id].to().into_iter().copied());
1457 }
1458}
1459
1460fn detect_cycles<K, N, T, S>(
1461 nodes: &HashMap<K, N, S>,
1462 roots: impl Iterator<Item = K>,
1463 scratchpad: &mut Vec<K>,
1464 scratchpad_set: &mut HashSet<K, S>,
1465) -> bool
1466where
1467 K: Hash + Copy + Eq + Ord,
1468 N: Node<K, T, From = Option<K>, To = IndexSet<K, S>>,
1469 S: BuildHasher + Default + Clone,
1470{
1471 scratchpad.extend(roots);
1472
1473 while let Some(id) = scratchpad.pop() {
1474 if !scratchpad_set.insert(id) {
1475 return true;
1476 }
1477 scratchpad.extend(nodes[&id].to().into_iter().rev().copied());
1478 }
1479
1480 scratchpad_set.len() != nodes.len()
1481}
1482
1483#[cfg(feature = "rkyv")]
1484fn archived_path_to_root<K, T, S>(
1485 nodes: &ArchivedHashMap<K::Archived, ArchivedDependentNode<K, T, S>>,
1486 mut id: K::Archived,
1487 thread: &mut Vec<K::Archived>,
1488) where
1489 K: Archive + Hash + Copy + Eq + Ord,
1490 <K as Archive>::Archived: Hash + Copy + Eq + Ord,
1491 T: Archive,
1492 S: BuildHasher + Default + Clone,
1493{
1494 thread.push(id);
1495
1496 while let ArchivedOption::Some(parent) = nodes[&id].from {
1497 thread.push(parent);
1498 id = parent;
1499 }
1500}
1501
1502#[cfg(feature = "rkyv")]
1503fn archived_topological_sort<K, N, T>(
1504 nodes: &ArchivedHashMap<K, N>,
1505 id: K,
1506 scratchpad: &mut Vec<K>,
1507 scratchpad_2: &mut Vec<K>,
1508 identifiers: &mut Vec<K>,
1509) where
1510 K: Hash + Copy + Eq + Ord,
1511 N: Node<K, T, From = ArchivedOption<K>, To = ArchivedIndexSet<K>>,
1512{
1513 scratchpad.push(id);
1514
1515 while let Some(id) = scratchpad.pop() {
1516 identifiers.push(id);
1517 scratchpad_2.extend(nodes[&id].to().iter().copied());
1518 scratchpad_2.reverse();
1519 scratchpad.append(scratchpad_2);
1520 }
1521}
1522
1523#[cfg(feature = "rkyv")]
1524fn archived_topological_sort_mirrored<K, N, T>(
1525 nodes: &ArchivedHashMap<K, N>,
1526 id: K,
1527 scratchpad: &mut Vec<K>,
1528 identifiers: &mut Vec<K>,
1529) where
1530 K: Hash + Copy + Eq + Ord,
1531 N: Node<K, T, From = ArchivedOption<K>, To = ArchivedIndexSet<K>>,
1532{
1533 scratchpad.push(id);
1534
1535 while let Some(id) = scratchpad.pop() {
1536 identifiers.push(id);
1537 scratchpad.extend(nodes[&id].to().iter().copied());
1538 }
1539}
1540
1541#[cfg(feature = "rkyv")]
1542fn archived_detect_cycles<K, N, T, S>(
1543 nodes: &ArchivedHashMap<K, N>,
1544 roots: impl Iterator<Item = K>,
1545 scratchpad: &mut Vec<K>,
1546 scratchpad_set: &mut HashSet<K, S>,
1547) -> bool
1548where
1549 K: Hash + Copy + Eq + Ord,
1550 N: Node<K, T, From = ArchivedOption<K>, To = ArchivedIndexSet<K>>,
1551 S: BuildHasher + Default + Clone,
1552{
1553 scratchpad.extend(roots);
1554
1555 while let Some(id) = scratchpad.pop() {
1556 if !scratchpad_set.insert(id) {
1557 return true;
1558 }
1559 scratchpad.extend(nodes[&id].to().iter().copied());
1560 }
1561
1562 scratchpad_set.len() != nodes.len()
1563}