1use std::any::Any;
6use std::fmt::{Debug, Display};
8use std::hash::Hash;
9use std::iter::FusedIterator;
10
11use serde::{Deserialize, Serialize};
12
13use ordermap::{OrderMap, OrderSet};
14
15use uuid::Uuid;
16
17use crate::cate_arena::*;
18use crate::id_distributer::IdDistributer;
20
21pub mod debug;
22pub mod display;
23pub mod serialize;
24pub mod macro_traits;
26pub use macro_traits::*;
27mod transaction;
31pub use transaction::Transaction;
32
33pub mod check;
34use check::*;
35
36pub mod macros;
37pub use ttgraph_macros::*;
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
43pub struct NodeIndex(pub usize);
44
45impl NodeIndex {
46 pub fn empty() -> NodeIndex {
54 NodeIndex(0)
55 }
56
57 pub fn is_empty(&self) -> bool {
65 self.0 == 0
66 }
67}
68
69impl Default for NodeIndex {
70 fn default() -> Self {
71 Self::empty()
72 }
73}
74
75impl Display for NodeIndex {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 if self.is_empty() {
84 write!(f, "empty")
85 } else {
86 write!(f, "{}", self.0)
87 }
88 }
89}
90
91pub struct Graph<NodeT, Arena = <NodeT as NodeEnum>::GenArena>
130where
131 NodeT: NodeEnum,
132 Arena: CateArena<V = NodeT, D = NodeT::Discriminant>,
133{
134 ctx_id: Uuid,
135 nodes: Arena,
136 back_links: OrderMap<NodeIndex, OrderSet<(NodeIndex, NodeT::SourceEnum)>>,
137}
138
139impl<NodeT, Arena> Graph<NodeT, Arena>
140where
141 NodeT: NodeEnum,
142 Arena: CateArena<V = NodeT, D = NodeT::Discriminant>,
143{
144 pub fn new(context: &Context) -> Self {
146 Graph {
147 ctx_id: context.id,
148 nodes: Arena::new(context.node_dist.clone()),
149 back_links: OrderMap::new(),
150 }
151 }
152
153 pub fn get(&self, idx: NodeIndex) -> Option<&NodeT> {
192 self.nodes.get(idx)
193 }
194
195 pub fn iter(&self) -> Arena::Iter<'_> {
242 self.nodes.iter()
243 }
244
245 pub fn iter_type<'a>(
289 &'a self, d: NodeT::Discriminant,
290 ) -> NodeIterator<'a, NodeT, ordermap::map::Iter<'a, usize, NodeT>> {
291 NodeIterator { iter: self.nodes.get_container(d).iter() }
292 }
293
294 pub fn iter_group(&self, name: &'static str) -> impl Iterator<Item = (NodeIndex, &NodeT)> {
351 self.iter().filter(move |(_, n)| n.in_group(name))
352 }
353
354 pub fn len(&self) -> usize {
383 self.nodes.len()
384 }
385
386 pub fn is_empty(&self) -> bool {
388 self.len() == 0
389 }
390
391 pub fn commit(&mut self, t: Transaction<NodeT, Arena>) -> Result<(), CommitError<NodeT>> {
439 let (lcr, mut err) = self.do_commit(t);
440 self.check_link_type(&lcr, &mut err);
441 if err.is_empty() {
442 Ok(())
443 } else {
444 Err(err)
445 }
446 }
447
448 #[cfg(feature = "debug")]
452 pub fn commit_checked(
453 &mut self, t: Transaction<NodeT, Arena>, checks: &GraphCheck<NodeT>,
454 ) -> Result<(), CommitError<NodeT>> {
455 let (lcr, mut err) = self.do_commit(t);
456 self.check_link_type(&lcr, &mut err);
457 self.check_change(&lcr, checks, &mut err);
458 if err.is_empty() {
459 Ok(())
460 } else {
461 Err(err)
462 }
463 }
464
465 pub fn switch_context(self, new_ctx: &Context) -> Result<Self, CommitError<NodeT>> {
475 let mut new_nodes = Arena::new(new_ctx.node_dist.clone());
476 let mut id_map = OrderMap::new();
477
478 for (id, x) in self.nodes.into_iter() {
479 let new_idx = new_nodes.insert(x);
480 id_map.insert(id, new_idx);
481 }
482
483 for (id, new_id) in &id_map {
484 for (y, s) in &self.back_links[id] {
485 new_nodes.get_mut(id_map[y]).unwrap().modify_link(*s, *id, *new_id);
486 }
487 }
488
489 let mut result = Graph {
490 ctx_id: new_ctx.id,
491 nodes: Arena::new(new_ctx.node_dist.clone()),
492 back_links: OrderMap::new(),
493 };
494
495 let mut lcr = LinkChangeRecorder::default();
496 let mut err = CommitError::default();
497 result.merge_nodes(new_nodes, &mut lcr);
498 result.apply_bidirectional_links(&lcr, &mut err);
499 result.check_link_type(&lcr, &mut err);
500 if err.is_empty() {
501 Ok(result)
502 } else {
503 Err(err)
504 }
505 }
506
507 #[cfg(feature = "debug")]
509 pub fn check_integrity(&self) {
510 for (_, node) in self.nodes.iter() {
511 for (y, _) in node.iter_sources() {
512 debug_assert!(self.get(y).is_some(), "Found external link, integrity check failed!");
513 }
514 }
515 }
516
517 #[cfg(not(feature = "debug"))]
518 pub fn check_integrity(&self) {}
519
520 #[cfg(feature = "debug")]
522 #[doc(hidden)]
523 pub fn check_backlinks(&self) {
524 let mut back_links: OrderMap<NodeIndex, OrderSet<(NodeIndex, NodeT::SourceEnum)>> = OrderMap::new();
525 for (x, n) in self.nodes.iter() {
526 back_links.entry(x).or_default();
527 for (y, s) in n.iter_sources() {
528 back_links.entry(y).or_default().insert((x, s));
529 let links = self.back_links.get(&y).unwrap_or_else(|| panic!("Node {} have no backlink!", x.0));
530 debug_assert!(links.contains(&(x, s)));
531 }
532 }
533 for (k, v) in back_links.iter() {
534 let Some(v2) = self.back_links.get(k) else { panic!("Key {:?} not in back_links {:?}", k, self.back_links) };
535 if !v2.set_eq(v) {
536 panic!("Backlink not equal {:?} expect {:?}", v2, v);
537 }
538 }
539 }
540
541 #[cfg(not(feature = "debug"))]
542 pub fn check_backlinks(&self) {}
543
544 fn do_commit(&mut self, t: Transaction<NodeT, Arena>) -> (LinkChangeRecorder<NodeT>, CommitError<NodeT>) {
545 debug_assert!(t.ctx_id == self.ctx_id, "The transaction and the graph are from different context!");
546 debug_assert!(t.alloc_nodes.is_empty(), "There are unfilled allocated nodes");
547
548 let mut lcr = LinkChangeRecorder::default();
549 let mut err = CommitError::default();
550
551 self.redirect_links_vec(t.redirect_links_vec, &mut lcr);
552 self.merge_nodes(t.inc_nodes, &mut lcr);
553 for (i, f) in t.mut_nodes {
554 self.modify_node(i, f, &mut lcr);
555 }
556 for (i, f) in t.update_nodes {
557 self.update_node(i, f, &mut lcr);
558 }
559 self.redirect_links_vec(t.redirect_all_links_vec, &mut lcr);
560 for n in &t.dec_nodes {
561 self.remove_node(*n, &mut lcr);
562 }
563
564 self.apply_bidirectional_links(&lcr, &mut err);
565 (lcr, err)
566 }
567
568 fn merge_nodes(&mut self, nodes: Arena, lcr: &mut LinkChangeRecorder<NodeT>) {
569 for (x, n) in nodes.iter() {
570 self.add_back_links(x, n);
571 for (y, s) in n.iter_sources() {
572 lcr.add_link(x, y, NodeT::to_link_mirror_enum(s));
573 }
574 }
575
576 self.nodes.merge(nodes);
577 }
578
579 fn remove_node(&mut self, x: NodeIndex, lcr: &mut LinkChangeRecorder<NodeT>) {
580 let n = self.nodes.remove(x).expect("Remove a non-existing node!");
581 for (y, s) in n.iter_sources() {
582 lcr.remove_link(x, y, NodeT::to_link_mirror_enum(s));
583 }
584 self.remove_back_links(x, &n);
585 for (y, s) in self.back_links.swap_remove(&x).unwrap() {
586 self.nodes.get_mut(y).unwrap().modify_link(s, x, NodeIndex::empty());
587 lcr.remove_link(y, x, NodeT::to_link_mirror_enum(s));
588 }
589 }
590
591 fn modify_node<F>(&mut self, x: NodeIndex, f: F, lcr: &mut LinkChangeRecorder<NodeT>)
592 where
593 F: FnOnce(&mut NodeT),
594 {
595 for (y, s) in self.nodes.get(x).unwrap().iter_sources() {
596 self.back_links.get_mut(&y).unwrap().swap_remove(&(x, s));
597 lcr.remove_link(x, y, NodeT::to_link_mirror_enum(s));
598 }
599
600 f(self.nodes.get_mut(x).unwrap());
601
602 for (y, s) in self.nodes.get(x).unwrap().iter_sources() {
603 self.back_links.get_mut(&y).unwrap().insert((x, s));
604 lcr.add_link(x, y, NodeT::to_link_mirror_enum(s));
605 }
606 }
607
608 fn update_node<F>(&mut self, x: NodeIndex, f: F, lcr: &mut LinkChangeRecorder<NodeT>)
609 where
610 F: FnOnce(NodeT) -> NodeT,
611 {
612 for (y, s) in self.nodes.get(x).unwrap().iter_sources() {
613 self.back_links.get_mut(&y).unwrap().swap_remove(&(x, s));
614 lcr.remove_link(x, y, NodeT::to_link_mirror_enum(s));
615 }
616
617 self.nodes.update_with(x, f);
618
619 for (y, s) in self.nodes.get(x).unwrap().iter_sources() {
620 self.back_links.get_mut(&y).unwrap().insert((x, s));
621 lcr.add_link(x, y, NodeT::to_link_mirror_enum(s));
622 }
623 }
624
625 fn redirect_links(&mut self, old_node: NodeIndex, new_node: NodeIndex, lcr: &mut LinkChangeRecorder<NodeT>) {
626 let old_link = self.back_links.swap_remove(&old_node).unwrap();
627 self.back_links.insert(old_node, OrderSet::new());
628
629 let new_link = self.back_links.entry(new_node).or_default();
630 for (y, s) in old_link {
631 new_link.insert((y, s));
632 let result = self.nodes.get_mut(y).unwrap().modify_link(s, old_node, new_node);
633 if result.added {
636 lcr.add_link(y, new_node, NodeT::to_link_mirror_enum(s));
637 }
638 if result.removed {
639 lcr.remove_link(y, old_node, NodeT::to_link_mirror_enum(s));
640 }
641 }
642 }
643
644 fn redirect_links_vec(&mut self, replacements: Vec<(NodeIndex, NodeIndex)>, lcr: &mut LinkChangeRecorder<NodeT>) {
645 let mut fa = OrderMap::new();
646
647 for (old, new) in &replacements {
648 fa.entry(*old).or_insert(*old);
649 fa.entry(*new).or_insert(*new);
650 }
651
652 for (old, new) in &replacements {
653 let mut x = *new;
654 while fa[&x] != x {
655 x = fa[&x];
656 }
657 assert!(x != *old, "Loop redirection detected!");
658 *fa.get_mut(old).unwrap() = x;
659 }
660
661 for (old, new) in &replacements {
662 let mut x = *new;
663 let mut y = fa[&x];
664 while x != y {
665 x = y;
666 y = fa[&y];
667 }
668
669 self.redirect_links(*old, x, lcr);
670
671 x = *new;
672 while fa[&x] != y {
673 let z = fa[&x];
674 *fa.get_mut(&x).unwrap() = y;
675 x = z;
676 }
677 }
678 }
679
680 fn apply_bidirectional_links(&mut self, lcr: &LinkChangeRecorder<NodeT>, err: &mut CommitError<NodeT>) {
681 for &(x, y, l) in &lcr.removes {
682 if !self.nodes.contains(x) || !self.nodes.contains(y) {
683 continue;
684 }
685
686 let bds = self.nodes.get(x).unwrap().get_bidiretional_link_mirrors_of(l);
687 let bds = self.nodes.get(y).unwrap().match_bd_link_group(bds);
688 for link in bds {
689 if self.nodes.get_mut(y).unwrap().remove_link(link, x) {
690 self.remove_back_link(y, x, NodeT::to_source_enum(link));
691 }
692 }
693 }
694
695 for &(x, y, l) in &lcr.adds {
696 if !self.nodes.contains(x) || !self.nodes.contains(y) {
697 continue;
698 }
699
700 let bds = self.nodes.get(x).unwrap().get_bidiretional_link_mirrors_of(l);
702 let bds = self.nodes.get(y).unwrap().match_bd_link_group(bds);
704 if bds.is_empty() {
705 continue;
706 }
707
708 let node = self.nodes.get(y).unwrap();
709 let found = bds.iter().any(|link| node.contains_link(*link, x));
710
711 if !found {
712 if bds.len() == 1 {
713 let link = *bds.first().unwrap();
714 match self.nodes.get_mut(y).unwrap().add_link(link, x) {
715 Ok(added) => {
716 if added {
717 self.add_back_link(y, x, NodeT::to_source_enum(link));
718 }
719 },
720 Err(old) => err.link_multiconnect.push(LinkMultiConnectError { x: y, link, old, new: x }),
721 }
722 } else {
723 err.bdlink_multichoices.push(BDLinkMultiChoiceError { x, link: l, y, choices: bds })
724 }
725 }
726 }
727 }
728
729 fn add_back_link(&mut self, x: NodeIndex, y: NodeIndex, src: NodeT::SourceEnum) {
730 self.back_links.entry(y).or_default().insert((x, src));
731 }
732
733 fn add_back_links(&mut self, x: NodeIndex, n: &NodeT) {
734 self.back_links.entry(x).or_default();
735 for (y, s) in n.iter_sources() {
736 self.back_links.entry(y).or_default().insert((x, s));
737 }
738 }
739
740 fn remove_back_link(&mut self, x: NodeIndex, y: NodeIndex, src: NodeT::SourceEnum) {
741 self.back_links.get_mut(&y).unwrap().swap_remove(&(x, src));
742 }
743
744 fn remove_back_links(&mut self, x: NodeIndex, n: &NodeT) {
745 for (y, s) in n.iter_sources() {
746 self.back_links.get_mut(&y).unwrap().swap_remove(&(x, s));
747 }
748 }
749
750 fn check_link_type(&self, lcr: &LinkChangeRecorder<NodeT>, err: &mut CommitError<NodeT>) {
751 for (_, y, l) in &lcr.adds {
752 if let Some(node) = self.nodes.get(*y) {
753 if let Result::Err(lerr) = NodeT::check_link_type(node.discriminant(), *l) {
754 err.link_type_errors.push(lerr);
755 }
757 }
758 }
759 }
760
761 #[cfg(feature = "debug")]
762 fn check_change(&self, lcr: &LinkChangeRecorder<NodeT>, checks: &GraphCheck<NodeT>, err: &mut CommitError<NodeT>) {
763 let mut changed_nodes = OrderSet::new();
764 for (x, _, _) in lcr.adds.iter().chain(lcr.removes.iter()) {
765 changed_nodes.insert(*x);
766 }
767 for (name, check_func) in &checks.node_checks {
768 for x in &changed_nodes {
769 if check_func(*x, self.get(*x).unwrap()).is_err() {
770 err.custom_node_check.push((name.to_string(), *x));
771 }
773 }
774 }
775 for (name, check_func) in &checks.link_add_checks {
776 for (x, y, _) in &lcr.adds {
777 if check_func(*x, *y, self.get(*x).unwrap(), self.get(*y)).is_err() {
778 err.custom_link_add_check.push((name.to_string(), *x, *y));
779 }
781 }
782 }
783 for (name, check_func) in &checks.link_remove_checks {
784 for (x, y, _) in &lcr.adds {
785 if check_func(*x, *y, self.get(*x).unwrap(), self.get(*y)).is_err() {
786 err.custom_link_remove_check.push((name.to_string(), *x, *y));
787 }
789 }
790 }
791 }
792
793 pub(crate) fn do_deserialize(ctx: &Context, nodes: Vec<(NodeIndex, NodeT)>) -> Self {
794 let arena = Arena::new_from_iter(ctx.node_dist.clone(), nodes);
795 let mut lcr = LinkChangeRecorder::default();
796 let mut err = CommitError::default();
797 let mut graph = Self::new(ctx);
798 graph.merge_nodes(arena, &mut lcr);
799 graph.apply_bidirectional_links(&lcr, &mut err);
800 graph
801 }
802}
803
804struct LinkChangeRecorder<NodeT: NodeEnum> {
805 adds: OrderSet<(NodeIndex, NodeIndex, NodeT::LinkMirrorEnum)>,
806 removes: OrderSet<(NodeIndex, NodeIndex, NodeT::LinkMirrorEnum)>,
807}
808impl<NodeT: NodeEnum> LinkChangeRecorder<NodeT> {
809 #[cfg(feature = "debug")]
810 fn add_link(&mut self, x: NodeIndex, y: NodeIndex, l: NodeT::LinkMirrorEnum) {
811 if y.is_empty() {
812 return;
813 }
814 if self.removes.contains(&(x, y, l)) {
815 self.removes.swap_remove(&(x, y, l));
816 } else {
817 self.adds.insert((x, y, l));
818 }
819 }
820
821 #[cfg(not(feature = "debug"))]
822 fn add_link(&mut self, x: NodeIndex, y: NodeIndex, l: NodeT::LinkMirrorEnum) {}
823
824 #[cfg(feature = "debug")]
825 fn remove_link(&mut self, x: NodeIndex, y: NodeIndex, l: NodeT::LinkMirrorEnum) {
826 if y.is_empty() {
827 return;
828 }
829 if self.adds.contains(&(x, y, l)) {
830 self.adds.swap_remove(&(x, y, l));
831 } else {
832 self.removes.insert((x, y, l));
833 }
834 }
835
836 #[cfg(not(feature = "debug"))]
837 fn remove_link(&mut self, x: NodeIndex, y: NodeIndex, l: NodeT::LinkMirrorEnum) {}
838}
839impl<NodeT: NodeEnum> Default for LinkChangeRecorder<NodeT> {
840 fn default() -> Self {
841 LinkChangeRecorder {
842 adds: OrderSet::default(),
843 removes: OrderSet::default(),
844 }
845 }
846}
847
848impl<T: NodeEnum, A: CateArena<V = T, D = T::Discriminant>> IntoIterator for Graph<T, A> {
849 type IntoIter = A::IntoIter;
850 type Item = (NodeIndex, T);
851
852 fn into_iter(self) -> Self::IntoIter {
853 self.nodes.into_iter()
854 }
855}
856
857impl<'a, T: NodeEnum + 'static, A: CateArena<V = T, D = T::Discriminant>> IntoIterator for &'a Graph<T, A> {
858 type IntoIter = A::Iter<'a>;
859 type Item = (NodeIndex, &'a T);
860
861 fn into_iter(self) -> Self::IntoIter {
862 self.iter()
863 }
864}
865
866pub struct NodeIterator<'a, V, I>
867where
868 V: NodeEnum + 'static,
869 I: Iterator<Item = (&'a usize, &'a V)> + ExactSizeIterator + FusedIterator,
870{
871 iter: I,
872}
873impl<'a, V, I> Iterator for NodeIterator<'a, V, I>
874where
875 V: NodeEnum + 'static,
876 I: Iterator<Item = (&'a usize, &'a V)> + ExactSizeIterator + FusedIterator,
877{
878 type Item = (NodeIndex, &'a V);
879 fn next(&mut self) -> Option<Self::Item> {
880 self.iter.next().map(|(k, v)| (NodeIndex(*k), v))
881 }
882 fn size_hint(&self) -> (usize, Option<usize>) {
883 self.iter.size_hint()
884 }
885}
886impl<'a, V, I> ExactSizeIterator for NodeIterator<'a, V, I>
887where
888 V: NodeEnum + 'static,
889 I: Iterator<Item = (&'a usize, &'a V)> + ExactSizeIterator + FusedIterator,
890{
891}
892impl<'a, V, I> FusedIterator for NodeIterator<'a, V, I>
893where
894 V: NodeEnum + 'static,
895 I: Iterator<Item = (&'a usize, &'a V)> + ExactSizeIterator + FusedIterator,
896{
897}
898
899pub type MutFunc<'a, T> = Box<dyn FnOnce(&mut T) + 'a>;
901pub type UpdateFunc<'a, T> = Box<dyn FnOnce(T) -> T + 'a>;
903
904#[derive(Debug, Clone, Default)]
907pub struct Context {
908 id: Uuid,
909 node_dist: IdDistributer,
910}
911impl Context {
912 pub fn new() -> Context {
914 Context {
915 id: Uuid::new_v4(),
916 node_dist: IdDistributer::new(),
917 }
918 }
919
920 pub(crate) fn from_id(id: Uuid, cnt: usize) -> Self {
921 Context {
922 id,
923 node_dist: IdDistributer::from_count(cnt),
924 }
925 }
926}
927
928#[derive(Debug, Clone)]
938pub struct LinkTypeError<NodeT: NodeEnum + ?Sized> {
939 pub link: NodeT::LoGMirrorEnum,
940 pub expect: &'static [NodeT::Discriminant],
941 pub found: NodeT::Discriminant,
942}
943
944pub type LinkTypeCheckResult<NodeT> = Result<(), LinkTypeError<NodeT>>;
945
946#[derive(Debug, Clone)]
949pub struct LinkMultiConnectError<NodeT: NodeEnum + ?Sized> {
950 pub x: NodeIndex,
951 pub link: NodeT::LinkMirrorEnum,
952 pub old: NodeIndex,
953 pub new: NodeIndex,
954}
955
956#[derive(Debug, Clone)]
960pub struct BDLinkMultiChoiceError<NodeT: NodeEnum + ?Sized> {
961 pub x: NodeIndex,
962 pub link: NodeT::LinkMirrorEnum,
963 pub y: NodeIndex,
964 pub choices: Vec<NodeT::LinkMirrorEnum>,
965}
966
967#[derive(Debug, Clone)]
968pub struct CommitError<NodeT: NodeEnum + ?Sized> {
969 pub link_multiconnect: Vec<LinkMultiConnectError<NodeT>>,
970 pub link_type_errors: Vec<LinkTypeError<NodeT>>,
971 pub bdlink_multichoices: Vec<BDLinkMultiChoiceError<NodeT>>,
972 pub custom_node_check: Vec<(String, NodeIndex)>,
973 pub custom_link_add_check: Vec<(String, NodeIndex, NodeIndex)>,
974 pub custom_link_remove_check: Vec<(String, NodeIndex, NodeIndex)>,
975}
976
977impl<NodeT: NodeEnum + ?Sized> CommitError<NodeT> {
978 pub fn is_empty(&self) -> bool {
979 self.link_multiconnect.is_empty()
980 && self.link_type_errors.is_empty()
981 && self.bdlink_multichoices.is_empty()
982 && self.custom_node_check.is_empty()
983 && self.custom_link_add_check.is_empty()
984 && self.custom_link_remove_check.is_empty()
985 }
986}
987
988impl<NodeT: NodeEnum + ?Sized> Default for CommitError<NodeT> {
989 fn default() -> Self {
990 Self {
991 link_multiconnect: Vec::new(),
992 link_type_errors: Vec::new(),
993 bdlink_multichoices: Vec::new(),
994 custom_node_check: Vec::new(),
995 custom_link_add_check: Vec::new(),
996 custom_link_remove_check: Vec::new(),
997 }
998 }
999}