1#[derive(thiserror::Error, Debug)]
5pub enum CypherLiteError {
6 #[error("I/O error: {0}")]
8 IoError(#[from] std::io::Error),
9
10 #[error("Corrupted page {page_id}: {reason}")]
12 CorruptedPage {
13 page_id: u32,
15 reason: String,
17 },
18
19 #[error("Transaction conflict: write lock unavailable")]
21 TransactionConflict,
22
23 #[error("Out of space: buffer pool or disk full")]
25 OutOfSpace,
26
27 #[error("Invalid magic number")]
29 InvalidMagicNumber,
30
31 #[error("Unsupported version: found {found}, supported {supported}")]
33 UnsupportedVersion {
34 found: u32,
36 supported: u32,
38 },
39
40 #[error("Checksum mismatch: expected {expected}, found {found}")]
42 ChecksumMismatch {
43 expected: u64,
45 found: u64,
47 },
48
49 #[error("Serialization error: {0}")]
51 SerializationError(String),
52
53 #[error("Node not found: {0}")]
55 NodeNotFound(u64),
56
57 #[error("Edge not found: {0}")]
59 EdgeNotFound(u64),
60
61 #[error("Parse error at line {line}, column {column}: {message}")]
63 ParseError {
64 line: usize,
66 column: usize,
68 message: String,
70 },
71
72 #[error("Semantic error: {0}")]
74 SemanticError(String),
75
76 #[error("Execution error: {0}")]
78 ExecutionError(String),
79
80 #[error("Unsupported syntax: {0}")]
82 UnsupportedSyntax(String),
83
84 #[error("Constraint violation: {0}")]
86 ConstraintViolation(String),
87
88 #[error("Invalid datetime format: {0}")]
90 InvalidDateTimeFormat(String),
91
92 #[error("System property is read-only: {0}")]
94 SystemPropertyReadOnly(String),
95
96 #[error("Feature incompatible: database requires flags 0x{db_flags:08X}, compiled with 0x{compiled_flags:08X}")]
98 FeatureIncompatible {
99 db_flags: u32,
101 compiled_flags: u32,
103 },
104
105 #[cfg(feature = "subgraph")]
107 #[error("Subgraph not found: {0}")]
108 SubgraphNotFound(u64),
109
110 #[cfg(feature = "subgraph")]
112 #[error("Feature requires subgraph support (compile with --features subgraph)")]
113 FeatureRequiresSubgraph,
114
115 #[cfg(feature = "hypergraph")]
117 #[error("Hyperedge not found: {0}")]
118 HyperEdgeNotFound(u64),
119
120 #[cfg(feature = "plugin")]
122 #[error("Plugin error: {0}")]
123 PluginError(String),
124
125 #[cfg(feature = "plugin")]
127 #[error("Function not found: {0}")]
128 FunctionNotFound(String),
129
130 #[cfg(feature = "plugin")]
132 #[error("Unsupported index type: {0}")]
133 UnsupportedIndexType(String),
134
135 #[cfg(feature = "plugin")]
137 #[error("Unsupported format: {0}")]
138 UnsupportedFormat(String),
139
140 #[cfg(feature = "plugin")]
142 #[error("Trigger error: {0}")]
143 TriggerError(String),
144}
145
146pub type Result<T> = std::result::Result<T, CypherLiteError>;
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[test]
155 fn test_invalid_magic_number_error() {
156 let err = CypherLiteError::InvalidMagicNumber;
157 assert_eq!(format!("{err}"), "Invalid magic number");
158 }
159
160 #[test]
162 fn test_unsupported_version_error() {
163 let err = CypherLiteError::UnsupportedVersion {
164 found: 99,
165 supported: 1,
166 };
167 assert_eq!(
168 format!("{err}"),
169 "Unsupported version: found 99, supported 1"
170 );
171 }
172
173 #[test]
175 fn test_checksum_mismatch_error() {
176 let err = CypherLiteError::ChecksumMismatch {
177 expected: 100,
178 found: 200,
179 };
180 assert_eq!(
181 format!("{err}"),
182 "Checksum mismatch: expected 100, found 200"
183 );
184 }
185
186 #[test]
188 fn test_transaction_conflict_error() {
189 let err = CypherLiteError::TransactionConflict;
190 assert_eq!(
191 format!("{err}"),
192 "Transaction conflict: write lock unavailable"
193 );
194 }
195
196 #[test]
198 fn test_out_of_space_error() {
199 let err = CypherLiteError::OutOfSpace;
200 assert_eq!(format!("{err}"), "Out of space: buffer pool or disk full");
201 }
202
203 #[test]
204 fn test_corrupted_page_error() {
205 let err = CypherLiteError::CorruptedPage {
206 page_id: 5,
207 reason: "bad header".to_string(),
208 };
209 assert_eq!(format!("{err}"), "Corrupted page 5: bad header");
210 }
211
212 #[test]
213 fn test_io_error_conversion() {
214 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file missing");
215 let err: CypherLiteError = io_err.into();
216 assert!(matches!(err, CypherLiteError::IoError(_)));
217 assert!(format!("{err}").contains("file missing"));
218 }
219
220 #[test]
221 fn test_error_is_send_sync() {
222 fn assert_send<T: Send>() {}
223 fn assert_sync<T: Sync>() {}
224 assert_send::<CypherLiteError>();
225 assert_sync::<CypherLiteError>();
226 }
227
228 #[test]
229 fn test_node_not_found_error() {
230 let err = CypherLiteError::NodeNotFound(42);
231 assert_eq!(format!("{err}"), "Node not found: 42");
232 }
233
234 #[test]
235 fn test_edge_not_found_error() {
236 let err = CypherLiteError::EdgeNotFound(99);
237 assert_eq!(format!("{err}"), "Edge not found: 99");
238 }
239
240 #[test]
242 fn test_parse_error() {
243 let err = CypherLiteError::ParseError {
244 line: 3,
245 column: 10,
246 message: "unexpected token".to_string(),
247 };
248 assert_eq!(
249 format!("{err}"),
250 "Parse error at line 3, column 10: unexpected token"
251 );
252 }
253
254 #[test]
256 fn test_semantic_error() {
257 let err = CypherLiteError::SemanticError("unknown label".to_string());
258 assert_eq!(format!("{err}"), "Semantic error: unknown label");
259 }
260
261 #[test]
263 fn test_execution_error() {
264 let err = CypherLiteError::ExecutionError("division by zero".to_string());
265 assert_eq!(format!("{err}"), "Execution error: division by zero");
266 }
267
268 #[test]
270 fn test_unsupported_syntax_error() {
271 let err = CypherLiteError::UnsupportedSyntax("MERGE".to_string());
272 assert_eq!(format!("{err}"), "Unsupported syntax: MERGE");
273 }
274
275 #[test]
277 fn test_constraint_violation_error() {
278 let err = CypherLiteError::ConstraintViolation("unique key violated".to_string());
279 assert_eq!(
280 format!("{err}"),
281 "Constraint violation: unique key violated"
282 );
283 }
284
285 #[test]
287 fn test_system_property_read_only_error() {
288 let err = CypherLiteError::SystemPropertyReadOnly("_created_at".to_string());
289 assert_eq!(
290 format!("{err}"),
291 "System property is read-only: _created_at"
292 );
293 }
294
295 #[test]
297 fn test_invalid_datetime_format_error() {
298 let err = CypherLiteError::InvalidDateTimeFormat("bad input".to_string());
299 assert_eq!(format!("{err}"), "Invalid datetime format: bad input");
300 }
301
302 #[test]
304 fn test_feature_incompatible_error() {
305 let err = CypherLiteError::FeatureIncompatible {
306 db_flags: 0x03,
307 compiled_flags: 0x01,
308 };
309 assert_eq!(
310 format!("{err}"),
311 "Feature incompatible: database requires flags 0x00000003, compiled with 0x00000001"
312 );
313 }
314
315 #[cfg(feature = "subgraph")]
320 #[test]
321 fn test_subgraph_not_found_error() {
322 let err = CypherLiteError::SubgraphNotFound(42);
323 assert_eq!(format!("{err}"), "Subgraph not found: 42");
324 }
325
326 #[cfg(feature = "subgraph")]
327 #[test]
328 fn test_feature_requires_subgraph_error() {
329 let err = CypherLiteError::FeatureRequiresSubgraph;
330 assert_eq!(
331 format!("{err}"),
332 "Feature requires subgraph support (compile with --features subgraph)"
333 );
334 }
335}