hydra_engine_wds/simulation/
types.rs1use crate::hydraulics::HydraulicError;
2use crate::quality::QualityError;
3use crate::ValidationError;
4
5pub use crate::io::{LinkQuantity, NodeQuantity, SimWarning, WarningKind};
9
10#[derive(Debug, Clone)]
14pub enum SessionError {
15 ValidationFailed(Vec<ValidationError>),
18 UnknownId(String),
20 NoSnapshotAtTime {
22 requested_t: f64,
24 },
25 InvalidPhase {
27 expected: String,
29 actual: String,
31 },
32 HydraulicSolve(HydraulicError),
35 QualityEngine(QualityError),
37}
38
39impl std::fmt::Display for SessionError {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 match self {
42 Self::ValidationFailed(errs) => {
43 write!(f, "validation failed: {} error(s)", errs.len())
44 }
45 Self::UnknownId(id) => write!(f, "unknown object ID: '{id}'"),
46 Self::NoSnapshotAtTime { requested_t } => {
47 write!(f, "no result snapshot at t={requested_t}")
48 }
49 Self::InvalidPhase { expected, actual } => {
50 write!(f, "invalid phase: expected {expected}, actual {actual}")
51 }
52 Self::HydraulicSolve(e) => write!(f, "hydraulic solver error: {e}"),
53 Self::QualityEngine(e) => write!(f, "quality engine error: {e:?}"),
54 }
55 }
56}
57
58impl std::error::Error for SessionError {}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum NodeProperty {
65 Elevation,
67 InitialQuality,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum LinkProperty {
74 Roughness,
76 InitialStatus,
78 InitialSetting,
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub(super) enum Phase {
86 Created,
88 Loaded,
90 HydraulicsDone,
92 QualityDone,
94}
95
96impl Phase {
97 pub(super) fn name(self) -> &'static str {
98 match self {
99 Phase::Created => "Created",
100 Phase::Loaded => "Loaded",
101 Phase::HydraulicsDone => "HydraulicsDone",
102 Phase::QualityDone => "QualityDone",
103 }
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110 use crate::hydraulics::HydraulicError;
111 use crate::quality::QualityError;
112
113 #[test]
114 fn phase_name_all_variants() {
115 assert_eq!(Phase::Created.name(), "Created");
116 assert_eq!(Phase::Loaded.name(), "Loaded");
117 assert_eq!(Phase::HydraulicsDone.name(), "HydraulicsDone");
118 assert_eq!(Phase::QualityDone.name(), "QualityDone");
119 }
120
121 #[test]
122 fn session_error_display_validation_failed() {
123 let msg = SessionError::ValidationFailed(vec![]).to_string();
124 assert_eq!(msg, "validation failed: 0 error(s)");
125 }
126
127 #[test]
128 fn session_error_display_unknown_id() {
129 let msg = SessionError::UnknownId("ABC".into()).to_string();
130 assert_eq!(msg, "unknown object ID: 'ABC'");
131 }
132
133 #[test]
134 fn session_error_display_no_snapshot_at_time() {
135 let msg = SessionError::NoSnapshotAtTime { requested_t: 42.0 }.to_string();
136 assert!(msg.contains("42"), "got: {msg}");
137 }
138
139 #[test]
140 fn session_error_display_invalid_phase() {
141 let msg = SessionError::InvalidPhase {
142 expected: "Loaded".into(),
143 actual: "Created".into(),
144 }
145 .to_string();
146 assert!(
147 msg.contains("Loaded") && msg.contains("Created"),
148 "got: {msg}"
149 );
150 }
151
152 #[test]
153 fn session_error_display_hydraulic_solve() {
154 let msg = SessionError::HydraulicSolve(HydraulicError::NotConverged).to_string();
155 assert!(msg.contains("hydraulic solver"), "got: {msg}");
156 }
157
158 #[test]
159 fn session_error_display_quality_engine() {
160 let msg = SessionError::QualityEngine(QualityError::ModeNone).to_string();
161 assert!(msg.contains("quality engine"), "got: {msg}");
162 }
163}