librsigstopup 0.1.0

Super safe library untuk simulasi perhitungan top-up dengan JSON API, verbose logging, dan full trace
Documentation
use serde::{Deserialize, Serialize};
use thiserror::Error;
pub type Result<T> = std::result::Result<T, CalculationError>;
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum CalculationError {
    #[error("Validation error: {field} - {message}")]
    ValidationError { field: String, message: String },
    #[error("Invalid input: {0}")]
    InvalidInput(String),
    #[error("Calculation failed: {0}")]
    CalculationFailed(String),
    #[error("JSON parse error: {0}")]
    JsonParseError(String),
    #[error("Configuration error: {0}")]
    ConfigError(String),
    #[error("Internal error: {0}")]
    InternalError(String),
}
impl CalculationError {
    pub fn to_json(&self) -> String {
        serde_json::to_string_pretty(self).unwrap_or_default()
    }
    pub fn validation(field: &str, message: &str) -> Self {
        Self::ValidationError {
            field: field.to_string(),
            message: message.to_string(),
        }
    }
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationError {
    pub field: String,
    pub message: String,
}
impl ValidationError {
    pub fn new(field: &str, message: &str) -> Self {
        Self {
            field: field.to_string(),
            message: message.to_string(),
        }
    }
}
impl From<ValidationError> for CalculationError {
    fn from(err: ValidationError) -> Self {
        CalculationError::validation(&err.field, &err.message)
    }
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ApiError {
    pub success: bool,
    pub error: ApiErrorDetail,
    pub timestamp: String,
    pub request_id: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ApiErrorDetail {
    pub code: String,
    pub message: String,
    pub details: Option<serde_json::Value>,
}
impl From<CalculationError> for ApiError {
    fn from(err: CalculationError) -> Self {
        let (code, message) = match &err {
            CalculationError::ValidationError { .. } => ("VALIDATION_ERROR", err.to_string()),
            CalculationError::InvalidInput(_) => ("INVALID_INPUT", err.to_string()),
            CalculationError::CalculationFailed(_) => ("CALCULATION_FAILED", err.to_string()),
            CalculationError::JsonParseError(_) => ("JSON_PARSE_ERROR", err.to_string()),
            CalculationError::ConfigError(_) => ("CONFIG_ERROR", err.to_string()),
            CalculationError::InternalError(_) => ("INTERNAL_ERROR", err.to_string()),
        };
        Self {
            success: false,
            error: ApiErrorDetail {
                code: code.to_string(),
                message,
                details: serde_json::to_value(err).ok(),
            },
            timestamp: chrono::Utc::now().to_rfc3339(),
            request_id: None,
        }
    }
}