Skip to main content

poolsim_core/
error.rs

1//! Error types and helpers for the public `poolsim-core` API.
2//!
3//! `PoolsimError` is designed to work for both library callers and service
4//! adapters:
5//!
6//! - stable machine-readable codes via [`PoolsimError::code`]
7//! - optional structured error details via [`PoolsimError::details`]
8//! - human-readable messages via `Display`
9//!
10//! This makes the same error type suitable for direct Rust usage, CLI
11//! rendering, and HTTP/WebSocket translation in `poolsim-web`.
12
13use serde_json::Value;
14use thiserror::Error;
15
16/// Error type returned by `poolsim-core` public APIs.
17#[derive(Debug, Error)]
18pub enum PoolsimError {
19    /// Invalid input payload or violated input constraints.
20    #[error("{message}")]
21    InvalidInput {
22        /// Stable machine-readable error code.
23        code: &'static str,
24        /// Human-readable error message.
25        message: String,
26        /// Optional structured details for API responses.
27        details: Option<Value>,
28    },
29
30    /// System is saturated (`rho >= 1.0`) for the requested configuration.
31    #[error("system saturated at rho={rho:.4}")]
32    Saturated {
33        /// Utilization ratio (`rho`) at failure time.
34        rho: f64,
35    },
36
37    /// Distribution fitting/sampling failure.
38    #[error("distribution error: {0}")]
39    Distribution(String),
40
41    /// Simulation runtime failure.
42    #[error("simulation error: {0}")]
43    Simulation(String),
44}
45
46impl PoolsimError {
47    /// Creates a standardized invalid-input error.
48    pub fn invalid_input(code: &'static str, message: impl Into<String>, details: Option<Value>) -> Self {
49        Self::InvalidInput {
50            code,
51            message: message.into(),
52            details,
53        }
54    }
55
56    /// Returns the stable machine-readable error code.
57    pub fn code(&self) -> &'static str {
58        match self {
59            Self::InvalidInput { code, .. } => code,
60            Self::Saturated { .. } => "SATURATED",
61            Self::Distribution(_) => "DISTRIBUTION_ERROR",
62            Self::Simulation(_) => "SIMULATION_ERROR",
63        }
64    }
65
66    /// Returns optional structured details associated with this error.
67    pub fn details(&self) -> Option<&Value> {
68        match self {
69            Self::InvalidInput { details, .. } => details.as_ref(),
70            _ => None,
71        }
72    }
73}