rsdiff_graphs/
graph.rs

1/*
2    Appellation: graph <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5
6use crate::{DefaultIx, EdgeIndex, NodeIndex};
7use core::marker::PhantomData;
8
9pub trait GraphEntry {
10    type Idx;
11    type Weight;
12}
13
14pub trait ComputeGraph {
15    type Edge: GraphEntry;
16    type Node: GraphEntry;
17
18    fn add_node(
19        &mut self,
20        node: <Self::Node as GraphEntry>::Weight,
21    ) -> <Self::Node as GraphEntry>::Idx;
22
23    fn add_edge(
24        &mut self,
25        src: <Self::Node as GraphEntry>::Idx,
26        target: <Self::Node as GraphEntry>::Idx,
27        weight: <Self::Edge as GraphEntry>::Weight,
28    ) -> <Self::Edge as GraphEntry>::Idx;
29
30    fn clear(&mut self);
31}
32
33pub struct Edge<Idx = DefaultIx, W = ()> {
34    pub link: Link<Idx>,
35    pub weight: Option<W>,
36    _idx: PhantomData<EdgeIndex<Idx>>,
37}
38
39impl<Idx, W> Edge<Idx, W> {
40    pub fn new(src: NodeIndex<Idx>, target: NodeIndex<Idx>, weight: Option<W>) -> Self {
41        Self {
42            link: Link::new(src, target),
43            weight,
44            _idx: PhantomData,
45        }
46    }
47
48    pub fn from_link(link: Link<Idx>) -> Self {
49        Self {
50            link,
51            weight: None,
52            _idx: PhantomData,
53        }
54    }
55
56    pub fn unweighted(src: NodeIndex<Idx>, target: NodeIndex<Idx>) -> Self {
57        Self::new(src, target, None)
58    }
59
60    pub fn weighted(src: NodeIndex<Idx>, target: NodeIndex<Idx>, weight: W) -> Self {
61        Self::new(src, target, Some(weight))
62    }
63
64    pub fn with_weight(self, weight: W) -> Self {
65        Self {
66            weight: Some(weight),
67            ..self
68        }
69    }
70
71    pub fn is_unweighted(&self) -> bool {
72        self.weight.is_none()
73    }
74
75    pub fn is_weighted(&self) -> bool {
76        self.weight.is_some()
77    }
78
79    pub fn weight(&self) -> Option<&W> {
80        self.weight.as_ref()
81    }
82
83    pub fn weight_mut(&mut self) -> Option<&mut W> {
84        self.weight.as_mut()
85    }
86}
87
88impl<Idx, W> GraphEntry for Edge<Idx, W> {
89    type Idx = EdgeIndex<Idx>;
90    type Weight = W;
91}
92
93pub struct Link<Idx = DefaultIx> {
94    pub src: NodeIndex<Idx>,
95    pub target: NodeIndex<Idx>,
96}
97
98impl<Idx> Link<Idx> {
99    pub fn new(src: NodeIndex<Idx>, target: NodeIndex<Idx>) -> Self {
100        Self { src, target }
101    }
102}
103
104pub trait GraphEdge {
105    type Idx;
106
107    fn src(&self) -> NodeIndex<Self::Idx>;
108
109    fn target(&self) -> NodeIndex<Self::Idx>;
110}
111
112impl<Idx> GraphEdge for Link<Idx>
113where
114    Idx: Copy,
115{
116    type Idx = Idx;
117
118    fn src(&self) -> NodeIndex<Idx> {
119        self.src
120    }
121
122    fn target(&self) -> NodeIndex<Idx> {
123        self.target
124    }
125}
126
127impl<Idx, W> GraphEdge for Edge<Idx, W>
128where
129    Idx: Copy,
130{
131    type Idx = Idx;
132
133    fn src(&self) -> NodeIndex<Idx> {
134        self.link.src
135    }
136
137    fn target(&self) -> NodeIndex<Idx> {
138        self.link.target
139    }
140}