use std::fmt; /// Storage engine error types. /// /// Replaces the stub `StorageError { message }` from Phase 1.1. /// All storage backends surface errors through this enum. #[derive(Debug)] pub enum StorageError { /// I/O error from the underlying filesystem or storage engine. Io(std::io::Error), /// Data corruption detected (checksum mismatch, invalid key encoding, etc.). Corruption { message: String }, /// The storage engine has been closed and cannot service requests. Closed, /// A batch write conflicted with a concurrent operation. BatchConflict, } impl fmt::Display for StorageError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Io(source) => write!(f, "I/O error: {source}"), Self::Corruption { message } => write!(f, "data corruption: {message}"), Self::Closed => f.write_str("storage closed"), Self::BatchConflict => f.write_str("batch conflict"), } } } impl std::error::Error for StorageError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Self::Io(source) => Some(source), _ => None, } } } impl From for StorageError { fn from(e: std::io::Error) -> Self { Self::Io(e) } } #[cfg(test)] mod tests { use super::*; #[test] fn display_io() { let e = StorageError::Io(std::io::Error::new( std::io::ErrorKind::NotFound, "file not found", )); assert!(e.to_string().contains("I/O error")); assert!(e.to_string().contains("file not found")); } #[test] fn display_corruption() { let e = StorageError::Corruption { message: "bad checksum".into(), }; assert_eq!(e.to_string(), "data corruption: bad checksum"); } #[test] fn display_closed() { assert_eq!(StorageError::Closed.to_string(), "storage closed"); } #[test] fn display_batch_conflict() { assert_eq!(StorageError::BatchConflict.to_string(), "batch conflict"); } #[test] fn from_io_error() { let io_err = std::io::Error::new(std::io::ErrorKind::Other, "disk full"); let storage_err: StorageError = io_err.into(); assert!(matches!(storage_err, StorageError::Io(_))); } #[test] fn source_io() { use std::error::Error; let e = StorageError::Io(std::io::Error::new(std::io::ErrorKind::Other, "test")); assert!(e.source().is_some()); } #[test] fn source_corruption_is_none() { use std::error::Error; let e = StorageError::Corruption { message: "test".into(), }; assert!(e.source().is_none()); } }