1use std::fmt;
4use thiserror::Error;
5
6pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Error, Debug)]
11pub enum Error {
12 #[error("I/O error: {0}")]
14 Io(#[from] std::io::Error),
15
16 #[error("Serialization error: {message}")]
18 Serialization {
19 message: String,
20 #[source]
21 source: Option<Box<dyn std::error::Error + Send + Sync>>,
22 },
23
24 #[error("Data corruption: {0}")]
26 Corruption(String),
27
28 #[error("Schema error: {0}")]
30 Schema(String),
31
32 #[error("CQL parse error: {0}")]
34 CqlParse(String),
35
36 #[error("Invalid format: {0}")]
38 InvalidFormat(String),
39
40 #[error("Unsupported format: {0}")]
42 UnsupportedFormat(String),
43
44 #[error("Operation timeout: {0}")]
46 Timeout(String),
47
48 #[error("Invalid path: {0}")]
50 InvalidPath(String),
51
52 #[error("Invalid state: {0}")]
54 InvalidState(String),
55
56 #[error("Query execution error: {0}")]
58 QueryExecution(String),
59
60 #[error("Type conversion error: {0}")]
62 TypeConversion(String),
63
64 #[error("Configuration error: {0}")]
66 Configuration(String),
67
68 #[error("Storage error: {0}")]
70 Storage(String),
71
72 #[error("Memory error: {0}")]
74 Memory(String),
75
76 #[error("Concurrency error: {0}")]
78 Concurrency(String),
79
80 #[error("Not found: {0}")]
82 NotFound(String),
83
84 #[error("Table error: {0}")]
86 Table(String),
87
88 #[error("Already exists: {0}")]
90 AlreadyExists(String),
91
92 #[error("Invalid operation: {0}")]
94 InvalidOperation(String),
95
96 #[error("Constraint violation: {0}")]
98 ConstraintViolation(String),
99
100 #[error("Transaction error: {0}")]
102 Transaction(String),
103
104 #[error("Index error: {0}")]
106 Index(String),
107
108 #[error("Compaction error: {0}")]
110 Compaction(String),
111
112 #[cfg(target_arch = "wasm32")]
114 #[error("WASM error: {0}")]
115 Wasm(String),
116
117 #[error("Internal error: {0}")]
119 Internal(String),
120
121 #[error("Parse error: {0}")]
123 Parse(String),
124
125 #[error("Invalid input: {0}")]
127 InvalidInput(String),
128
129 #[error("Unsupported query: {0}")]
131 UnsupportedQuery(String),
132}
133
134impl Error {
135 pub fn serialization(msg: impl Into<String>) -> Self {
137 Self::Serialization {
138 message: msg.into(),
139 source: None,
140 }
141 }
142
143 pub fn corruption(msg: impl Into<String>) -> Self {
145 Self::Corruption(msg.into())
146 }
147
148 pub fn schema(msg: impl Into<String>) -> Self {
150 Self::Schema(msg.into())
151 }
152
153 pub fn cql_parse(msg: impl Into<String>) -> Self {
155 Self::CqlParse(msg.into())
156 }
157
158 pub fn invalid_format(msg: impl Into<String>) -> Self {
160 Self::InvalidFormat(msg.into())
161 }
162
163 pub fn unsupported_format(msg: impl Into<String>) -> Self {
165 Self::UnsupportedFormat(msg.into())
166 }
167
168 pub fn invalid_path(msg: impl Into<String>) -> Self {
170 Self::InvalidPath(msg.into())
171 }
172
173 pub fn invalid_state(msg: impl Into<String>) -> Self {
175 Self::InvalidState(msg.into())
176 }
177
178 pub fn query_execution(msg: impl Into<String>) -> Self {
180 Self::QueryExecution(msg.into())
181 }
182
183 pub fn type_conversion(msg: impl Into<String>) -> Self {
185 Self::TypeConversion(msg.into())
186 }
187
188 pub fn configuration(msg: impl Into<String>) -> Self {
190 Self::Configuration(msg.into())
191 }
192
193 pub fn storage(msg: impl Into<String>) -> Self {
195 Self::Storage(msg.into())
196 }
197
198 pub fn memory(msg: impl Into<String>) -> Self {
200 Self::Memory(msg.into())
201 }
202
203 pub fn concurrency(msg: impl Into<String>) -> Self {
205 Self::Concurrency(msg.into())
206 }
207
208 pub fn not_found(msg: impl Into<String>) -> Self {
210 Self::NotFound(msg.into())
211 }
212
213 pub fn already_exists(msg: impl Into<String>) -> Self {
215 Self::AlreadyExists(msg.into())
216 }
217
218 pub fn invalid_operation(msg: impl Into<String>) -> Self {
220 Self::InvalidOperation(msg.into())
221 }
222
223 pub fn constraint_violation(msg: impl Into<String>) -> Self {
225 Self::ConstraintViolation(msg.into())
226 }
227
228 pub fn transaction(msg: impl Into<String>) -> Self {
230 Self::Transaction(msg.into())
231 }
232
233 pub fn index(msg: impl Into<String>) -> Self {
235 Self::Index(msg.into())
236 }
237
238 pub fn compaction(msg: impl Into<String>) -> Self {
240 Self::Compaction(msg.into())
241 }
242
243 #[cfg(target_arch = "wasm32")]
245 pub fn wasm(msg: impl Into<String>) -> Self {
246 Self::Wasm(msg.into())
247 }
248
249 pub fn internal(msg: impl Into<String>) -> Self {
251 Self::Internal(msg.into())
252 }
253
254 pub fn invalid_input(msg: impl Into<String>) -> Self {
256 Self::InvalidInput(msg.into())
257 }
258
259 pub fn parse(msg: impl Into<String>) -> Self {
261 Self::Parse(msg.into())
262 }
263
264 pub fn unsupported_query(msg: impl Into<String>) -> Self {
266 Self::UnsupportedQuery(msg.into())
267 }
268
269 pub fn table_not_found(msg: impl Into<String>) -> Self {
271 Self::NotFound(format!("Table not found: {}", msg.into()))
272 }
273
274 pub fn ambiguous_table(msg: impl Into<String>) -> Self {
276 Self::Table(format!("Ambiguous table reference: {}", msg.into()))
277 }
278
279 pub fn is_recoverable(&self) -> bool {
281 match self {
282 Error::Io(_) => true,
284 Error::Concurrency(_) => true,
285 Error::Memory(_) => true,
286
287 Error::Corruption(_) => false,
289 Error::Schema(_) => false,
290 Error::CqlParse(_) => false,
291 Error::Configuration(_) => false,
292
293 Error::Storage(_) => true,
295 Error::QueryExecution(_) => false,
296 Error::TypeConversion(_) => false,
297 Error::NotFound(_) => false,
298 Error::AlreadyExists(_) => false,
299 Error::InvalidOperation(_) => false,
300 Error::ConstraintViolation(_) => false,
301 Error::Transaction(_) => true,
302 Error::Index(_) => true,
303 Error::Compaction(_) => true,
304
305 Error::Table(_) => false,
307
308 #[cfg(target_arch = "wasm32")]
309 Error::Wasm(_) => false,
310
311 Error::Serialization { .. } => false,
312 Error::Internal(_) => false,
313 Error::Parse(_) => false,
314 Error::InvalidInput(_) => false,
315 Error::InvalidFormat(_) => false,
316 Error::UnsupportedFormat(_) => false,
317 Error::InvalidPath(_) => false,
318 Error::InvalidState(_) => false,
319 Error::Timeout(_) => false,
320 Error::UnsupportedQuery(_) => false,
321 }
322 }
323
324 pub fn category(&self) -> ErrorCategory {
326 match self {
327 Error::Io(_) => ErrorCategory::System,
328 Error::Serialization { .. } => ErrorCategory::Data,
329 Error::Corruption(_) => ErrorCategory::Data,
330 Error::Schema(_) => ErrorCategory::Schema,
331 Error::CqlParse(_) => ErrorCategory::Query,
332 Error::QueryExecution(_) => ErrorCategory::Query,
333 Error::TypeConversion(_) => ErrorCategory::Data,
334 Error::Configuration(_) => ErrorCategory::Configuration,
335 Error::Storage(_) => ErrorCategory::Storage,
336 Error::Memory(_) => ErrorCategory::System,
337 Error::Concurrency(_) => ErrorCategory::Concurrency,
338 Error::NotFound(_) => ErrorCategory::NotFound,
339 Error::AlreadyExists(_) => ErrorCategory::Conflict,
340 Error::InvalidOperation(_) => ErrorCategory::Logic,
341 Error::ConstraintViolation(_) => ErrorCategory::Constraint,
342 Error::Transaction(_) => ErrorCategory::Transaction,
343 Error::Index(_) => ErrorCategory::Storage,
344 Error::Compaction(_) => ErrorCategory::Storage,
345
346 Error::Table(_) => ErrorCategory::Schema,
348
349 #[cfg(target_arch = "wasm32")]
350 Error::Wasm(_) => ErrorCategory::Platform,
351
352 Error::Internal(_) => ErrorCategory::Internal,
353 Error::Parse(_) => ErrorCategory::Data,
354 Error::InvalidInput(_) => ErrorCategory::Data,
355 Error::InvalidFormat(_) => ErrorCategory::Data,
356 Error::UnsupportedFormat(_) => ErrorCategory::Data,
357 Error::InvalidPath(_) => ErrorCategory::System,
358 Error::InvalidState(_) => ErrorCategory::Logic,
359 Error::Timeout(_) => ErrorCategory::System,
360 Error::UnsupportedQuery(_) => ErrorCategory::Query,
361 }
362 }
363}
364
365#[derive(Debug, Clone, Copy, PartialEq, Eq)]
367pub enum ErrorCategory {
368 System,
370 Data,
372 Schema,
374 Query,
376 Configuration,
378 Storage,
380 Concurrency,
382 NotFound,
384 Conflict,
386 Logic,
388 Constraint,
390 Transaction,
392 Platform,
394 Internal,
396}
397
398impl fmt::Display for ErrorCategory {
399 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400 let name = match self {
401 ErrorCategory::System => "System",
402 ErrorCategory::Data => "Data",
403 ErrorCategory::Schema => "Schema",
404 ErrorCategory::Query => "Query",
405 ErrorCategory::Configuration => "Configuration",
406 ErrorCategory::Storage => "Storage",
407 ErrorCategory::Concurrency => "Concurrency",
408 ErrorCategory::NotFound => "NotFound",
409 ErrorCategory::Conflict => "Conflict",
410 ErrorCategory::Logic => "Logic",
411 ErrorCategory::Constraint => "Constraint",
412 ErrorCategory::Transaction => "Transaction",
413 ErrorCategory::Platform => "Platform",
414 ErrorCategory::Internal => "Internal",
415 };
416 write!(f, "{}", name)
417 }
418}
419
420impl From<bincode::Error> for Error {
422 fn from(err: bincode::Error) -> Self {
423 Error::Serialization {
424 message: err.to_string(),
425 source: Some(Box::new(err)),
426 }
427 }
428}
429
430impl From<serde_json::Error> for Error {
432 fn from(err: serde_json::Error) -> Self {
433 Error::Serialization {
434 message: err.to_string(),
435 source: Some(Box::new(err)),
436 }
437 }
438}
439
440impl<I> From<nom::Err<nom::error::Error<I>>> for Error
442where
443 I: std::fmt::Debug,
444{
445 fn from(err: nom::Err<nom::error::Error<I>>) -> Self {
446 Error::CqlParse(format!("Parse error: {:?}", err))
447 }
448}
449
450pub type ParseResult<I, O> = nom::IResult<I, O, Error>;
452
453#[derive(Debug, Clone)]
455pub struct ParseError {
456 pub message: String,
457}
458
459impl std::fmt::Display for ParseError {
460 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
461 write!(f, "{}", self.message)
462 }
463}
464
465impl std::error::Error for ParseError {}
466
467#[cfg(test)]
468mod tests {
469 use super::*;
470
471 #[test]
472 fn test_error_from_conversions() {
473 let io_err = std::io::Error::other("test error");
475 let bincode_err = bincode::Error::new(bincode::ErrorKind::Io(io_err));
476 let error = Error::from(bincode_err);
477 assert!(matches!(error, Error::Serialization { .. }));
478
479 let json_err = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
481 let error = Error::from(json_err);
482 assert!(matches!(error, Error::Serialization { .. }));
483
484 let nom_err = nom::Err::Error(nom::error::Error::new(
486 "test input",
487 nom::error::ErrorKind::Tag,
488 ));
489 let error = Error::from(nom_err);
490 assert!(matches!(error, Error::CqlParse(_)));
491 }
492
493 #[test]
494 fn test_parse_error_display() {
495 let parse_error = ParseError {
497 message: "test parse error".to_string(),
498 };
499 let display_str = format!("{}", parse_error);
500 assert_eq!(display_str, "test parse error");
501 }
502
503 #[test]
504 #[cfg(target_arch = "wasm32")]
505 fn test_wasm_error_creation() {
506 let err = Error::wasm("WASM error");
508 assert!(matches!(err, Error::Wasm(_)));
509 assert!(!err.is_recoverable());
510 assert_eq!(err.category(), ErrorCategory::Platform);
511 }
512
513 #[test]
514 fn test_new_error_types_coverage() {
515 let table_err = Error::Table("table error".to_string());
517 assert!(!table_err.is_recoverable());
518 assert_eq!(table_err.category(), ErrorCategory::Schema);
519 }
520
521 #[test]
522 fn test_error_creation() {
523 let err = Error::storage("test error");
524 assert!(matches!(err, Error::Storage(_)));
525 assert_eq!(err.to_string(), "Storage error: test error");
526 }
527
528 #[test]
529 fn test_error_categories() {
530 assert_eq!(Error::storage("test").category(), ErrorCategory::Storage);
531 assert_eq!(Error::schema("test").category(), ErrorCategory::Schema);
532 assert_eq!(Error::cql_parse("test").category(), ErrorCategory::Query);
533 }
534
535 #[test]
536 fn test_error_recoverability() {
537 assert!(Error::concurrency("test").is_recoverable());
538 assert!(!Error::corruption("test").is_recoverable());
539 assert!(!Error::schema("test").is_recoverable());
540 }
541
542 #[test]
543 fn test_all_error_constructors() {
544 let _ = Error::serialization("test");
546 let _ = Error::corruption("test");
547 let _ = Error::schema("test");
548 let _ = Error::cql_parse("test");
549 let _ = Error::invalid_format("test");
550 let _ = Error::unsupported_format("test");
551 let _ = Error::invalid_path("test");
552 let _ = Error::invalid_state("test");
553 let _ = Error::query_execution("test");
554 let _ = Error::type_conversion("test");
555 let _ = Error::configuration("test");
556 let _ = Error::storage("test");
557 let _ = Error::memory("test");
558 let _ = Error::concurrency("test");
559 let _ = Error::not_found("test");
560 let _ = Error::already_exists("test");
561 let _ = Error::invalid_operation("test");
562 let _ = Error::constraint_violation("test");
563 let _ = Error::transaction("test");
564 let _ = Error::index("test");
565 let _ = Error::compaction("test");
566 let _ = Error::internal("test");
567 let _ = Error::invalid_input("test");
568 let _ = Error::parse("test");
569 }
570
571 #[test]
572 fn test_all_error_categories() {
573 assert_eq!(Error::serialization("test").category(), ErrorCategory::Data);
575 assert_eq!(Error::corruption("test").category(), ErrorCategory::Data);
576 assert_eq!(Error::cql_parse("test").category(), ErrorCategory::Query);
577 assert_eq!(
578 Error::invalid_format("test").category(),
579 ErrorCategory::Data
580 );
581 assert_eq!(
582 Error::unsupported_format("test").category(),
583 ErrorCategory::Data
584 );
585 assert_eq!(
586 Error::invalid_path("test").category(),
587 ErrorCategory::System
588 );
589 assert_eq!(
590 Error::invalid_state("test").category(),
591 ErrorCategory::Logic
592 );
593 assert_eq!(
594 Error::query_execution("test").category(),
595 ErrorCategory::Query
596 );
597 assert_eq!(
598 Error::type_conversion("test").category(),
599 ErrorCategory::Data
600 );
601 assert_eq!(
602 Error::configuration("test").category(),
603 ErrorCategory::Configuration
604 );
605 assert_eq!(Error::memory("test").category(), ErrorCategory::System);
606 assert_eq!(
607 Error::concurrency("test").category(),
608 ErrorCategory::Concurrency
609 );
610 assert_eq!(Error::not_found("test").category(), ErrorCategory::NotFound);
611 assert_eq!(
612 Error::already_exists("test").category(),
613 ErrorCategory::Conflict
614 );
615 assert_eq!(
616 Error::invalid_operation("test").category(),
617 ErrorCategory::Logic
618 );
619 assert_eq!(
620 Error::constraint_violation("test").category(),
621 ErrorCategory::Constraint
622 );
623 assert_eq!(
624 Error::transaction("test").category(),
625 ErrorCategory::Transaction
626 );
627 assert_eq!(Error::index("test").category(), ErrorCategory::Storage);
628 assert_eq!(Error::compaction("test").category(), ErrorCategory::Storage);
629 assert_eq!(Error::internal("test").category(), ErrorCategory::Internal);
630 assert_eq!(Error::invalid_input("test").category(), ErrorCategory::Data);
631 assert_eq!(Error::parse("test").category(), ErrorCategory::Data);
632 }
633
634 #[test]
635 fn test_all_error_recoverability() {
636 assert!(Error::memory("test").is_recoverable());
638 assert!(Error::storage("test").is_recoverable());
639 assert!(Error::transaction("test").is_recoverable());
640 assert!(Error::index("test").is_recoverable());
641 assert!(Error::compaction("test").is_recoverable());
642
643 assert!(!Error::serialization("test").is_recoverable());
644 assert!(!Error::cql_parse("test").is_recoverable());
645 assert!(!Error::invalid_format("test").is_recoverable());
646 assert!(!Error::unsupported_format("test").is_recoverable());
647 assert!(!Error::invalid_path("test").is_recoverable());
648 assert!(!Error::invalid_state("test").is_recoverable());
649 assert!(!Error::query_execution("test").is_recoverable());
650 assert!(!Error::type_conversion("test").is_recoverable());
651 assert!(!Error::configuration("test").is_recoverable());
652 assert!(!Error::not_found("test").is_recoverable());
653 assert!(!Error::already_exists("test").is_recoverable());
654 assert!(!Error::invalid_operation("test").is_recoverable());
655 assert!(!Error::constraint_violation("test").is_recoverable());
656 assert!(!Error::internal("test").is_recoverable());
657 assert!(!Error::invalid_input("test").is_recoverable());
658 assert!(!Error::parse("test").is_recoverable());
659 }
660
661 #[test]
662 fn test_error_category_display() {
663 assert_eq!(ErrorCategory::System.to_string(), "System");
665 assert_eq!(ErrorCategory::Data.to_string(), "Data");
666 assert_eq!(ErrorCategory::Schema.to_string(), "Schema");
667 assert_eq!(ErrorCategory::Query.to_string(), "Query");
668 assert_eq!(ErrorCategory::Configuration.to_string(), "Configuration");
669 assert_eq!(ErrorCategory::Storage.to_string(), "Storage");
670 assert_eq!(ErrorCategory::Concurrency.to_string(), "Concurrency");
671 assert_eq!(ErrorCategory::NotFound.to_string(), "NotFound");
672 assert_eq!(ErrorCategory::Conflict.to_string(), "Conflict");
673 assert_eq!(ErrorCategory::Logic.to_string(), "Logic");
674 assert_eq!(ErrorCategory::Constraint.to_string(), "Constraint");
675 assert_eq!(ErrorCategory::Transaction.to_string(), "Transaction");
676 assert_eq!(ErrorCategory::Platform.to_string(), "Platform");
677 assert_eq!(ErrorCategory::Internal.to_string(), "Internal");
678 }
679
680 #[test]
681 fn test_error_from_io_error() {
682 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
684 let cqlite_err: Error = io_err.into();
685 assert!(matches!(cqlite_err, Error::Io(_)));
686 assert_eq!(cqlite_err.category(), ErrorCategory::System);
687 assert!(cqlite_err.is_recoverable());
688 }
689
690 #[test]
691 fn test_result_type_alias() {
692 let success: Result<i32> = Ok(42);
694 let failure: Result<i32> = Err(Error::storage("test error"));
695
696 assert!(success.is_ok());
697 if let Ok(value) = success {
698 assert_eq!(value, 42);
699 }
700 assert!(failure.is_err());
701 }
702}