Skip to main content

dag/
errors.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8use std::io;
9use std::num::TryFromIntError;
10
11use thiserror::Error;
12
13use crate::Group;
14use crate::Id;
15use crate::Vertex;
16
17/// Error used by the Dag crate.
18#[derive(Debug, Error)]
19pub enum DagError {
20    /// A vertex name cannot be found.
21    #[error("{0:?} cannot be found")]
22    VertexNotFound(Vertex),
23
24    /// An Id cannot be found.
25    #[error("{0:?} cannot be found")]
26    IdNotFound(Id),
27
28    /// A fast path cannot be used.
29    #[error("NeedSlowPath: {0}")]
30    NeedSlowPath(String),
31
32    /// Callsite does something wrong. For example, a "parent function" does not
33    /// return reproducible results for a same vertex if called twice.
34    #[error("ProgrammingError: {0}")]
35    Programming(String),
36
37    /// Logic error in this crate. A bug in this crate or the backend data.
38    #[error("bug: {0}")]
39    Bug(String),
40
41    /// The backend (ex. filesystem) cannot fulfill the request somehow.
42    #[error(transparent)]
43    Backend(Box<BackendError>),
44
45    /// No space for new Ids.
46    #[error("out of space for group {0:?}")]
47    IdOverflow(Group),
48
49    /// Integer conversion overflow.
50    #[error(transparent)]
51    IntOverflow(#[from] TryFromIntError),
52}
53
54#[derive(Debug, Error)]
55pub enum BackendError {
56    #[error("{0}")]
57    Generic(String),
58
59    #[error(transparent)]
60    Io(#[from] std::io::Error),
61
62    #[cfg(any(test, feature = "indexedlog-backend"))]
63    #[error(transparent)]
64    IndexedLog(#[from] indexedlog::Error),
65
66    /// Other source of backend errors. Useful for external crates implementing
67    /// traits of the `dag` crate.
68    #[error(transparent)]
69    Other(#[from] anyhow::Error),
70}
71
72impl From<BackendError> for DagError {
73    fn from(err: BackendError) -> DagError {
74        DagError::Backend(Box::new(err))
75    }
76}
77
78#[cfg(any(test, feature = "indexedlog-backend"))]
79impl From<indexedlog::Error> for DagError {
80    fn from(err: indexedlog::Error) -> DagError {
81        DagError::Backend(Box::new(BackendError::from(err)))
82    }
83}
84
85impl From<io::Error> for DagError {
86    fn from(err: io::Error) -> DagError {
87        DagError::Backend(Box::new(BackendError::from(err)))
88    }
89}
90
91/// Quick way to return a `BackendError::Generic` error.
92pub fn bug<T>(message: impl ToString) -> crate::Result<T> {
93    Err(DagError::Bug(message.to_string()))
94}
95
96/// Quick way to return a `Programming` error.
97pub fn programming<T>(message: impl ToString) -> crate::Result<T> {
98    Err(DagError::Programming(message.to_string()))
99}
100
101pub trait NotFoundError {
102    fn not_found_error(&self) -> DagError;
103
104    fn not_found<T>(&self) -> crate::Result<T> {
105        Err(self.not_found_error())
106    }
107}
108
109impl NotFoundError for Id {
110    fn not_found_error(&self) -> DagError {
111        ::fail::fail_point!("dag-not-found-id");
112        DagError::IdNotFound(self.clone())
113    }
114}
115
116impl NotFoundError for Vertex {
117    fn not_found_error(&self) -> DagError {
118        ::fail::fail_point!("dag-not-found-vertex");
119        DagError::VertexNotFound(self.clone())
120    }
121}