Skip to main content

xs/
error.rs

1//! Shared error types used across the crate.
2
3/// The crate's general-purpose error: any boxed, thread-safe [`std::error::Error`].
4///
5/// Fallible store operations such as [`append`](crate::Store::append) and
6/// [`remove`](crate::Store::remove) return `Result<_, Error>`. Use
7/// [`NotFound::is_not_found`] or [`has_not_found_io_error`] to test for the
8/// not-found case.
9pub type Error = Box<dyn std::error::Error + Send + Sync>;
10
11/// Marker error indicating a requested resource does not exist.
12#[derive(Debug)]
13pub struct NotFound;
14
15impl std::fmt::Display for NotFound {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        write!(f, "Not found")
18    }
19}
20
21impl std::error::Error for NotFound {}
22
23impl NotFound {
24    /// Check if an error is our custom NotFound error
25    pub fn is_not_found(err: &Error) -> bool {
26        err.downcast_ref::<NotFound>().is_some()
27    }
28}
29
30/// Check if an error has ErrorKind::NotFound in its chain
31pub fn has_not_found_io_error(err: &Error) -> bool {
32    // Check if it's directly an IO error with NotFound kind
33    if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
34        return io_err.kind() == std::io::ErrorKind::NotFound;
35    }
36
37    // Check the error chain for IO errors with NotFound kind
38    let mut source = err.source();
39    while let Some(err) = source {
40        if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
41            if io_err.kind() == std::io::ErrorKind::NotFound {
42                return true;
43            }
44        }
45        source = err.source();
46    }
47
48    false
49}