1use crate::ancestors::node_leaps;
12use crate::graph::{
13 Graph, GraphReadError, GraphWriteError, LabelledGraph, Leap, LeapCounts,
14 LeapType, MergeRankedGraph, MutableGraph, NodeID, Parents, Rank,
15 RankedGraph, Revision, SizedGraph, StableOrderGraph, NULL_ID,
16 NULL_REVISION,
17};
18use crate::testing::ordering::NodeComparator;
19use std::cmp::Ordering;
20use std::collections::HashMap;
21use std::marker::PhantomData;
22use std::option::Option::Some;
23use std::result::Result;
24use std::result::Result::{Err, Ok};
25use std::vec::Vec;
26
27#[derive(Clone, Debug, PartialEq, Eq)]
31struct Node {
32 rev: Revision,
33 id: NodeID,
34 parents: Parents,
35 rank: Rank,
36 merge_rank: Rank,
37 leap_counts: LeapCounts,
38 leaps: Vec<Leap>,
39}
40
41#[derive(Clone, Debug)]
43pub struct InMemoryGraph<C: NodeComparator> {
44 _node_comparator: PhantomData<C>,
45 _empty_leap_vec: Vec<Leap>,
46 nodes: Vec<Node>,
48 rev_map: HashMap<NodeID, Revision>,
49}
50
51impl<C: NodeComparator> InMemoryGraph<C> {
52 pub fn new() -> Self {
53 let mut graph = Self {
54 _node_comparator: PhantomData,
55 _empty_leap_vec: Vec::with_capacity(0),
56 nodes: Vec::new(),
57 rev_map: HashMap::new(),
58 };
59 graph.rev_map.insert(NULL_ID, NULL_REVISION);
60 graph
61 }
62
63 fn get_by_revision(&self, rev: Revision) -> Result<Node, GraphReadError> {
64 match self.nodes.get(rev as usize) {
65 Some(node) => Ok(node.clone()),
66 None => Err(GraphReadError::InvalidKey),
67 }
68 }
69}
70
71impl<C: NodeComparator> Graph for InMemoryGraph<C> {
72 fn parents(&self, rev: Revision) -> Result<Parents, GraphReadError> {
73 Ok(match rev {
74 NULL_REVISION => Parents([NULL_REVISION, NULL_REVISION]),
75 r => self.get_by_revision(r)?.parents,
76 })
77 }
78}
79
80impl<C: NodeComparator> RankedGraph for InMemoryGraph<C> {
81 fn rank(&self, rev: Revision) -> Result<Rank, GraphReadError> {
82 Ok(match rev {
83 NULL_REVISION => 0,
84 r => self.get_by_revision(r)?.rank,
85 })
86 }
87}
88
89impl<C: NodeComparator> MergeRankedGraph for InMemoryGraph<C> {
90 fn merge_rank(&self, rev: Revision) -> Result<Rank, GraphReadError> {
91 Ok(match rev {
92 NULL_REVISION => 0,
93 r => self.get_by_revision(r)?.merge_rank,
94 })
95 }
96}
97
98impl<C: NodeComparator> LabelledGraph for InMemoryGraph<C> {
99 fn rev_of_node_id(
100 &self,
101 node_id: NodeID,
102 ) -> Result<Revision, GraphReadError> {
103 self.rev_map
104 .get(&node_id)
105 .cloned()
106 .ok_or(GraphReadError::InvalidKey)
107 }
108
109 fn node_id(&self, rev: Revision) -> Result<NodeID, GraphReadError> {
110 Ok(self.get_by_revision(rev)?.id)
111 }
112}
113
114impl<C: NodeComparator> SizedGraph for InMemoryGraph<C> {
115 fn nb_nodes(&self) -> usize {
116 self.nodes.len()
117 }
118}
119
120impl<C: NodeComparator> StableOrderGraph for InMemoryGraph<C> {
121 fn sorted_parents(
122 &self,
123 parents: Parents,
124 ) -> Result<Parents, GraphReadError> {
125 Ok(Parents(match parents {
126 Parents([p, NULL_REVISION]) | Parents([NULL_REVISION, p]) => {
127 [p, NULL_REVISION]
128 }
129 Parents([p1, p2]) => {
130 if C::compare(self, p1, p2)? == Ordering::Less {
131 [p1, p2]
132 } else {
133 [p2, p1]
134 }
135 }
136 }))
137 }
138
139 fn ordered_parents(
140 &self,
141 rev: Revision,
142 ) -> Result<Parents, GraphReadError> {
143 self.sorted_parents(self.parents(rev)?)
144 }
145
146 fn leaps(&self, rev: Revision) -> Result<&Vec<Leap>, GraphReadError> {
147 match rev {
148 NULL_REVISION => Ok(&self._empty_leap_vec),
149 r => Ok(&self.nodes[r as usize].leaps),
150 }
151 }
152
153 fn leap_counts(
154 &self,
155 rev: Revision,
156 ) -> Result<LeapCounts, GraphReadError> {
157 Ok(match rev {
158 NULL_REVISION => LeapCounts {
159 soft_leaps: 0,
160 hard_leaps: 0,
161 },
162 r => self.nodes[r as usize].leap_counts,
163 })
164 }
165}
166
167fn count_leaps(leaps: &[Leap]) -> LeapCounts {
168 let mut leap_counts = LeapCounts {
169 soft_leaps: 0,
170 hard_leaps: 0,
171 };
172
173 for leap in leaps {
174 match leap.leap_type {
175 LeapType::Soft => leap_counts.soft_leaps += 1,
176 LeapType::Hard | LeapType::Last => leap_counts.hard_leaps += 1,
177 }
178 }
179
180 leap_counts
181}
182
183fn make_node<C: NodeComparator>(
184 graph: &InMemoryGraph<C>,
185 parents: Parents,
186 node_id: NodeID,
187 rev: Revision,
188) -> Result<Node, GraphReadError> {
189 let Parents([p_min, p_max]) = graph.sorted_parents(parents)?;
190 let leap_info = node_leaps(graph, rev, &parents)?;
191 let exclusive_merge_rank = if p_max == NULL_REVISION {
192 0
193 } else {
194 1 + leap_info.exclusive_merge_count
195 };
196
197 Ok(Node {
198 rev,
199 id: node_id,
200 parents,
201 rank: 1 + leap_info.exclusive_part_size + graph.rank(p_min)?,
202 merge_rank: exclusive_merge_rank + graph.merge_rank(p_min)?,
203 leap_counts: count_leaps(&leap_info.leaps)
204 + graph.leap_counts(p_min)?,
205 leaps: leap_info.leaps,
206 })
207}
208
209impl<C: NodeComparator> MutableGraph for InMemoryGraph<C> {
210 fn push(
211 &mut self,
212 node_id: NodeID,
213 p1: NodeID,
214 p2: NodeID,
215 ) -> Result<Revision, GraphWriteError> {
216 let parents = Parents([self.rev_map[&p1], self.rev_map[&p2]]);
217 let rev = self.nodes.len() as Revision;
218 let node = make_node(self, parents, node_id, rev)
219 .map_err(|_| GraphWriteError::InvalidParents(node_id))?;
220
221 self.rev_map.insert(node_id, rev);
222 self.nodes.push(node);
223 Ok(rev)
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use crate::graph::{
230 Graph, MutableGraph, NodeID, Parents, RankedGraph, SizedGraph,
231 NODE_ID_LEN, NULL_ID, NULL_REVISION,
232 };
233 use crate::testing::graph_in_mem::InMemoryGraph;
234 use crate::testing::ordering::NodeIDComparator;
235 use std::iter::Iterator;
236 use std::vec::Vec;
237
238 #[test]
239 fn test_simple_in_memory_graph() {
240 let node: Vec<NodeID> =
241 (0..=6).map(|i| NodeID([i + 1; NODE_ID_LEN])).collect();
242
243 let mut graph = InMemoryGraph::<NodeIDComparator>::new();
244 graph.push(node[0], NULL_ID, NULL_ID).unwrap();
245 graph.push(node[1], node[0], NULL_ID).unwrap();
246 graph.push(node[2], node[0], NULL_ID).unwrap();
247 graph.push(node[3], node[1], NULL_ID).unwrap();
248 graph.push(node[4], node[3], node[2]).unwrap();
249 graph.push(node[5], node[4], NULL_ID).unwrap();
250 graph.push(node[6], node[3], NULL_ID).unwrap();
251
252 assert_eq!(graph.nb_nodes(), 7);
253
254 assert_eq!(
255 graph.parents(NULL_REVISION).unwrap(),
256 Parents([NULL_REVISION, NULL_REVISION])
257 );
258 assert_eq!(graph.rank(NULL_REVISION).unwrap(), 0);
259
260 let r0 = graph.get_by_revision(0).unwrap();
261 assert_eq!(r0.rev, 0);
262 assert_eq!(r0.id, node[0]);
263 assert_eq!(r0.parents, Parents([NULL_REVISION, NULL_REVISION]));
264 assert_eq!(r0.rank, 1);
265 assert_eq!(r0.merge_rank, 0);
266 assert_eq!(r0.leap_counts.soft_leaps, 0);
267 assert_eq!(r0.leap_counts.hard_leaps, 0);
268
269 let r4 = graph.get_by_revision(4).unwrap();
270 assert_eq!(r4.rev, 4);
271 assert_eq!(r4.id, node[4]);
272 assert_eq!(r4.parents, Parents([3, 2]));
273 assert_eq!(r4.rank, 5);
274 assert_eq!(r4.merge_rank, 1);
275 assert_eq!(r4.leap_counts.soft_leaps, 0);
276 assert_eq!(r4.leap_counts.hard_leaps, 1);
277
278 let r6 = graph.get_by_revision(6).unwrap();
279 assert_eq!(r6.rev, 6);
280 assert_eq!(r6.id, node[6]);
281 assert_eq!(r6.parents, Parents([3, NULL_REVISION]));
282 assert_eq!(graph.parents(6).unwrap(), Parents([3, NULL_REVISION]));
283 assert_eq!(r6.rank, 4);
284 assert_eq!(r6.merge_rank, 0);
285 assert_eq!(r6.leap_counts.soft_leaps, 0);
286 assert_eq!(r6.leap_counts.hard_leaps, 0);
287 }
288}