use std::io;
#[derive(Debug, thiserror::Error)]
pub enum CheckpointError {
#[error("Serialization failed: {0}")]
Serialize(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("Deserialization failed: {0}")]
Deserialize(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("Schema migration failed: from version {from} to {to}: {reason}")]
SchemaMigration {
from: u32,
to: u32,
reason: String,
},
#[error("Storage error: {0}")]
Storage(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("Database error: {0}")]
Database(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("Serialization error: {0}")]
Serialization(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("Checkpoint not found: thread={thread_id}, id={checkpoint_id}")]
NotFound {
thread_id: String,
checkpoint_id: String,
},
#[error("Connection pool exhausted")]
PoolExhausted,
}
impl From<serde_json::Error> for CheckpointError {
fn from(err: serde_json::Error) -> Self {
Self::Serialize(Box::new(err))
}
}
impl From<io::Error> for CheckpointError {
fn from(err: io::Error) -> Self {
Self::Storage(Box::new(err))
}
}
impl CheckpointError {
#[must_use]
pub fn serialize_msg(msg: String) -> Self {
Self::Serialize(Box::new(StringError(msg)))
}
#[must_use]
pub fn deserialize_msg(msg: String) -> Self {
Self::Deserialize(Box::new(StringError(msg)))
}
#[must_use]
pub fn storage_msg(msg: String) -> Self {
Self::Storage(Box::new(StringError(msg)))
}
#[must_use]
pub fn database_msg(msg: String) -> Self {
Self::Database(Box::new(StringError(msg)))
}
}
struct StringError(String);
impl std::fmt::Debug for StringError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::fmt::Display for StringError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::error::Error for StringError {}