use thiserror::Error;
#[derive(Error, Debug)]
pub enum CrdtError {
#[error("Filesystem error: {0}")]
FileSystem(String),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("Deserialization error: {0}")]
Deserialization(String),
#[error("CRDT encoding/decoding error: {0}")]
Encoding(String),
#[error("Document not found: {0}")]
DocumentNotFound(String),
#[error("Invalid entity type: {0}")]
InvalidEntityType(String),
#[error("Invalid document ID: {0}")]
InvalidDocumentId(String),
#[error("Conflict resolution failed: {0}")]
ConflictResolution(String),
#[error("State vector mismatch: expected {expected}, got {actual}")]
StateVectorMismatch { expected: String, actual: String },
#[error("Materialization failed for {entity_type}/{entity_id}: {reason}")]
MaterializationFailed {
entity_type: String,
entity_id: String,
reason: String,
},
#[error("Map operation failed on key '{key}': {reason}")]
MapOperation { key: String, reason: String },
#[error("Type mismatch for key '{key}': expected {expected}, got {actual}")]
TypeMismatch {
key: String,
expected: String,
actual: String,
},
#[error("Operation error: {0}")]
Operation(String),
}
pub type CrdtResult<T> = Result<T, CrdtError>;
impl CrdtError {
pub fn encoding_error(msg: impl Into<String>) -> Self {
Self::Encoding(msg.into())
}
pub fn materialization_failed(
entity_type: impl Into<String>,
entity_id: impl Into<String>,
reason: impl Into<String>,
) -> Self {
Self::MaterializationFailed {
entity_type: entity_type.into(),
entity_id: entity_id.into(),
reason: reason.into(),
}
}
pub fn map_operation(key: impl Into<String>, reason: impl Into<String>) -> Self {
Self::MapOperation {
key: key.into(),
reason: reason.into(),
}
}
pub fn type_mismatch(
key: impl Into<String>,
expected: impl Into<String>,
actual: impl Into<String>,
) -> Self {
Self::TypeMismatch {
key: key.into(),
expected: expected.into(),
actual: actual.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_display() {
let err = CrdtError::DocumentNotFound("doc-123".to_string());
assert_eq!(err.to_string(), "Document not found: doc-123");
let err = CrdtError::type_mismatch("status", "string", "number");
assert_eq!(
err.to_string(),
"Type mismatch for key 'status': expected string, got number"
);
}
#[test]
fn test_materialization_error() {
let err = CrdtError::materialization_failed("channel", "ch-1", "Validation failed");
assert_eq!(
err.to_string(),
"Materialization failed for channel/ch-1: Validation failed"
);
}
#[test]
fn test_filesystem_error() {
let err = CrdtError::FileSystem("Failed to write file".to_string());
assert_eq!(err.to_string(), "Filesystem error: Failed to write file");
}
}