summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2022-12-28 16:57:35 +0100
committerMatthias Beyer <mail@beyermatthias.de>2022-12-28 17:13:45 +0100
commit7863c3bcf8c7ca37bfc5652ec92e620968e635e4 (patch)
tree232bcc294e1d442d31a49c060b3b9e14c3f8ed4f /src
parent5cc96a7a9f8a48a13dca4dd6a48dacff27773f3b (diff)
Transform codebase to use thiserror
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
Diffstat (limited to 'src')
-rw-r--r--src/async_dag.rs74
-rw-r--r--src/dag_backend.rs7
-rw-r--r--src/error.rs11
-rw-r--r--src/lib.rs3
-rw-r--r--src/node_id.rs2
-rw-r--r--src/test_impl.rs19
6 files changed, 78 insertions, 38 deletions
diff --git a/src/async_dag.rs b/src/async_dag.rs
index 8b4c595..7abc6c5 100644
--- a/src/async_dag.rs
+++ b/src/async_dag.rs
@@ -6,8 +6,6 @@
use std::pin::Pin;
-use anyhow::anyhow;
-use anyhow::Result;
use futures::stream::StreamExt;
use futures::task::Poll;
@@ -27,16 +25,17 @@ where
_node: std::marker::PhantomData<N>,
}
-impl<Id, N, Backend> AsyncDag<Id, N, Backend>
+impl<Id, N, Backend, Error> AsyncDag<Id, N, Backend>
where
Id: NodeId + Send,
N: Node<Id = Id>,
- Backend: DagBackend<Id, N>,
+ Backend: DagBackend<Id, N, Error = Error>,
+ Error: From<crate::Error<Id>>,
{
/// Create a new DAG with a backend and a HEAD node
///
/// The head node is `DagBackend::put` into the backend before the AsyncDag object is created.
- pub async fn new(mut backend: Backend, head: N) -> Result<Self> {
+ pub async fn new(mut backend: Backend, head: N) -> Result<Self, Error> {
backend.put(head).await.map(|id| AsyncDag {
head: id,
backend,
@@ -49,16 +48,16 @@ where
/// # Warning
///
/// This fails if backend.get(head) fails.
- pub async fn load(backend: Backend, head: Id) -> Result<Self> {
+ pub async fn load(backend: Backend, head: Id) -> Result<Self, Error> {
backend
- .get(head)
+ .get(head.clone())
.await?
.map(|(id, _)| AsyncDag {
head: id,
backend,
_node: std::marker::PhantomData,
})
- .ok_or_else(|| anyhow!("Node not found"))
+ .ok_or_else(|| crate::Error::NodeNotFound(head).into())
}
pub fn head(&self) -> &Id {
@@ -74,10 +73,10 @@ where
}
/// Check whether an `id` is in the DAG.
- pub async fn has_id(&self, id: &Id) -> Result<bool> {
+ pub async fn has_id(&self, id: &Id) -> Result<bool, Error> {
self.stream()
- .map(|r| -> Result<bool> { r.map(|(ref node_id, _)| node_id == id) })
- .collect::<Vec<Result<bool>>>()
+ .map(|r| -> Result<bool, _> { r.map(|(ref node_id, _)| node_id == id) })
+ .collect::<Vec<Result<bool, _>>>()
.await
.into_iter()
.fold(Ok(false), |acc, e| match (acc, e) {
@@ -94,7 +93,7 @@ where
/// # Warning
///
/// The order of the nodes is not (yet) guaranteed.
- pub fn stream(&self) -> Stream<Id, N, Backend> {
+ pub fn stream(&self) -> Stream<Id, N, Backend, Error> {
Stream {
dag: self,
backlog: {
@@ -110,11 +109,11 @@ where
/// # Warning
///
/// fails if the passed node does not point to the current HEAD in its parents.
- pub async fn update_head(&mut self, node: N) -> Result<Id> {
+ pub async fn update_head(&mut self, node: N) -> Result<Id, Error> {
if node.parent_ids().iter().any(|id| id == &self.head) {
self.update_head_unchecked(node).await
} else {
- Err(anyhow!("Node does not have HEAD as parent"))
+ Err(Error::from(crate::Error::HeadNotAParent))
}
}
@@ -124,7 +123,7 @@ where
///
/// Does not check whether the passed `node` does point to the current (then old) HEAD in its
/// parents. Be careful to not lose nodes from the DAG with this.
- pub async fn update_head_unchecked(&mut self, node: N) -> Result<Id> {
+ pub async fn update_head_unchecked(&mut self, node: N) -> Result<Id, Error> {
let id = self.backend.put(node).await?;
self.head = id.clone();
Ok(id)
@@ -149,9 +148,13 @@ where
///
/// 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<M>(&mut self, other: &AsyncDag<Id, N, Backend>, merger: M) -> Result<Id>
+ pub async fn merge<M>(
+ &mut self,
+ other: &AsyncDag<Id, N, Backend>,
+ merger: M,
+ ) -> Result<Id, Error>
where
- M: Merger<Id, N>,
+ M: Merger<Id, N, Error = Error>,
{
let node = merger.create_merge_node(&self.head, &other.head)?;
let id = self.backend.put(node).await?;
@@ -165,41 +168,49 @@ where
Id: NodeId,
N: Node<Id = Id>,
{
- fn create_merge_node(&self, left_id: &Id, right_id: &Id) -> Result<N>;
+ type Error;
+
+ fn create_merge_node(&self, left_id: &Id, right_id: &Id) -> Result<N, Self::Error>;
}
-impl<Id, N, F> Merger<Id, N> for F
+impl<Id, N, F, Error> Merger<Id, N> for F
where
Id: NodeId,
N: Node<Id = Id>,
- F: Fn(&Id, &Id) -> Result<N>,
+ F: Fn(&Id, &Id) -> Result<N, Error>,
+ Error: From<crate::Error<Id>>,
{
- fn create_merge_node(&self, left_id: &Id, right_id: &Id) -> Result<N> {
+ type Error = Error;
+
+ fn create_merge_node(&self, left_id: &Id, right_id: &Id) -> Result<N, Self::Error> {
(self)(left_id, right_id)
}
}
/// Stream adapter for streaming all nodes in a DAG
-pub struct Stream<'a, Id, N, Backend>
+pub struct Stream<'a, Id, N, Backend, Error>
where
Id: NodeId + Send,
N: Node<Id = Id>,
Backend: DagBackend<Id, N>,
+ Error: From<crate::Error<Id>>,
{
dag: &'a AsyncDag<Id, N, Backend>,
- backlog: Vec<Pin<Backlog<'a, Id, N>>>,
+ backlog: Vec<Pin<Backlog<'a, Id, N, Error>>>,
}
-pub type Backlog<'a, Id, N> =
- Box<(dyn futures::future::Future<Output = Result<Option<(Id, N)>>> + std::marker::Send + 'a)>;
+pub type Backlog<'a, Id, N, Error> = Box<
+ (dyn futures::future::Future<Output = Result<Option<(Id, N)>, Error>> + std::marker::Send + 'a),
+>;
-impl<'a, Id, N, Backend> futures::stream::Stream for Stream<'a, Id, N, Backend>
+impl<'a, Id, N, Backend, Error> futures::stream::Stream for Stream<'a, Id, N, Backend, Error>
where
Id: NodeId + Send,
N: Node<Id = Id>,
- Backend: DagBackend<Id, N>,
+ Backend: DagBackend<Id, N, Error = Error>,
+ Error: From<crate::Error<Id>>,
{
- type Item = Result<(Id, N)>;
+ type Item = Result<(Id, N), Error>;
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
@@ -235,11 +246,10 @@ where
#[cfg(test)]
mod tests {
-
- use anyhow::Result;
use futures::StreamExt;
use crate::test_impl as test;
+ use crate::test_impl::TestError;
use crate::AsyncDag;
use crate::DagBackend;
@@ -445,11 +455,13 @@ mod tests {
struct M;
impl super::Merger<test::Id, test::Node> for M {
+ type Error = TestError;
+
fn create_merge_node(
&self,
left_id: &test::Id,
right_id: &test::Id,
- ) -> Result<test::Node> {
+ ) -> Result<test::Node, Self::Error> {
Ok(test::Node {
parents: vec![*left_id, *right_id],
data: 3,
diff --git a/src/dag_backend.rs b/src/dag_backend.rs
index 2be9736..09dc428 100644
--- a/src/dag_backend.rs
+++ b/src/dag_backend.rs
@@ -4,7 +4,6 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
-use anyhow::Result;
use async_trait::async_trait;
use crate::Node;
@@ -20,6 +19,8 @@ where
N: Node,
Id: NodeId + Send,
{
+ type Error;
+
/// Get a `Node` from the backend that is identified by `id`
///
/// # Returns
@@ -27,12 +28,12 @@ where
/// * Should return Err(_) if the operation failed.
/// * Should return Ok(None) if there is no node that is identified by `id`
/// * Otherwise return the Id along with the node identified by it
- async fn get(&self, id: Id) -> Result<Option<(Id, N)>>;
+ async fn get(&self, id: Id) -> Result<Option<(Id, N)>, Self::Error>;
/// Store a `node` in the backend, returning its `Id`
///
/// This function should store the `node` in the backend and return the `id` the node has.
- async fn put(&mut self, node: N) -> Result<Id>;
+ async fn put(&mut self, node: N) -> Result<Id, Self::Error>;
}
#[cfg(test)]
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..fd91045
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,11 @@
+#[derive(Debug, thiserror::Error)]
+pub enum Error<Id>
+where
+ Id: crate::NodeId,
+{
+ #[error("Node not found: {:?}", .0)]
+ NodeNotFound(Id),
+
+ #[error("Node does not have HEAD as parent")]
+ HeadNotAParent,
+}
diff --git a/src/lib.rs b/src/lib.rs
index bcb6ae0..67bce67 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -16,5 +16,8 @@ pub use node::*;
mod node_id;
pub use node_id::*;
+mod error;
+pub use error::*;
+
#[cfg(test)]
mod test_impl;
diff --git a/src/node_id.rs b/src/node_id.rs
index df1e4d4..5d0663a 100644
--- a/src/node_id.rs
+++ b/src/node_id.rs
@@ -7,4 +7,4 @@
/// A unique identifier for a `Node`
///
/// The `NodeId` should be cheap to clone (for example a UUID or some form of a hash value).
-pub trait NodeId: Clone + Eq + PartialEq {}
+pub trait NodeId: Clone + Eq + PartialEq + std::fmt::Debug {}
diff --git a/src/test_impl.rs b/src/test_impl.rs
index a95c4c6..c8f2b51 100644
--- a/src/test_impl.rs
+++ b/src/test_impl.rs
@@ -7,9 +7,20 @@
use std::sync::Arc;
use std::sync::RwLock;
-use anyhow::Result;
use async_trait::async_trait;
+#[derive(Debug)]
+pub struct TestError;
+
+impl<Id> From<crate::Error<Id>> for TestError
+where
+ Id: crate::NodeId,
+{
+ fn from(_ce: crate::Error<Id>) -> Self {
+ TestError
+ }
+}
+
#[derive(Copy, Clone, Eq, PartialEq, std::hash::Hash, Debug)]
pub struct Id(pub(crate) usize);
@@ -46,7 +57,9 @@ impl Backend {
#[async_trait]
impl crate::DagBackend<Id, Node> for Backend {
- async fn get(&self, id: Id) -> Result<Option<(Id, Node)>> {
+ type Error = TestError;
+
+ async fn get(&self, id: Id) -> Result<Option<(Id, Node)>, Self::Error> {
if self.0.read().unwrap().len() < id.0 + 1 {
Ok(None)
} else {
@@ -54,7 +67,7 @@ impl crate::DagBackend<Id, Node> for Backend {
}
}
- async fn put(&mut self, node: Node) -> Result<Id> {
+ async fn put(&mut self, node: Node) -> Result<Id, Self::Error> {
while self.0.read().unwrap().len() < node.data + 1 {
self.0.write().unwrap().push(None)
}