use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug, Clone)]
pub enum Error {
#[error("Missing required field: {0}")]
MissingField(String),
#[error("Invalid value for {field}: {message}")]
InvalidValue { field: String, message: String },
#[error("{entity_type} not found: {id}")]
NotFound { entity_type: String, id: String },
#[error("{entity_type} already exists: {id}")]
Duplicate { entity_type: String, id: String },
#[error("Invalid action {action} for {context}")]
InvalidAction { action: String, context: String },
#[error("Invalid state transition from {from} to {to}")]
InvalidStateTransition { from: String, to: String },
#[error("Insufficient quantity: required {required}, available {available}")]
InsufficientQuantity { required: String, available: String },
#[error("Unit mismatch: cannot operate on {unit1} and {unit2}")]
UnitMismatch { unit1: String, unit2: String },
#[error("Validation error: {0}")]
Validation(String),
#[error("Storage error: {0}")]
Storage(String),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("{0}")]
Custom(String),
}
impl Error {
pub fn missing_field(field: impl Into<String>) -> Self {
Error::MissingField(field.into())
}
pub fn invalid_value(field: impl Into<String>, message: impl Into<String>) -> Self {
Error::InvalidValue {
field: field.into(),
message: message.into(),
}
}
pub fn not_found(entity_type: impl Into<String>, id: impl Into<String>) -> Self {
Error::NotFound {
entity_type: entity_type.into(),
id: id.into(),
}
}
pub fn duplicate(entity_type: impl Into<String>, id: impl Into<String>) -> Self {
Error::Duplicate {
entity_type: entity_type.into(),
id: id.into(),
}
}
pub fn invalid_action(action: impl Into<String>, context: impl Into<String>) -> Self {
Error::InvalidAction {
action: action.into(),
context: context.into(),
}
}
pub fn validation(message: impl Into<String>) -> Self {
Error::Validation(message.into())
}
pub fn storage(message: impl Into<String>) -> Self {
Error::Storage(message.into())
}
pub fn custom(message: impl Into<String>) -> Self {
Error::Custom(message.into())
}
}
#[cfg(feature = "serde")]
impl From<serde_json::Error> for Error {
fn from(err: serde_json::Error) -> Self {
Error::Serialization(err.to_string())
}
}