icydb_core/
error.rs

1use crate::db::store::StoreError;
2use std::fmt;
3use thiserror::Error as ThisError;
4
5///
6/// InternalError
7/// Structured runtime error with a stable internal classification.
8/// Not a stable API; intended for internal use and may change without notice.
9///
10
11#[derive(Debug, ThisError)]
12#[error("{message}")]
13pub struct InternalError {
14    pub class: ErrorClass,
15    pub origin: ErrorOrigin,
16    pub message: String,
17    pub store: Option<StoreError>,
18}
19
20impl InternalError {
21    pub fn new(class: ErrorClass, origin: ErrorOrigin, message: impl Into<String>) -> Self {
22        let message = message.into();
23        let store = match (class, origin) {
24            (ErrorClass::Corruption, ErrorOrigin::Store) => Some(StoreError::Corrupt {
25                message: message.clone(),
26            }),
27            (ErrorClass::InvariantViolation, ErrorOrigin::Store) => {
28                Some(StoreError::InvariantViolation {
29                    message: message.clone(),
30                })
31            }
32            _ => None,
33        };
34        Self {
35            class,
36            origin,
37            message,
38            store,
39        }
40    }
41
42    pub fn store_not_found(key: impl Into<String>) -> Self {
43        let key = key.into();
44        Self {
45            class: ErrorClass::NotFound,
46            origin: ErrorOrigin::Store,
47            message: format!("data key not found: {key}"),
48            store: Some(StoreError::NotFound { key }),
49        }
50    }
51
52    #[must_use]
53    pub const fn is_not_found(&self) -> bool {
54        matches!(self.store, Some(StoreError::NotFound { .. }))
55    }
56
57    #[must_use]
58    pub fn display_with_class(&self) -> String {
59        format!("{}:{}: {}", self.origin, self.class, self.message)
60    }
61}
62
63///
64/// ErrorClass
65/// Internal error taxonomy for runtime classification.
66/// Not a stable API; may change without notice.
67///
68
69#[derive(Clone, Copy, Debug, Eq, PartialEq)]
70pub enum ErrorClass {
71    Corruption,
72    NotFound,
73    Internal,
74    Conflict,
75    Unsupported,
76    InvariantViolation,
77}
78
79impl fmt::Display for ErrorClass {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        let label = match self {
82            Self::Corruption => "corruption",
83            Self::NotFound => "not_found",
84            Self::Internal => "internal",
85            Self::Conflict => "conflict",
86            Self::Unsupported => "unsupported",
87            Self::InvariantViolation => "invariant_violation",
88        };
89        write!(f, "{label}")
90    }
91}
92
93///
94/// ErrorOrigin
95/// Internal origin taxonomy for runtime classification.
96/// Not a stable API; may change without notice.
97///
98
99#[derive(Clone, Copy, Debug, Eq, PartialEq)]
100pub enum ErrorOrigin {
101    Serialize,
102    Store,
103    Index,
104    Query,
105    Response,
106    Executor,
107    Interface,
108}
109
110impl fmt::Display for ErrorOrigin {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        let label = match self {
113            Self::Serialize => "serialize",
114            Self::Store => "store",
115            Self::Index => "index",
116            Self::Query => "query",
117            Self::Response => "response",
118            Self::Executor => "executor",
119            Self::Interface => "interface",
120        };
121        write!(f, "{label}")
122    }
123}