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}