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}