use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Error)]
pub enum CrowdError {
#[error(
"{model}: parameter `{param}` must be > 0, got {value} (zero/negative values \
produce NaN velocities within a few ticks)"
)]
NonPositiveParam {
model: &'static str,
param: &'static str,
value: f64,
},
#[error("{model}: parameter `{param}` must be >= 0, got {value}")]
NegativeParam {
model: &'static str,
param: &'static str,
value: f64,
},
#[error("{model}: parameter `{param}` must be >= 1, got 0")]
ZeroCount {
model: &'static str,
param: &'static str,
},
#[error(
"{model}: CFL violation — dt * max_accel = {product} m/s exceeds \
max_speed = {max_speed} m/s; reduce `dt` to at most {max_dt} s or \
raise `max_speed`"
)]
CflViolation {
model: &'static str,
product: f64,
max_speed: f64,
max_dt: f64,
},
#[error(
"{model}: dt must be a finite positive number, got {dt}; every \
step_* entry point assumes a real-time tick duration"
)]
InvalidDt {
model: &'static str,
dt: f64,
},
}
#[inline]
pub(crate) fn require_positive(
model: &'static str,
param: &'static str,
value: f64,
) -> Result<(), CrowdError> {
if value.is_finite() && value > 0.0 {
Ok(())
} else {
Err(CrowdError::NonPositiveParam {
model,
param,
value,
})
}
}
#[inline]
pub(crate) fn require_nonneg(
model: &'static str,
param: &'static str,
value: f64,
) -> Result<(), CrowdError> {
if value.is_finite() && value >= 0.0 {
Ok(())
} else {
Err(CrowdError::NegativeParam {
model,
param,
value,
})
}
}
#[inline]
pub(crate) fn require_count(
model: &'static str,
param: &'static str,
value: usize,
) -> Result<(), CrowdError> {
if value >= 1 {
Ok(())
} else {
Err(CrowdError::ZeroCount { model, param })
}
}
#[inline]
pub(crate) fn require_dt(model: &'static str, dt: f64) -> Result<(), CrowdError> {
if dt.is_finite() && dt > 0.0 {
Ok(())
} else {
Err(CrowdError::InvalidDt { model, dt })
}
}