use thiserror::Error;
use std::io;
use uuid::Uuid;
#[derive(Error, Debug)]
pub enum StorageError {
#[error("I/O error: {0}")]
Io(#[from] io::Error),
#[error("Data integrity error: CRC mismatch at offset {offset}, expected {expected:x}, got {actual:x}")]
CrcMismatch {
offset: u64,
expected: u32,
actual: u32,
},
#[error("Invalid data format: {message}")]
InvalidFormat { message: String },
#[error("Segment not found: {segment_id}")]
SegmentNotFound { segment_id: Uuid },
#[error("Offset out of range: {offset} is beyond available data")]
OffsetOutOfRange { offset: u64 },
#[error("Configuration error: {message}")]
Configuration { message: String },
#[error("Insufficient disk space: need {required} bytes, available {available} bytes")]
InsufficientSpace {
required: u64,
available: u64,
},
#[error("Synchronization error: {message}")]
Synchronization { message: String },
#[error("Serialization error: {0}")]
Serialization(#[from] bincode::Error),
#[error("Internal error: {message}")]
Internal { message: String },
}
impl StorageError {
pub fn configuration(message: impl Into<String>) -> Self {
Self::Configuration {
message: message.into(),
}
}
pub fn invalid_format(message: impl Into<String>) -> Self {
Self::InvalidFormat {
message: message.into(),
}
}
pub fn internal(message: impl Into<String>) -> Self {
Self::Internal {
message: message.into(),
}
}
pub fn synchronization(message: impl Into<String>) -> Self {
Self::Synchronization {
message: message.into(),
}
}
pub fn is_retryable(&self) -> bool {
match self {
Self::Io(_) => true,
Self::InsufficientSpace { .. } => false,
Self::CrcMismatch { .. } => false,
Self::InvalidFormat { .. } => false,
Self::SegmentNotFound { .. } => false,
Self::OffsetOutOfRange { .. } => false,
Self::Configuration { .. } => false,
Self::Synchronization { .. } => true,
Self::Serialization(_) => false,
Self::Internal { .. } => false,
}
}
pub fn severity(&self) -> ErrorSeverity {
match self {
Self::CrcMismatch { .. } => ErrorSeverity::High,
Self::InsufficientSpace { .. } => ErrorSeverity::High,
Self::Internal { .. } => ErrorSeverity::High,
Self::InvalidFormat { .. } => ErrorSeverity::Medium,
Self::SegmentNotFound { .. } => ErrorSeverity::Medium,
Self::Configuration { .. } => ErrorSeverity::Medium,
Self::Io(_) => ErrorSeverity::Low,
Self::OffsetOutOfRange { .. } => ErrorSeverity::Low,
Self::Synchronization { .. } => ErrorSeverity::Low,
Self::Serialization(_) => ErrorSeverity::Low,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorSeverity {
High,
Medium,
Low,
}
pub type StorageResult<T> = Result<T, StorageError>;