use crate::hydraulics::HydraulicError;
use crate::quality::QualityError;
use crate::ValidationError;
pub use crate::io::{LinkQuantity, NodeQuantity, SimWarning, WarningKind};
#[derive(Debug, Clone)]
pub enum SessionError {
ValidationFailed(Vec<ValidationError>),
UnknownId(String),
NoSnapshotAtTime {
requested_t: f64,
},
InvalidPhase {
expected: String,
actual: String,
},
HydraulicSolve(HydraulicError),
QualityEngine(QualityError),
}
impl std::fmt::Display for SessionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ValidationFailed(errs) => {
write!(f, "validation failed: {} error(s)", errs.len())
}
Self::UnknownId(id) => write!(f, "unknown object ID: '{id}'"),
Self::NoSnapshotAtTime { requested_t } => {
write!(f, "no result snapshot at t={requested_t}")
}
Self::InvalidPhase { expected, actual } => {
write!(f, "invalid phase: expected {expected}, actual {actual}")
}
Self::HydraulicSolve(e) => write!(f, "hydraulic solver error: {e}"),
Self::QualityEngine(e) => write!(f, "quality engine error: {e:?}"),
}
}
}
impl std::error::Error for SessionError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeProperty {
Elevation,
InitialQuality,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LinkProperty {
Roughness,
InitialStatus,
InitialSetting,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum Phase {
Created,
Loaded,
HydraulicsDone,
QualityDone,
}
impl Phase {
pub(super) fn name(self) -> &'static str {
match self {
Phase::Created => "Created",
Phase::Loaded => "Loaded",
Phase::HydraulicsDone => "HydraulicsDone",
Phase::QualityDone => "QualityDone",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::hydraulics::HydraulicError;
use crate::quality::QualityError;
#[test]
fn phase_name_all_variants() {
assert_eq!(Phase::Created.name(), "Created");
assert_eq!(Phase::Loaded.name(), "Loaded");
assert_eq!(Phase::HydraulicsDone.name(), "HydraulicsDone");
assert_eq!(Phase::QualityDone.name(), "QualityDone");
}
#[test]
fn session_error_display_validation_failed() {
let msg = SessionError::ValidationFailed(vec![]).to_string();
assert_eq!(msg, "validation failed: 0 error(s)");
}
#[test]
fn session_error_display_unknown_id() {
let msg = SessionError::UnknownId("ABC".into()).to_string();
assert_eq!(msg, "unknown object ID: 'ABC'");
}
#[test]
fn session_error_display_no_snapshot_at_time() {
let msg = SessionError::NoSnapshotAtTime { requested_t: 42.0 }.to_string();
assert!(msg.contains("42"), "got: {msg}");
}
#[test]
fn session_error_display_invalid_phase() {
let msg = SessionError::InvalidPhase {
expected: "Loaded".into(),
actual: "Created".into(),
}
.to_string();
assert!(
msg.contains("Loaded") && msg.contains("Created"),
"got: {msg}"
);
}
#[test]
fn session_error_display_hydraulic_solve() {
let msg = SessionError::HydraulicSolve(HydraulicError::NotConverged).to_string();
assert!(msg.contains("hydraulic solver"), "got: {msg}");
}
#[test]
fn session_error_display_quality_engine() {
let msg = SessionError::QualityEngine(QualityError::ModeNone).to_string();
assert!(msg.contains("quality engine"), "got: {msg}");
}
}