1use std::fmt;
2
3#[derive(Debug)]
5pub enum EdgestoreError {
6 Io(std::io::Error),
8 Checksum {
10 expected: u32,
12 got: u32,
14 },
15 CorruptRecord(String),
17 CorruptKey,
19 WalFull,
21 WriterBusy,
23 InvalidOperation(String),
25 NamespaceTooLong {
27 len: usize,
29 max: usize,
31 },
32 KeyNotFound,
34 FormatVersion {
36 expected: u8,
38 got: u8,
40 },
41 SegmentCorrupt(String),
43 ManifestCorrupt(String),
45 CompactionError(String),
47 ReplicationError(String),
49 DimensionMismatch {
51 expected: usize,
53 actual: usize,
55 },
56 CorruptData(String),
58}
59
60impl fmt::Display for EdgestoreError {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 match self {
63 EdgestoreError::Io(e) => write!(f, "I/O error: {}", e),
64 EdgestoreError::Checksum { expected, got } => {
65 write!(f, "CRC32C mismatch: expected {:#010x}, got {:#010x}", expected, got)
66 }
67 EdgestoreError::CorruptRecord(msg) => write!(f, "corrupt WAL record: {}", msg),
68 EdgestoreError::CorruptKey => write!(f, "corrupt key encoding"),
69 EdgestoreError::WalFull => write!(f, "WAL rotation threshold reached"),
70 EdgestoreError::WriterBusy => write!(f, "another writer holds the database lock"),
71 EdgestoreError::InvalidOperation(msg) => write!(f, "invalid operation: {}", msg),
72 EdgestoreError::NamespaceTooLong { len, max } => {
73 write!(f, "namespace length {} exceeds maximum {}", len, max)
74 }
75 EdgestoreError::KeyNotFound => write!(f, "key not found"),
76 EdgestoreError::FormatVersion { expected, got } => {
77 write!(f, "WAL format version mismatch: expected {}, got {}", expected, got)
78 }
79 EdgestoreError::SegmentCorrupt(msg) => write!(f, "segment corrupt: {}", msg),
80 EdgestoreError::ManifestCorrupt(msg) => write!(f, "manifest corrupt: {}", msg),
81 EdgestoreError::CompactionError(msg) => write!(f, "compaction error: {}", msg),
82 EdgestoreError::ReplicationError(msg) => write!(f, "replication error: {}", msg),
83 EdgestoreError::DimensionMismatch { expected, actual } => {
84 write!(f, "dimension mismatch: expected {} bytes, got {}", expected, actual)
85 }
86 EdgestoreError::CorruptData(msg) => write!(f, "corrupt data: {}", msg),
87 }
88 }
89}
90
91impl std::error::Error for EdgestoreError {}
92
93impl From<std::io::Error> for EdgestoreError {
94 fn from(e: std::io::Error) -> Self {
95 EdgestoreError::Io(e)
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[test]
104 fn test_display_variants() {
105 let cases: &[(&str, EdgestoreError)] = &[
106 ("corrupt WAL record: bad data", EdgestoreError::CorruptRecord("bad data".to_string())),
107 ("corrupt key encoding", EdgestoreError::CorruptKey),
108 ("WAL rotation threshold reached", EdgestoreError::WalFull),
109 ("another writer holds the database lock", EdgestoreError::WriterBusy),
110 ("invalid operation: not active", EdgestoreError::InvalidOperation("not active".to_string())),
111 ("namespace length 70000 exceeds maximum 65535", EdgestoreError::NamespaceTooLong { len: 70000, max: 65535 }),
112 ("key not found", EdgestoreError::KeyNotFound),
113 ("WAL format version mismatch: expected 1, got 2", EdgestoreError::FormatVersion { expected: 1, got: 2 }),
114 ("segment corrupt: bad block", EdgestoreError::SegmentCorrupt("bad block".to_string())),
115 ("manifest corrupt: truncated", EdgestoreError::ManifestCorrupt("truncated".to_string())),
116 ("compaction error: oops", EdgestoreError::CompactionError("oops".to_string())),
117 ];
118
119 for (expected, err) in cases {
120 assert_eq!(format!("{}", err), *expected, "Display mismatch for {:?}", err);
121 }
122 }
123
124 #[test]
125 fn test_io_from_conversion() {
126 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file gone");
127 let edge_err = EdgestoreError::from(io_err);
128 assert!(matches!(edge_err, EdgestoreError::Io(_)));
129 }
130}