1use std::{error, fmt, fmt::Write, io, path::PathBuf};
2
3#[derive(Debug)]
5pub enum Error {
6 FileOpen(PathBuf, io::Error),
8 Mmap(io::Error),
10 PathNotDir,
12 RecordExists(Vec<u8>),
14 DataFileDamaged,
16 SeqNoIndexDamaged,
18 Extend(io::Error),
20 Flush(io::Error),
22 Metadata(io::Error),
24 Protect(io::Error),
26}
27
28impl error::Error for Error {
29 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
30 match self {
31 Error::FileOpen(_, source) => Some(source),
32 Error::Mmap(source) => Some(source),
33 Error::PathNotDir => None,
34 Error::RecordExists(_) => None,
35 Error::DataFileDamaged => None,
36 Error::SeqNoIndexDamaged => None,
37 Error::Extend(source) => Some(source),
38 Error::Flush(source) => Some(source),
39 Error::Metadata(source) => Some(source),
40 Error::Protect(source) => Some(source),
41 }
42 }
43}
44
45impl fmt::Display for Error {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 match self {
48 Error::FileOpen(path, _) => write!(f, "failed to open file `{}`", path.display()),
49 Error::Mmap(_) => write!(f, "memory map failed"),
50 Error::PathNotDir => write!(
51 f,
52 "database path already exists and does not point to a directory"
53 ),
54 Error::RecordExists(id) => write!(f, "a record with id {} already exists", hex(&id)),
55 Error::DataFileDamaged => write!(f, "data file looks damaged"),
56 Error::SeqNoIndexDamaged => write!(f, "sequential number index file looks damaged"),
57 Error::Extend(_) => write!(f, "failed to extend a database file"),
58 Error::Flush(_) => write!(f, "failed to flush database records to disk"),
59 Error::Metadata(_) => write!(f, "failed to get file metadata"),
60 Error::Protect(_) => write!(f, "failed to make a memory mapping page immutable"),
61 }
62 }
63}
64
65fn hex(bytes: &[u8]) -> String {
66 let mut s = String::with_capacity(bytes.len() * 2);
67 for byte in bytes {
68 write!(&mut s, "{:2x}", byte).unwrap();
69 }
70 s
71}