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>);
209 fn get_active_path(&mut self, output: &mut Vec<K>);
213 fn get_path_from(&mut self, id: &K, output: &mut Vec<K>);
217 fn insert(&mut self, node: N) -> bool;
221 fn set_active(&mut self, id: &K, value: bool) -> bool;
225 fn remove(&mut self, id: &K) -> Option<N>;
231 fn remove_tracked(&mut self, id: &K, on_removal: impl FnMut(N)) -> bool;
239 fn clear(&mut self);
243}
244
245pub trait MetadataWeave<K, N, T, M>: Weave<K, N, T>
251where
252 K: Hash + Copy + Eq + Ord,
253 N: Node<K, T>,
254{
255 #[must_use]
257 fn metadata(&self) -> &M;
258 fn metadata_mut<O>(&mut self, callback: impl FnOnce(&mut M) -> O) -> O;
264}
265
266pub trait BookmarkableWeave<K, N, T>: Weave<K, N, T>
268where
269 K: Hash + Copy + Eq + Ord,
270 N: Node<K, T>,
271{
272 type Bookmarks;
274
275 #[must_use]
277 fn bookmarks(&self) -> &Self::Bookmarks;
278 #[must_use]
280 fn contains_bookmark(&self, id: &K) -> bool;
281 fn set_bookmarked(&mut self, id: &K, value: bool) -> bool;
283}
284
285pub trait SortableWeave<K, N, T>: Weave<K, N, T>
291where
292 K: Hash + Copy + Eq + Ord,
293 N: Node<K, T>,
294{
295 fn sort_children_by(&mut self, id: &K, cmp: impl FnMut(&N, &N) -> Ordering) -> bool;
301 fn sort_children_by_id(&mut self, id: &K, cmp: impl FnMut(&K, &K) -> Ordering) -> bool;
307 fn sort_roots_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering);
313 fn sort_roots_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering);
319}
320
321pub trait SortableBookmarkableWeave<K, N, T>:
327 BookmarkableWeave<K, N, T> + SortableWeave<K, N, T>
328where
329 K: Hash + Copy + Eq + Ord,
330 N: Node<K, T>,
331{
332 fn sort_bookmarks_by(&mut self, cmp: impl FnMut(&N, &N) -> Ordering);
338 fn sort_bookmarks_by_id(&mut self, cmp: impl FnMut(&K, &K) -> Ordering);
344}
345
346pub trait ActiveSingularWeave<K, N, T>: Weave<K, N, T>
348where
349 K: Hash + Copy + Eq + Ord,
350 N: Node<K, T>,
351{
352 #[must_use]
354 fn active(&self) -> Option<K>;
355}
356
357pub trait ActivePathWeave<K, N, T>: Weave<K, N, T>
359where
360 K: Hash + Copy + Eq + Ord,
361 N: Node<K, T>,
362{
363 type Active;
365
366 #[must_use]
368 fn active(&self) -> &Self::Active;
369 fn set_active_path(&mut self, active: impl Iterator<Item = K>);
373}
374
375pub trait IndependentWeave<K, N, T>: Weave<K, N, T> + SemiIndependentWeave<K, N, T>
377where
378 K: Hash + Copy + Eq + Ord,
379 N: Node<K, T>,
380 T: IndependentContents,
381{
382 fn move_to(&mut self, id: &K, new_parents: &[K]) -> bool;
386}
387
388pub trait SemiIndependentWeave<K, N, T>: Weave<K, N, T>
394where
395 K: Hash + Copy + Eq + Ord,
396 N: Node<K, T>,
397 T: IndependentContents,
398{
399 #[must_use]
407 fn get_contents_mut<O>(&mut self, id: &K, callback: impl FnOnce(&mut T) -> O) -> Option<O>;
408}
409
410pub trait DiscreteWeave<K, N, T>: Weave<K, N, T>
416where
417 K: Hash + Copy + Eq + Ord,
418 N: Node<K, T>,
419 T: DiscreteContents,
420{
421 fn split(&mut self, id: &K, at: usize, new_id: K) -> bool;
431 fn merge_with_parent(&mut self, id: &K) -> Option<K>;
439}
440
441#[must_use]
443pub trait ImmutableWeave<K, N, T>
444where
445 K: Hash + Copy + Eq + Ord,
446 N: Node<K, T>,
447{
448 type Nodes;
450 type Roots;
452
453 #[must_use]
455 fn len(&self) -> usize;
456 #[must_use]
458 fn is_empty(&self) -> bool;
459 #[must_use]
461 fn nodes(&self) -> &Self::Nodes;
462 #[must_use]
464 fn roots(&self) -> &Self::Roots;
465 #[must_use]
467 fn contains(&self, id: &K) -> bool;
468 #[must_use]
472 fn contains_active(&self, id: &K) -> bool;
473 #[must_use]
475 fn get(&self, id: &K) -> Option<&N>;
476 #[must_use]
478 fn get_parents(&self, id: &K) -> Option<&N::From>;
479 #[must_use]
481 fn get_children(&self, id: &K) -> Option<&N::To>;
482 #[must_use]
484 fn get_contents(&self, id: &K) -> Option<&T>;
485 fn get_ordered_identifiers(&self, output: &mut Vec<K>);
487 fn get_ordered_identifiers_from(&self, id: &K, output: &mut Vec<K>);
491 fn get_active_path(&self, output: &mut Vec<K>);
495 fn get_path_from(&self, id: &K, output: &mut Vec<K>);
499}
500
501pub trait ImmutableMetadataWeave<K, N, T, M>: ImmutableWeave<K, N, T>
503where
504 K: Hash + Copy + Eq + Ord,
505 N: Node<K, T>,
506{
507 #[must_use]
509 fn metadata(&self) -> &M;
510}
511
512pub trait ImmutableBookmarkableWeave<K, N, T>: ImmutableWeave<K, N, T>
514where
515 K: Hash + Copy + Eq + Ord,
516 N: Node<K, T>,
517{
518 type Bookmarks;
520
521 #[must_use]
523 fn bookmarks(&self) -> &Self::Bookmarks;
524 #[must_use]
526 fn contains_bookmark(&self, id: &K) -> bool;
527}
528
529pub trait ImmutableActiveSingularWeave<K, N, T>: ImmutableWeave<K, N, T>
531where
532 K: Hash + Copy + Eq + Ord,
533 N: Node<K, T>,
534{
535 #[must_use]
537 fn active(&self) -> Option<K>;
538}
539
540pub trait ImmutableActivePathWeave<K, N, T>: ImmutableWeave<K, N, T>
542where
543 K: Hash + Copy + Eq + Ord,
544 N: Node<K, T>,
545{
546 type Active;
548
549 #[must_use]
551 fn active(&self) -> &Self::Active;
552}
553
554#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
555enum Step<A, B> {
556 Enter(A),
557 Exit(B),
558}
559
560fn topological_sort<'a, K, N, T, S>(
561 nodes: &'a HashMap<K, N, S>,
562 id: &'a K,
563 scratchpad: &mut Vec<K>,
564 identifiers: &mut Vec<K>,
565 identifier_set: &mut HashSet<K, S>,
566 identifier_map: &mut HashMap<K, usize, S>,
567) where
568 K: Hash + Copy + Eq + Ord + 'a,
569 N: Node<K, T> + 'a,
570 <N as Node<K, T>>::From: 'a,
571 <N as Node<K, T>>::To: 'a,
572 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator + ExactSizeIterator>,
573 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
574 S: BuildHasher + Default + Clone,
575{
576 scratchpad.push(*id);
577
578 while let Some(id) = scratchpad.pop() {
579 let node = &nodes[&id];
580
581 if identifier_set.contains(&id)
582 || identifier_map
583 .get(&id)
584 .copied()
585 .unwrap_or_else(|| node.from().into_iter().len())
586 != 0
587 {
588 continue;
589 }
590
591 identifiers.push(id);
592 identifier_set.insert(id);
593
594 for child in node.to().into_iter().rev().copied() {
595 let remaining = identifier_map
596 .entry(child)
597 .or_insert_with(|| nodes[&child].from().into_iter().len());
598 *remaining = remaining.strict_sub(1);
599
600 scratchpad.push(child);
601 }
602 }
603}
604
605fn topological_sort_subgraph<'a, K, N, T, S>(
606 nodes: &'a HashMap<K, N, S>,
607 filter: &impl Fn(&K) -> bool,
608 id: &'a K,
609 scratchpad: &mut Vec<K>,
610 identifiers: &mut Vec<K>,
611 identifier_set: &mut HashSet<K, S>,
612 identifier_map: &mut HashMap<K, usize, S>,
613) where
614 K: Hash + Copy + Eq + Ord + 'a,
615 N: Node<K, T> + 'a,
616 <N as Node<K, T>>::From: 'a,
617 <N as Node<K, T>>::To: 'a,
618 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
619 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
620 S: BuildHasher + Default + Clone,
621{
622 scratchpad.push(*id);
623
624 while let Some(id) = scratchpad.pop() {
625 let node = &nodes[&id];
626
627 if !filter(&id)
628 || identifier_set.contains(&id)
629 || identifier_map.get(&id).copied().unwrap_or_else(|| {
630 node.from()
631 .into_iter()
632 .filter(|&parent| filter(parent))
633 .count()
634 }) != 0
635 {
636 continue;
637 }
638
639 identifiers.push(id);
640 identifier_set.insert(id);
641
642 for child in node.to().into_iter().rev().copied() {
643 let remaining = identifier_map.entry(child).or_insert_with(|| {
644 nodes[&child]
645 .from()
646 .into_iter()
647 .filter(|&parent| filter(parent))
648 .count()
649 });
650 *remaining = remaining.strict_sub(1);
651
652 scratchpad.push(child);
653 }
654 }
655}
656
657fn detect_cycles<'a, K, N, T, S>(
658 nodes: &'a HashMap<K, N, S>,
659 roots: impl Iterator<Item = K>,
660 scratchpad: &mut Vec<Step<K, K>>,
661 scratchpad_map: &mut HashMap<K, bool, S>,
662) -> bool
663where
664 K: Hash + Copy + Eq + Ord + 'a,
665 N: Node<K, T> + 'a,
666 <N as Node<K, T>>::From: 'a,
667 <N as Node<K, T>>::To: 'a,
668 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
669 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator + ExactSizeIterator>,
670 S: BuildHasher + Default + Clone,
671{
672 for root in roots {
673 if scratchpad_map.contains_key(&root) {
674 continue;
675 }
676
677 scratchpad.push(Step::Enter(root));
678
679 while let Some(step) = scratchpad.pop() {
680 match step {
681 Step::Enter(id) => {
682 scratchpad.push(Step::Exit(id));
683
684 match scratchpad_map.entry(id) {
685 Entry::Occupied(entry) => {
686 if !entry.get() {
687 return true;
688 }
689 }
690 Entry::Vacant(entry) => {
691 entry.insert_entry(false);
692
693 scratchpad.extend(
694 nodes[&id].to().into_iter().rev().copied().map(Step::Enter),
695 );
696 }
697 }
698 }
699 Step::Exit(id) => {
700 scratchpad_map.insert(id, true);
701 }
702 }
703 }
704 }
705
706 scratchpad_map.len() != nodes.len()
707}
708
709fn shortest_path_to_ancestor<'a, K, N, T, S>(
710 nodes: &'a HashMap<K, N, S>,
711 id: &'a K,
712 target: &impl Fn(&'a N) -> bool,
713 scratchpad: &mut VecDeque<K>,
714 scratchpad_map: &mut HashMap<K, K, S>,
715 scratchpad_set: &mut HashSet<K, S>,
716 path: &mut Vec<K>,
717) where
718 K: Hash + Copy + Eq + Ord + 'a,
719 N: Node<K, T> + 'a,
720 <N as Node<K, T>>::From: 'a,
721 <N as Node<K, T>>::To: 'a,
722 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
723 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
724 S: BuildHasher + Default + Clone,
725{
726 scratchpad.push_front(*id);
727 scratchpad_set.insert(*id);
728
729 while let Some(id) = scratchpad.pop_back() {
730 let node = &nodes[&id];
731
732 if target(node) {
733 scratchpad.clear();
734
735 path.push(id);
736
737 while let Some(child) = scratchpad_map.remove(path.last().unwrap()) {
738 path.push(child);
739 }
740
741 return;
742 }
743
744 for parent in node.from().into_iter().copied() {
745 if scratchpad_set.insert(parent) {
746 scratchpad.push_front(parent);
747 scratchpad_map.insert(parent, id);
748 }
749 }
750 }
751}
752
753fn longest_candidate_path_to_root<'a, K, N, T, S>(
754 nodes: &'a HashMap<K, N, S>,
755 topological_order: &[K],
756 is_candidate: &impl Fn(&K) -> bool,
757 scratchpad_map: &mut HashMap<K, usize, S>,
758 reversed_path: &mut Vec<K>,
759) where
760 K: Hash + Copy + Eq + Ord + 'a,
761 N: Node<K, T> + 'a,
762 <N as Node<K, T>>::From: 'a,
763 <N as Node<K, T>>::To: 'a,
764 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
765 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
766 S: BuildHasher + Default + Clone,
767{
768 let mut longest_distance = None;
769
770 for id in topological_order {
771 if !is_candidate(id) {
772 continue;
773 }
774
775 let node = &nodes[id];
776 let distance = if node.from().into_iter().next().is_none() {
777 Some(0)
778 } else {
779 node.from()
780 .into_iter()
781 .filter_map(|parent| scratchpad_map.get(parent).copied())
782 .max()
783 .map(|l| l.strict_add(1))
784 };
785
786 if let Some(distance) = distance {
787 scratchpad_map.insert(*id, distance);
788
789 if longest_distance.is_none_or(|(value, _)| distance > value) {
790 longest_distance = Some((distance, id));
791 }
792 }
793 }
794
795 let mut current = longest_distance.map(|(_, id)| id);
796
797 while let Some(id) = current {
798 reversed_path.push(*id);
799
800 current = nodes[id]
801 .from()
802 .into_iter()
803 .filter(|id| scratchpad_map.contains_key(*id))
804 .min_by_key(|id| Reverse(scratchpad_map[*id]));
805 }
806}
807
808fn ancestor_subgraph<'a, K, N, T, S>(
809 nodes: &'a HashMap<K, N, S>,
810 id: K,
811 scratchpad: &mut Vec<K>,
812 identifiers: &mut HashSet<K, S>,
813) where
814 K: Hash + Copy + Eq + Ord + 'a,
815 N: Node<K, T>,
816 <N as Node<K, T>>::From: 'a,
817 <N as Node<K, T>>::To: 'a,
818 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
819 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
820 S: BuildHasher + Default + Clone,
821{
822 scratchpad.push(id);
823
824 while let Some(id) = scratchpad.pop() {
825 if identifiers.insert(id) {
826 scratchpad.extend(nodes[&id].from().into_iter().rev().copied());
827 }
828 }
829}
830
831fn descendant_subgraph<'a, K, N, T, S>(
832 nodes: &'a HashMap<K, N, S>,
833 id: K,
834 scratchpad: &mut Vec<K>,
835 identifiers: &mut HashSet<K, S>,
836) where
837 K: Hash + Copy + Eq + Ord + 'a,
838 N: Node<K, T>,
839 <N as Node<K, T>>::From: 'a,
840 <N as Node<K, T>>::To: 'a,
841 &'a N::From: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
842 &'a N::To: IntoIterator<Item = &'a K, IntoIter: DoubleEndedIterator>,
843 S: BuildHasher + Default + Clone,
844{
845 scratchpad.push(id);
846
847 while let Some(id) = scratchpad.pop() {
848 if identifiers.insert(id) {
849 scratchpad.extend(nodes[&id].to().into_iter().rev().copied());
850 }
851 }
852}