summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2021-04-04 14:23:43 +0200
committerMatthias Beyer <mail@beyermatthias.de>2021-04-04 14:23:43 +0200
commit0dce0832b9f389f9a3d2bf815963fd72e41659d1 (patch)
tree002bd8197a18e218a55934718b1f61f4a9b09948 /src
parent99fce07a1473499f8538a35b29712ee3960dc789 (diff)
Add AsyncDag::merge() function
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src')
-rw-r--r--src/async_dag.rs77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/async_dag.rs b/src/async_dag.rs
index 75e56fc..9faf1e6 100644
--- a/src/async_dag.rs
+++ b/src/async_dag.rs
@@ -121,6 +121,19 @@ impl<Id, N, Backend> AsyncDag<Id, N, Backend>
_node: std::marker::PhantomData,
}
}
+
+ /// Merge another AsyncDag into this one
+ ///
+ /// Use the `merger` function to merge the two head IDs and generate a new Node instance for
+ /// the new HEAD of `self`.
+ pub async fn merge<Merger>(&mut self, other: AsyncDag<Id, N, Backend>, merger: Merger) -> Result<Id>
+ where Merger: FnOnce(Id, Id) -> Result<N>
+ {
+ let node = merger(self.head.clone(), other.head)?;
+ let id = self.backend.put(node).await?;
+ self.head = id.clone();
+ Ok(id)
+ }
}
@@ -353,5 +366,69 @@ mod tests {
assert_eq!(branched.head, test::Id(0));
}
+ #[test]
+ fn test_merging() {
+ let mut dag = {
+ let head = test::Node {
+ id: test::Id(0),
+ parents: vec![],
+ data: 42,
+ };
+ let b = test::Backend::new(vec![Some(head.clone())]);
+ let dag = tokio_test::block_on(AsyncDag::new(b, head));
+ assert!(dag.is_ok());
+ dag.unwrap()
+ };
+
+ let mut branched = dag.branch();
+
+ {
+ assert_eq!(dag.backend.0.read().unwrap().len(), 1);
+ assert_eq!(dag.head, test::Id(0));
+ let new_head = test::Node {
+ id: test::Id(1),
+ parents: vec![test::Id(0)],
+ data: 43,
+ };
+
+ let id = tokio_test::block_on(dag.update_head(new_head));
+ assert!(id.is_ok());
+ let id = id.unwrap();
+
+ assert_eq!(dag.backend.0.read().unwrap().len(), 2);
+ assert_eq!(dag.head, test::Id(1));
+ }
+
+ {
+ assert_eq!(branched.backend.0.read().unwrap().len(), 2);
+ assert_eq!(branched.head, test::Id(0));
+ let new_head = test::Node {
+ id: test::Id(2),
+ parents: vec![test::Id(0)],
+ data: 44,
+ };
+
+ let id = tokio_test::block_on(branched.update_head(new_head));
+ assert!(id.is_ok());
+ let id = id.unwrap();
+
+ assert_eq!(branched.backend.0.read().unwrap().len(), 3);
+ assert_eq!(branched.head, test::Id(2));
+ }
+
+ let merge = tokio_test::block_on(dag.merge(branched, |left, right| {
+ Ok(test::Node {
+ id: test::Id(3),
+ parents: vec![left, right],
+ data: 45,
+ })
+ }));
+ assert!(merge.is_ok());
+ let merge = merge.unwrap();
+
+ assert_eq!(dag.backend.0.read().unwrap().len(), 4);
+ assert_eq!(dag.head, test::Id(3));
+ }
+
}