graph_types/errors/
mod.rs

1use crate::{GraphEntry, Query};
2use std::{
3    error::Error,
4    fmt::{Debug, Display, Formatter},
5    ops::DerefMut,
6    path::Path,
7};
8
9/// The result type alias of a graph operation, see [`GraphError`] & [`GraphErrorKind`] for more.
10///
11/// # Examples
12///
13/// ```
14/// use graph_theory::GraphResult;
15/// ```
16pub type GraphResult<T = ()> = Result<T, GraphError>;
17
18/// The error type of a graph operation, see [`GraphErrorKind`] for more.
19///
20/// # Size
21///
22/// The size of this struct is always 8 bytes.
23///
24/// ```
25/// use graph_theory::GraphError;
26/// assert_eq!(std::mem::size_of::<GraphError>(), 8);
27/// ```
28///
29/// # Examples
30///
31/// ```
32/// use graph_theory::GraphError;
33/// GraphError::node_not_found(0); // node id 0 not found
34/// GraphError::edge_out_of_range(0, 5); // edge id 0 out of range (max 5)
35/// GraphError::custom("user angry"); // user is angry now
36/// ```
37#[derive(Debug)]
38pub struct GraphError {
39    kind: Box<GraphErrorKind>,
40}
41
42/// The real error type of a graph operation, it will not be exposed to the user, see [`GraphError`] for more.
43///
44/// # Examples
45///
46/// ```
47/// use graph_theory::GraphEngine;
48/// ```
49#[derive(Debug)]
50pub enum GraphErrorKind {
51    /// Some index is not found in storage.
52    ///
53    /// # Examples
54    ///
55    /// - edge id 0 out of range
56    ///
57    /// ```
58    /// use graph_theory::{GraphError, Query};
59    /// GraphError::not_found(Query::edge(0));
60    /// GraphError::edge_not_found(0);
61    /// ```
62    NotFound { query: Query },
63
64    /// Some index is not found in storage.
65    ///
66    /// # Examples
67    ///
68    /// - edge id 0 out of range
69    ///
70    /// ```
71    /// use graph_theory::{GraphError, Query};
72    /// GraphError::not_found(Query::edge(0));
73    /// GraphError::edge_not_found(0);
74    /// ```
75    NotSupported { query: Query },
76    /// Some index is out of range of storage.
77    ///
78    /// Max index is 5, but you query index 6.
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// use graph_theory::{GraphError, Query};
84    /// GraphError::not_found(Query::edge(0));
85    /// GraphError::node_out_of_range(6, 5);
86    /// ```
87    OutOfRange {
88        /// The entry type of the error.
89        entry: GraphEntry,
90        /// The entry index you want to access.
91        index: usize,
92        /// All elements count of the storage.
93        max: usize,
94    },
95    /// An IO error occurred.
96    ///
97    /// # Examples
98    ///
99    /// ```
100    /// use graph_theory::{GraphError, Query};
101    /// ```
102    IO {
103        /// The position of the error occurred.
104        entry: String,
105        /// The wrapped IO error.
106        error: std::io::Error,
107    },
108    /// # Arguments
109    ///
110    /// * `index`:
111    ///
112    /// returns: Option<Cow<Self::Node>>
113    ///
114    /// # Examples
115    ///
116    /// ```
117    /// use graph_theory::GraphEngine;
118    /// ```
119    Custom {
120        /// # Arguments
121        message: String,
122    },
123}
124
125impl Error for GraphError {}
126
127impl Display for GraphError {
128    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
129        Display::fmt(&self.kind, f)
130    }
131}
132
133impl Display for GraphErrorKind {
134    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
135        match self {
136            GraphErrorKind::NotFound { query } => {
137                write!(f, "{query:?} not found")
138            }
139            GraphErrorKind::NotSupported { query } => {
140                write!(f, "{query:?} not found")
141            }
142            GraphErrorKind::OutOfRange { entry, index, max } => {
143                write!(f, "{entry:?} index {index} is out of range, max index is {max}")
144            }
145            GraphErrorKind::Custom { message } => f.write_str(message),
146            GraphErrorKind::IO { entry, error } if entry.is_empty() => {
147                write!(f, "IO error: {error}", error = error)
148            }
149            GraphErrorKind::IO { entry, error } => {
150                write!(f, "IO error at {entry:?}: {error}", entry = entry, error = error)
151            }
152        }
153    }
154}
155
156impl GraphError {
157    /// Some index is not found in storage.
158    ///
159    /// # Examples
160    ///
161    /// - edge id 0 out of range
162    ///
163    /// ```
164    /// use graph_theory::{GraphError, Query};
165    /// GraphError::not_found(Query::edge(0));
166    /// GraphError::edge_not_found(0);
167    /// ```
168    pub fn custom<S>(message: S) -> Self
169    where
170        S: ToString,
171    {
172        Self { kind: Box::new(GraphErrorKind::Custom { message: message.to_string() }) }
173    }
174    /// Some index is not found in storage.
175    ///
176    /// # Examples
177    ///
178    /// - edge id 0 out of range
179    ///
180    /// ```
181    /// use graph_theory::{GraphError, Query};
182    /// GraphError::not_found(Query::edge(0));
183    /// GraphError::edge_not_found(0);
184    /// ```
185    pub fn not_found<Q: Into<Query>>(query: Q) -> Self {
186        Self { kind: Box::new(GraphErrorKind::NotFound { query: query.into() }) }
187    }
188    /// Some index is not found in storage.
189    ///
190    /// # Examples
191    ///
192    /// - edge id 0 out of range
193    ///
194    /// ```
195    /// use graph_theory::{GraphError, Query};
196    /// GraphError::not_found(Query::edge(0));
197    /// GraphError::edge_not_found(0);
198    /// ```
199    pub fn not_support<Q: Into<Query>>(query: Q) -> Self {
200        Self { kind: Box::new(GraphErrorKind::NotSupported { query: query.into() }) }
201    }
202    /// Fill where the io error occurred.
203    ///
204    /// # Examples
205    ///
206    /// - edge id 0 out of range
207    ///
208    /// ```
209    /// use graph_theory::{GraphError, Query};
210    /// GraphError::not_found(Query::edge(0));
211    /// GraphError::edge_not_found(0);
212    /// ```
213    pub fn with_io_path<P>(mut self, path: P) -> Self
214    where
215        P: AsRef<Path>,
216    {
217        match self.kind.deref_mut() {
218            GraphErrorKind::IO { entry, error: _ } => {
219                *entry = path.as_ref().to_string_lossy().to_string();
220                self
221            }
222            _ => self,
223        }
224    }
225    /// Some index is not found in storage.
226    ///
227    /// # Examples
228    ///
229    /// - edge id 0 out of range
230    ///
231    /// ```
232    /// use graph_theory::{GraphError, Query};
233    /// GraphError::not_found(Query::edge(0));
234    /// GraphError::edge_not_found(0);
235    /// ```
236    pub fn node_out_of_range(index: usize, max: usize) -> Self {
237        Self { kind: Box::new(GraphErrorKind::OutOfRange { entry: GraphEntry::Node, index, max }) }
238    }
239    /// Some index is not found in storage.
240    ///
241    /// # Examples
242    ///
243    /// - edge id 0 out of range
244    ///
245    /// ```
246    /// use graph_theory::{GraphError, Query};
247    /// GraphError::not_found(Query::edge(0));
248    /// ```
249    pub fn edge_out_of_range(index: usize, max: usize) -> Self {
250        Self { kind: Box::new(GraphErrorKind::OutOfRange { entry: GraphEntry::Edge, index, max }) }
251    }
252}