1use crate::types::PageId;
2
3pub type Result<T> = std::result::Result<T, Error>;
4
5#[derive(Debug, thiserror::Error)]
6pub enum Error {
7 #[error("page {0} failed MAC verification: data has been tampered with")]
8 PageTampered(PageId),
9
10 #[error("incorrect passphrase or wrong key file")]
11 BadPassphrase,
12
13 #[error("database file is locked by another process")]
14 DatabaseLocked,
15
16 #[error("key file does not match data file (file_id mismatch)")]
17 KeyFileMismatch,
18
19 #[error("transaction requires more pages than buffer pool capacity ({capacity})")]
20 TransactionTooLarge { capacity: usize },
21
22 #[error("database file is corrupted: both commit slots are invalid")]
23 DatabaseCorrupted,
24
25 #[error("page checksum mismatch on page {0} (post-decrypt integrity failure)")]
26 ChecksumMismatch(PageId),
27
28 #[error("invalid page type {0} on page {1}")]
29 InvalidPageType(u16, PageId),
30
31 #[error("key too large: {size} bytes (max {max})")]
32 KeyTooLarge { size: usize, max: usize },
33
34 #[error("value too large: {size} bytes (max {max})")]
35 ValueTooLarge { size: usize, max: usize },
36
37 #[error("invalid magic number: expected 0x{expected:08X}, found 0x{found:08X}")]
38 InvalidMagic { expected: u32, found: u32 },
39
40 #[error("unsupported format version: {0}")]
41 UnsupportedVersion(u32),
42
43 #[error("key file integrity check failed (HMAC mismatch)")]
44 KeyFileIntegrity,
45
46 #[error("invalid key file magic")]
47 InvalidKeyFileMagic,
48
49 #[error("key unwrap failed (AES-KW integrity check)")]
50 KeyUnwrapFailed,
51
52 #[error("no write transaction active")]
53 NoWriteTransaction,
54
55 #[error("a write transaction is already active")]
56 WriteTransactionActive,
57
58 #[error("page {0} is out of bounds (beyond high water mark)")]
59 PageOutOfBounds(PageId),
60
61 #[error("buffer pool is full and all pages are pinned")]
62 BufferPoolFull,
63
64 #[error("unsupported cipher: {0}")]
65 UnsupportedCipher(u8),
66
67 #[error("unsupported KDF algorithm: {0}")]
68 UnsupportedKdf(u8),
69
70 #[error("FIPS mode violation: {0}")]
71 FipsViolation(String),
72
73 #[error("table not found: {0}")]
74 TableNotFound(String),
75
76 #[error("table already exists: {0}")]
77 TableAlreadyExists(String),
78
79 #[error("passphrase is required")]
80 PassphraseRequired,
81
82 #[error("sync error: {0}")]
83 Sync(String),
84
85 #[error("I/O error: {0}")]
86 Io(#[from] std::io::Error),
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn error_display() {
95 let e = Error::PageTampered(PageId(42));
96 assert!(format!("{e}").contains("page:42"));
97
98 let e = Error::TransactionTooLarge { capacity: 256 };
99 assert!(format!("{e}").contains("256"));
100 }
101
102 #[test]
103 fn error_from_io() {
104 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
105 let e: Error = io_err.into();
106 assert!(matches!(e, Error::Io(_)));
107 }
108}