1#![no_std]
12#![forbid(non_ascii_idents)]
13#![warn(missing_docs)]
14#![warn(let_underscore)]
15#![warn(clippy::pedantic)]
16#![warn(clippy::cargo)]
17#![allow(clippy::multiple_crate_versions, reason = "Unresolvable")]
18#![warn(clippy::nursery)]
19#![warn(clippy::restriction)]
20#![allow(clippy::blanket_clippy_restriction_lints, reason = "Conflicting lint")]
21#![allow(clippy::allow_attributes, reason = "Conflicting lint")]
22#![allow(clippy::pattern_type_mismatch, reason = "Conflicting lint")]
23#![allow(clippy::separated_literal_suffix, reason = "Conflicting lint")]
24#![allow(
25 clippy::field_scoped_visibility_modifiers,
26 reason = "Used by IndependentWeave::from()"
27)]
28#![allow(
29 clippy::missing_inline_in_public_items,
30 reason = "Reasonable candidates have already been inlined"
31)]
32#![allow(clippy::exhaustive_enums, reason = "API")]
33#![allow(clippy::exhaustive_structs, reason = "API")]
34#![allow(clippy::little_endian_bytes, reason = "API")]
35#![allow(clippy::partial_pub_fields, reason = "API")]
36#![allow(clippy::pub_use, reason = "API")]
37#![allow(clippy::arbitrary_source_item_ordering, reason = "Readability")]
38#![allow(clippy::question_mark_used, reason = "Readability")]
39#![allow(clippy::single_call_fn, reason = "Readability")]
40#![allow(clippy::single_char_lifetime_names, reason = "Readability")]
41#![allow(clippy::else_if_without_else, reason = "Style")]
42#![allow(clippy::if_then_some_else_none, reason = "Style")]
43#![allow(clippy::implicit_return, reason = "Style")]
44#![allow(clippy::min_ident_chars, reason = "Style")]
45#![allow(clippy::mod_module_files, reason = "Style")]
46#![allow(clippy::module_name_repetitions, reason = "Style")]
47#![allow(clippy::multiple_inherent_impl, reason = "Style")]
48#![allow(clippy::try_err, reason = "Style")]
49#![allow(clippy::allow_attributes_without_reason)] #![allow(clippy::indexing_slicing)] #![allow(clippy::unwrap_in_result)] #![allow(clippy::unwrap_used)] #![allow(clippy::missing_docs_in_private_items)] #![allow(clippy::shadow_unrelated)] #![allow(clippy::shadow_reuse)] mod contract;
58pub mod dependent;
59pub mod independent;
60pub mod wrappers;
61
62#[cfg(feature = "rkyv")]
63pub mod versioning;
64
65pub use contracts;
66pub use hashbrown;
67pub use indexmap;
68
69#[cfg(feature = "rkyv")]
70pub use rkyv;
71
72#[cfg(feature = "loro")]
73pub use loro;
74
75extern crate alloc;
76
77use alloc::{collections::vec_deque::VecDeque, vec::Vec};
78use core::{
79 cmp::{Ordering, Reverse},
80 hash::{BuildHasher, Hash},
81};
82
83use hashbrown::{HashMap, HashSet, hash_map::Entry};
84
85#[cfg(feature = "serde")]
86pub use serde;
87
88#[must_use]
90pub trait Node<K, T>
91where
92 K: Hash + Copy + Eq + Ord,
93{
94 type From;
96 type To;
98
99 #[must_use]
101 fn id(&self) -> K;
102 #[must_use]
104 fn from(&self) -> &Self::From;
105 #[must_use]
107 fn to(&self) -> &Self::To;
108 #[must_use]
112 fn is_active(&self) -> bool;
113 #[must_use]
115 fn contents(&self) -> &T;
116}
117
118pub trait DiscreteContents: Sized {
120 fn split(self, at: usize) -> DiscreteContentResult<Self>;
124 fn merge(self, value: Self) -> DiscreteContentResult<Self>;
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
132#[allow(missing_docs, reason = "Enum items are self-explanatory")]
133#[must_use]
134pub enum DiscreteContentResult<T> {
135 One(T),
136 Two(T, T),
137}
138
139pub trait IndependentContents {}
141
142pub trait DeduplicatableContents {
146 #[must_use]
148 fn is_duplicate_of(&self, other: &Self) -> bool;
149}
150
151#[must_use]
161pub trait Weave<K, N, T>
162where
163 K: Hash + Copy + Eq + Ord,
164 N: Node<K, T>,
165{
166 type Nodes;
168 type Roots;
170
171 #[must_use]
173 fn len(&self) -> usize;
174 #[must_use]
176 fn is_empty(&self) -> bool;
177 #[must_use]
179 fn nodes(&self) -> &Self::Nodes;
180 #[must_use]
182 fn roots(&self) -> &Self::Roots;
183 #[must_use]
185 fn contains(&self, id: &K) -> bool;
186 #[must_use]
190 fn contains_active(&self, id: &K) -> bool;
191 #[must_use]
193 fn get(&self, id: &K) -> Option<&N>;
194 #[must_use]
196 fn get_parents(&self, id: &K) -> Option<&N::From>;
197 #[must_use]
199 fn get_children(&self, id: &K) -> Option<&N::To>;
200 #[must_use]
202 fn get_contents(&self, id: &K) -> Option<&T>;
203 fn get_ordered_identifiers(&mut self, output: &mut Vec<K>);
205 fn get_ordered_identifiers_from(&mut self, id: &K, output: &mut Vec<K>);
207 fn get_active_path(&mut self, output: &mut Vec<K>);
211 fn get_path_from(&mut self, id: &K, output: &mut Vec<K>);
215 fn insert(&mut self, node: N) -> bool;
219 fn set_active(&mut self, id: &K, value: bool) -> bool;
223 fn remove(&mut self, id: &K) -> Option<N>;
229 fn remove_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool;
237 fn clear(&mut self);
241}
242
243pub trait MetadataWeave<K, N, T, M>: Weave<K, N, T>
249where
250 K: Hash + Copy + Eq + Ord,
251 N: Node<K, T>,
252{
253 #[must_use]
255 fn metadata(&self) -> &M;
256 fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O;
262}
263
264pub trait BookmarkableWeave<K, N, T>: Weave<K, N, T>
266where
267 K: Hash + Copy + Eq + Ord,
268 N: Node<K, T>,
269{
270 type Bookmarks;
272
273 #[must_use]
275 fn bookmarks(&self) -> &Self::Bookmarks;
276 #[must_use]
278 fn contains_bookmark(&self, id: &K) -> bool;
279 fn set_bookmarked(&mut self, id: &K, value: bool) -> bool;
281}
282
283pub trait SortableWeave<K, N, T>: Weave<K, N, T>
289where
290 K: Hash + Copy + Eq + Ord,
291 N: Node<K, T>,
292{
293 fn sort_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool;
299 fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool;
305 fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering);
311 fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering);
317}
318
319pub trait SortableBookmarkableWeave<K, N, T>:
325 BookmarkableWeave<K, N, T> + SortableWeave<K, N, T>
326where
327 K: Hash + Copy + Eq + Ord,
328 N: Node<K, T>,
329{
330 fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering);
336 fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering);
342}
343
344pub trait ActiveSingularWeave<K, N, T>: Weave<K, N, T>
346where
347 K: Hash + Copy + Eq + Ord,
348 N: Node<K, T>,
349{
350 #[must_use]
352 fn active(&self) -> Option<K>;
353}
354
355pub trait ActivePathWeave<K, N, T>: Weave<K, N, T>
357where
358 K: Hash + Copy + Eq + Ord,
359 N: Node<K, T>,
360{
361 type Active;
363
364 #[must_use]
366 fn active(&self) -> &Self::Active;
367 fn set_active_path(&mut self, active: impl Iterator<Item = K>);
371}
372
373pub trait IndependentWeave<K, N, T>: Weave<K, N, T> + SemiIndependentWeave<K, N, T>
375where
376 K: Hash + Copy + Eq + Ord,
377 N: Node<K, T>,
378 T: IndependentContents,
379{
380 fn move_to(&mut self, id: &K, new_parents: &[K]) -> bool;
384}
385
386pub trait SemiIndependentWeave<K, N, T>: Weave<K, N, T>
392where
393 K: Hash + Copy + Eq + Ord,
394 N: Node<K, T>,
395 T: IndependentContents,
396{
397 #[must_use]
405 fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O>;
406}
407
408pub trait DiscreteWeave<K, N, T>: Weave<K, N, T>
414where
415 K: Hash + Copy + Eq + Ord,
416 N: Node<K, T>,
417 T: DiscreteContents,
418{
419 fn split(&mut self, id: &K, at: usize, new_id: K) -> bool;
427 fn merge_with_parent(&mut self, id: &K) -> Option<K>;
435}
436
437#[must_use]
439pub trait ImmutableWeave<K, N, T>
440where
441 K: Hash + Copy + Eq + Ord,
442 N: Node<K, T>,
443{
444 type Nodes;
446 type Roots;
448
449 #[must_use]
451 fn len(&self) -> usize;
452 #[must_use]
454 fn is_empty(&self) -> bool;
455 #[must_use]
457 fn nodes(&self) -> &Self::Nodes;
458 #[must_use]
460 fn roots(&self) -> &Self::Roots;
461 #[must_use]
463 fn contains(&self, id: &K) -> bool;
464 #[must_use]
468 fn contains_active(&self, id: &K) -> bool;
469 #[must_use]
471 fn get(&self, id: &K) -> Option<&N>;
472 #[must_use]
474 fn get_parents(&self, id: &K) -> Option<&N::From>;
475 #[must_use]
477 fn get_children(&self, id: &K) -> Option<&N::To>;
478 #[must_use]
480 fn get_contents(&self, id: &K) -> Option<&T>;
481 fn get_ordered_identifiers(&self, output: &mut Vec<K>);
483 fn get_ordered_identifiers_from(&self, id: &K, output: &mut Vec<K>);
485 fn get_active_path(&self, output: &mut Vec<K>);
489 fn get_path_from(&self, id: &K, output: &mut Vec<K>);
493}
494
495pub trait ImmutableMetadataWeave<K, N, T, M>: ImmutableWeave<K, N, T>
497where
498 K: Hash + Copy + Eq + Ord,
499 N: Node<K, T>,
500{
501 #[must_use]
503 fn metadata(&self) -> &M;
504}
505
506pub trait ImmutableBookmarkableWeave<K, N, T>: ImmutableWeave<K, N, T>
508where
509 K: Hash + Copy + Eq + Ord,
510 N: Node<K, T>,
511{
512 type Bookmarks;
514
515 #[must_use]
517 fn bookmarks(&self) -> &Self::Bookmarks;
518 #[must_use]
520 fn contains_bookmark(&self, id: &K) -> bool;
521}
522
523pub trait ImmutableActiveSingularWeave<K, N, T>: ImmutableWeave<K, N, T>
525where
526 K: Hash + Copy + Eq + Ord,
527 N: Node<K, T>,
528{
529 #[must_use]
531 fn active(&self) -> Option<K>;
532}
533
534pub trait ImmutableActivePathWeave<K, N, T>: ImmutableWeave<K, N, T>
536where
537 K: Hash + Copy + Eq + Ord,
538 N: Node<K, T>,
539{
540 type Active;
542
543 #[must_use]
545 fn active(&self) -> &Self::Active;
546}
547
548#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
549enum Step<A, B> {
550 Enter(A),
551 Exit(B),
552}
553
554fn topological_sort<'a, K, N, T, S>(
555 nodes: &'a HashMap<K, N, S>,
556 id: &'a K,
557 scratchpad: &mut Vec<K>,
558 identifiers: &mut Vec<K>,
559 identifier_set: &mut HashSet<K, S>,
560 identifier_map: &mut HashMap<K, usize, S>,
561) where
562 K: Hash + Copy + Eq + Ord + 'a,
563 N: Node<K, T> + 'a,
564 <N as Node<K, T>>::From: 'a,
565 <N as Node<K, T>>::To: 'a,
566 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator + ExactSizeIterator>,
567 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
568 S: BuildHasher + Default + Clone,
569{
570 scratchpad.push(*id);
571
572 while let Some(id) = scratchpad.pop() {
573 let node = &nodes[&id];
574
575 if identifier_set.contains(&id)
576 || identifier_map
577 .get(&id)
578 .copied()
579 .unwrap_or_else(|| node.from().into_iter().len())
580 != 0
581 {
582 continue;
583 }
584
585 identifiers.push(id);
586 identifier_set.insert(id);
587
588 for child in node.to().into_iter().rev().copied() {
589 let remaining = identifier_map
590 .entry(child)
591 .or_insert_with(|| nodes[&child].from().into_iter().len());
592 *remaining = remaining.strict_sub(1);
593
594 scratchpad.push(child);
595 }
596 }
597}
598
599fn topological_sort_subgraph<'a, K, N, T, S>(
600 nodes: &'a HashMap<K, N, S>,
601 filter: &impl Fn(&K) -> bool,
602 id: &'a K,
603 scratchpad: &mut Vec<K>,
604 identifiers: &mut Vec<K>,
605 identifier_set: &mut HashSet<K, S>,
606 identifier_map: &mut HashMap<K, usize, S>,
607) where
608 K: Hash + Copy + Eq + Ord + 'a,
609 N: Node<K, T> + 'a,
610 <N as Node<K, T>>::From: 'a,
611 <N as Node<K, T>>::To: 'a,
612 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
613 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
614 S: BuildHasher + Default + Clone,
615{
616 scratchpad.push(*id);
617
618 while let Some(id) = scratchpad.pop() {
619 let node = &nodes[&id];
620
621 if !filter(&id)
622 || identifier_set.contains(&id)
623 || identifier_map.get(&id).copied().unwrap_or_else(|| {
624 node.from()
625 .into_iter()
626 .filter(|&parent| filter(parent))
627 .count()
628 }) != 0
629 {
630 continue;
631 }
632
633 identifiers.push(id);
634 identifier_set.insert(id);
635
636 for child in node.to().into_iter().rev().copied() {
637 let remaining = identifier_map.entry(child).or_insert_with(|| {
638 nodes[&child]
639 .from()
640 .into_iter()
641 .filter(|&parent| filter(parent))
642 .count()
643 });
644 *remaining = remaining.strict_sub(1);
645
646 scratchpad.push(child);
647 }
648 }
649}
650
651fn detect_cycles<'a, K, N, T, S>(
652 nodes: &'a HashMap<K, N, S>,
653 roots: impl Iterator<Item = K>,
654 scratchpad: &mut Vec<Step<K, K>>,
655 scratchpad_map: &mut HashMap<K, bool, S>,
656) -> bool
657where
658 K: Hash + Copy + Eq + Ord + 'a,
659 N: Node<K, T> + 'a,
660 <N as Node<K, T>>::From: 'a,
661 <N as Node<K, T>>::To: 'a,
662 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
663 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator + ExactSizeIterator>,
664 S: BuildHasher + Default + Clone,
665{
666 for root in roots {
667 if scratchpad_map.contains_key(&root) {
668 continue;
669 }
670
671 scratchpad.push(Step::Enter(root));
672
673 while let Some(step) = scratchpad.pop() {
674 match step {
675 Step::Enter(id) => {
676 scratchpad.push(Step::Exit(id));
677
678 match scratchpad_map.entry(id) {
679 Entry::Occupied(entry) => {
680 if !entry.get() {
681 return true;
682 }
683 }
684 Entry::Vacant(entry) => {
685 entry.insert_entry(false);
686
687 scratchpad.extend(
688 nodes[&id].to().into_iter().rev().copied().map(Step::Enter),
689 );
690 }
691 }
692 }
693 Step::Exit(id) => {
694 scratchpad_map.insert(id, true);
695 }
696 }
697 }
698 }
699
700 scratchpad_map.len() != nodes.len()
701}
702
703fn shortest_path_to_ancestor<'a, K, N, T, S>(
704 nodes: &'a HashMap<K, N, S>,
705 id: &'a K,
706 target: &impl Fn(&'a N) -> bool,
707 scratchpad: &mut VecDeque<K>,
708 scratchpad_map: &mut HashMap<K, K, S>,
709 scratchpad_set: &mut HashSet<K, S>,
710 path: &mut Vec<K>,
711) where
712 K: Hash + Copy + Eq + Ord + 'a,
713 N: Node<K, T> + 'a,
714 <N as Node<K, T>>::From: 'a,
715 <N as Node<K, T>>::To: 'a,
716 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
717 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
718 S: BuildHasher + Default + Clone,
719{
720 scratchpad.push_front(*id);
721 scratchpad_set.insert(*id);
722
723 while let Some(id) = scratchpad.pop_back() {
724 let node = &nodes[&id];
725
726 if target(node) {
727 scratchpad.clear();
728
729 path.push(id);
730
731 while let Some(child) = scratchpad_map.remove(path.last().unwrap()) {
732 path.push(child);
733 }
734
735 return;
736 }
737
738 for parent in node.from().into_iter().copied() {
739 if scratchpad_set.insert(parent) {
740 scratchpad.push_front(parent);
741 scratchpad_map.insert(parent, id);
742 }
743 }
744 }
745}
746
747fn longest_candidate_path_to_root<'a, K, N, T, S>(
748 nodes: &'a HashMap<K, N, S>,
749 topological_order: &[K],
750 is_candidate: &impl Fn(&K) -> bool,
751 scratchpad_map: &mut HashMap<K, usize, S>,
752 reversed_path: &mut Vec<K>,
753) where
754 K: Hash + Copy + Eq + Ord + 'a,
755 N: Node<K, T> + 'a,
756 <N as Node<K, T>>::From: 'a,
757 <N as Node<K, T>>::To: 'a,
758 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
759 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
760 S: BuildHasher + Default + Clone,
761{
762 let mut longest_distance = None;
763
764 for id in topological_order {
765 if !is_candidate(id) {
766 continue;
767 }
768
769 let node = &nodes[id];
770 let distance = if node.from().into_iter().next().is_none() {
771 Some(0)
772 } else {
773 node.from()
774 .into_iter()
775 .filter_map(|parent| scratchpad_map.get(parent).copied())
776 .max()
777 .map(|l| l.strict_add(1))
778 };
779
780 if let Some(distance) = distance {
781 scratchpad_map.insert(*id, distance);
782
783 if longest_distance.is_none_or(|(value, _)| distance > value) {
784 longest_distance = Some((distance, id));
785 }
786 }
787 }
788
789 let mut current = longest_distance.map(|(_, id)| id);
790
791 while let Some(id) = current {
792 reversed_path.push(*id);
793
794 current = nodes[id]
795 .from()
796 .into_iter()
797 .filter(|id| scratchpad_map.contains_key(*id))
798 .min_by_key(|id| Reverse(scratchpad_map[*id]));
799 }
800}
801
802fn ancestor_subgraph<'a, K, N, T, S>(
803 nodes: &'a HashMap<K, N, S>,
804 id: K,
805 scratchpad: &mut Vec<K>,
806 identifiers: &mut HashSet<K, S>,
807) where
808 K: Hash + Copy + Eq + Ord + 'a,
809 N: Node<K, T>,
810 <N as Node<K, T>>::From: 'a,
811 <N as Node<K, T>>::To: 'a,
812 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
813 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
814 S: BuildHasher + Default + Clone,
815{
816 scratchpad.push(id);
817
818 while let Some(id) = scratchpad.pop() {
819 if identifiers.insert(id) {
820 scratchpad.extend(nodes[&id].from().into_iter().rev().copied());
821 }
822 }
823}
824
825fn descendant_subgraph<'a, K, N, T, S>(
826 nodes: &'a HashMap<K, N, S>,
827 id: K,
828 scratchpad: &mut Vec<K>,
829 identifiers: &mut HashSet<K, S>,
830) where
831 K: Hash + Copy + Eq + Ord + 'a,
832 N: Node<K, T>,
833 <N as Node<K, T>>::From: 'a,
834 <N as Node<K, T>>::To: 'a,
835 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
836 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
837 S: BuildHasher + Default + Clone,
838{
839 scratchpad.push(id);
840
841 while let Some(id) = scratchpad.pop() {
842 if identifiers.insert(id) {
843 scratchpad.extend(nodes[&id].to().into_iter().rev().copied());
844 }
845 }
846}