carapace_wasm/input_v1/decode/
mod.rs1mod elements_2d;
16mod elements_3d;
17mod shared;
18mod stages;
19
20use super::error::DecodeError;
21use super::session::Session;
22use super::CarapaceInputV1;
23
24pub fn decode(input: CarapaceInputV1) -> Result<Session, DecodeError> {
25 let check = |series: &super::tables::TimeSeriesSpec| -> Result<(), DecodeError> {
27 use super::tables::TimeSeriesSpec;
28 if let TimeSeriesSpec::Path { times, factors }
29 | TimeSeriesSpec::BoundedPath { times, factors, .. } = series
30 {
31 if times.is_empty()
32 || times.len() != factors.len()
33 || times.iter().any(|t| !t.is_finite())
34 || factors.iter().any(|v| !v.is_finite())
35 || times.windows(2).any(|w| w[1] <= w[0])
36 {
37 return Err(DecodeError::InvalidAnalysisOption {
38 stage: "timeSeries".into(),
39 field: "path",
40 });
41 }
42 }
43 Ok(())
44 };
45 for series in &input.load_patterns.series {
46 check(series)?;
47 }
48 for stage in &input.sequence.stages {
49 if let super::sequence::StageSpec::Transient {
50 ground_motions,
51 damping,
52 steps,
53 ..
54 } = stage
55 {
56 if *steps == 0
57 || !damping.alpha_m.is_finite()
58 || !damping.beta_k.is_finite()
59 || damping.alpha_m < 0.0
60 || damping.beta_k < 0.0
61 || damping.modal_anchors.is_some_and(|a| {
62 a.mode1 == 0
63 || a.mode2 == 0
64 || !a.ratio.is_finite()
65 || !(0.0..=1.0).contains(&a.ratio)
66 })
67 {
68 return Err(DecodeError::InvalidAnalysisOption {
69 stage: stage.id().into(),
70 field: "damping/steps",
71 });
72 }
73 for motion in ground_motions {
74 check(&motion.series)?;
75 if !motion.scale_factor.is_finite() {
76 return Err(DecodeError::InvalidAnalysisOption {
77 stage: stage.id().into(),
78 field: "groundMotion.scaleFactor",
79 });
80 }
81 }
82 }
83 }
84 match input.header.ndm {
85 2 => elements_2d::decode(input).map(Session::D2),
86 3 => elements_3d::decode(input).map(Session::D3),
87 got => Err(DecodeError::UnsupportedNdm { got }),
88 }
89}