use std::fmt;
use std::path::PathBuf;
#[derive(Debug)]
#[non_exhaustive]
pub enum JournalError {
Io {
message: String,
path: Option<PathBuf>,
},
CorruptEntry {
sequence: u64,
expected_crc: u32,
actual_crc: u32,
},
DeserializationError {
sequence: u64,
message: String,
},
SerializationError {
message: String,
},
EntryTooLarge {
entry_bytes: usize,
segment_size: usize,
},
InvalidDirectory {
path: PathBuf,
},
MutexPoisoned,
SequenceNotFound {
sequence: u64,
},
InvalidEntryHeader {
offset: usize,
message: String,
},
CounterOverflow {
counter: &'static str,
},
}
impl fmt::Display for JournalError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
JournalError::Io { message, path } => {
if let Some(p) = path {
write!(f, "journal I/O error at {}: {message}", p.display())
} else {
write!(f, "journal I/O error: {message}")
}
}
JournalError::CorruptEntry {
sequence,
expected_crc,
actual_crc,
} => {
write!(
f,
"corrupt journal entry at sequence {sequence}: \
expected CRC {expected_crc:#010x}, got {actual_crc:#010x}"
)
}
JournalError::DeserializationError { sequence, message } => {
write!(
f,
"journal deserialization error at sequence {sequence}: {message}"
)
}
JournalError::SerializationError { message } => {
write!(f, "journal serialization error: {message}")
}
JournalError::EntryTooLarge {
entry_bytes,
segment_size,
} => {
write!(
f,
"journal entry too large: {entry_bytes} bytes exceeds \
segment size {segment_size} bytes"
)
}
JournalError::InvalidDirectory { path } => {
write!(f, "invalid journal directory: {}", path.display())
}
JournalError::MutexPoisoned => {
write!(f, "journal internal mutex poisoned")
}
JournalError::SequenceNotFound { sequence } => {
write!(f, "sequence {sequence} not found in journal")
}
JournalError::InvalidEntryHeader { offset, message } => {
write!(
f,
"invalid journal entry header at offset {offset}: {message}"
)
}
JournalError::CounterOverflow { counter } => {
write!(f, "journal counter overflowed: {counter}")
}
}
}
}
impl std::error::Error for JournalError {}
impl From<std::io::Error> for JournalError {
#[cold]
fn from(err: std::io::Error) -> Self {
JournalError::Io {
message: err.to_string(),
path: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_counter_overflow_display() {
let err = JournalError::CounterOverflow {
counter: "archived segment count",
};
let msg = err.to_string();
assert!(msg.contains("counter overflowed"));
assert!(msg.contains("archived segment count"));
}
}